diff --git a/config/boards/radxa-cubie-a5e.csc b/config/boards/radxa-cubie-a5e.csc index 27f82ff0b..aebd76142 100644 --- a/config/boards/radxa-cubie-a5e.csc +++ b/config/boards/radxa-cubie-a5e.csc @@ -14,9 +14,9 @@ BOOTSTART="1" BOOTSIZE="512" ROOTSTART="513" -#function post_family_tweaks__radxa_cubie-a5e() { -# display_alert "Applying wifi firmware" -# pushd "$SDCARD/lib/firmware" -# ln -s "aic8800/SDIO/aic8800D80" "aic8800_sdio" # use armbian-firmware -# popd -#} +function post_family_tweaks__radxa_cubie-a5e() { + display_alert "Applying wifi firmware" + pushd "$SDCARD/lib/firmware" + ln -s "aic8800/SDIO/aic8800D80" "aic8800_sdio" # use armbian-firmware + popd +} diff --git a/config/kernel/linux-sun55iw3-dev.config b/config/kernel/linux-sun55iw3-dev.config index 61c70ff82..9508912ad 100644 --- a/config/kernel/linux-sun55iw3-dev.config +++ b/config/kernel/linux-sun55iw3-dev.config @@ -114,7 +114,6 @@ CONFIG_PREEMPT_COUNT=y CONFIG_PREEMPTION=y # CONFIG_PREEMPT_DYNAMIC is not set # CONFIG_SCHED_CORE is not set -# CONFIG_SCHED_CLASS_EXT is not set # # CPU/Task time and stats accounting @@ -1447,7 +1446,12 @@ CONFIG_NET_FLOW_LIMIT=y # end of Networking options # CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m +CONFIG_CAN_GW=m +# CONFIG_CAN_J1939 is not set +# CONFIG_CAN_ISOTP is not set CONFIG_BT=m CONFIG_BT_BREDR=y CONFIG_BT_RFCOMM=m @@ -2201,7 +2205,24 @@ CONFIG_ETHERNET=y # CONFIG_NET_VENDOR_AGERE is not set # CONFIG_NET_VENDOR_ALACRITECH is not set CONFIG_NET_VENDOR_ALLWINNER=y -CONFIG_SUN4I_EMAC=m +# CONFIG_SUN4I_EMAC is not set + +# +# Stmmac Drivers +# +CONFIG_SUNXI55I_GMAC200=m +CONFIG_SUNXI55I_STMMAC=m +# CONFIG_SUNXI55I_STMMAC_UIO is not set +# end of Stmmac Drivers + +# +# Gmac Drivers +# +CONFIG_SUNXI55I_GMAC=m +CONFIG_SUNXI55I_GMAC_MDIO=m +# CONFIG_SUNXI55I_GMAC_METADATA is not set +# end of Gmac Drivers + # CONFIG_NET_VENDOR_ALTEON is not set # CONFIG_ALTERA_TSE is not set # CONFIG_NET_VENDOR_AMAZON is not set @@ -2370,6 +2391,7 @@ CONFIG_REALTEK_PHY=y CONFIG_REALTEK_PHY_HWMON=y # CONFIG_RENESAS_PHY is not set CONFIG_ROCKCHIP_PHY=y +CONFIG_MAXIO_PHY=m CONFIG_SMSC_PHY=y # CONFIG_STE10XP is not set # CONFIG_TERANETICS_PHY is not set @@ -2384,6 +2406,53 @@ CONFIG_SMSC_PHY=y # CONFIG_XILINX_GMII2RGMII is not set # CONFIG_MICREL_KS8995MA is not set # CONFIG_PSE_CONTROLLER is not set +CONFIG_CAN_DEV=m +# CONFIG_CAN_VCAN is not set +# CONFIG_CAN_VXCAN is not set +CONFIG_CAN_NETLINK=y +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_RX_OFFLOAD=y +# CONFIG_CAN_CAN327 is not set +# CONFIG_CAN_FLEXCAN is not set +# CONFIG_CAN_GRCAN is not set +# CONFIG_CAN_KVASER_PCIEFD is not set +# CONFIG_CAN_SLCAN is not set +# CONFIG_CAN_XILINXCAN is not set +# CONFIG_CAN_C_CAN is not set +# CONFIG_CAN_CC770 is not set +# CONFIG_CAN_CTUCANFD_PCI is not set +# CONFIG_CAN_CTUCANFD_PLATFORM is not set +# CONFIG_CAN_ESD_402_PCI is not set +# CONFIG_CAN_IFI_CANFD is not set +# CONFIG_CAN_M_CAN is not set +# CONFIG_CAN_PEAK_PCIEFD is not set +# CONFIG_CAN_SJA1000 is not set +# CONFIG_CAN_SOFTING is not set + +# +# CAN SPI interfaces +# +# CONFIG_CAN_HI311X is not set +# CONFIG_CAN_MCP251X is not set +# CONFIG_CAN_MCP251XFD is not set +# end of CAN SPI interfaces + +# +# CAN USB interfaces +# +# CONFIG_CAN_8DEV_USB is not set +# CONFIG_CAN_EMS_USB is not set +# CONFIG_CAN_ESD_USB is not set +# CONFIG_CAN_ETAS_ES58X is not set +# CONFIG_CAN_F81604 is not set +CONFIG_CAN_GS_USB=m +# CONFIG_CAN_KVASER_USB is not set +# CONFIG_CAN_MCBA_USB is not set +# CONFIG_CAN_PEAK_USB is not set +# CONFIG_CAN_UCAN is not set +# end of CAN USB interfaces + +# CONFIG_CAN_DEBUG_DEVICES is not set CONFIG_MDIO_DEVICE=y CONFIG_MDIO_BUS=y CONFIG_FWNODE_MDIO=y @@ -2710,8 +2779,12 @@ CONFIG_WLAN_VENDOR_ZYDAS=y CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set # CONFIG_WLAN_VENDOR_QUANTENNA is not set +CONFIG_AIC_SDIO_WLAN_SUPPORT=y +CONFIG_AIC_FW_PATH="/lib/firmware/aic8800_sdio" +CONFIG_AIC8800_WLAN_SUPPORT=m +CONFIG_AIC8800_BTLPM_SUPPORT=m CONFIG_MAC80211_HWSIM=m -# CONFIG_VIRT_WIFI is not set +CONFIG_VIRT_WIFI=m # CONFIG_WAN is not set # @@ -8044,22 +8117,11 @@ CONFIG_DEBUG_KERNEL=y # # Compile-time checks and compiler options # -CONFIG_DEBUG_INFO=y CONFIG_AS_HAS_NON_CONST_ULEB128=y -# CONFIG_DEBUG_INFO_NONE is not set +CONFIG_DEBUG_INFO_NONE=y # CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT is not set # CONFIG_DEBUG_INFO_DWARF4 is not set -CONFIG_DEBUG_INFO_DWARF5=y -# CONFIG_DEBUG_INFO_REDUCED is not set -CONFIG_DEBUG_INFO_COMPRESSED_NONE=y -# CONFIG_DEBUG_INFO_COMPRESSED_ZLIB is not set -# CONFIG_DEBUG_INFO_SPLIT is not set -CONFIG_DEBUG_INFO_BTF=y -CONFIG_PAHOLE_HAS_SPLIT_BTF=y -CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y -CONFIG_DEBUG_INFO_BTF_MODULES=y -# CONFIG_MODULE_ALLOW_BTF_MISMATCH is not set -# CONFIG_GDB_SCRIPTS is not set +# CONFIG_DEBUG_INFO_DWARF5 is not set CONFIG_FRAME_WARN=1024 CONFIG_STRIP_ASM_SYMS=y # CONFIG_READABLE_ASM is not set @@ -8278,7 +8340,6 @@ CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set CONFIG_BLK_DEV_IO_TRACE=y -CONFIG_PROBE_EVENTS_BTF_ARGS=y CONFIG_KPROBE_EVENTS=y # CONFIG_KPROBE_EVENTS_ON_NOTRACE is not set # CONFIG_UPROBE_EVENTS is not set @@ -8313,7 +8374,6 @@ CONFIG_STRICT_DEVMEM=y # arm64 Debugging # # CONFIG_PID_IN_CONTEXTIDR is not set -# CONFIG_DEBUG_EFI is not set # CONFIG_ARM64_RELOC_TEST is not set # CONFIG_CORESIGHT is not set # end of arm64 Debugging diff --git a/patch/kernel/archive/sunxi-dev-6.14/0801-net-wireless-backport-aic8800-sdio-v2024_0327_3561b08f.patch b/patch/kernel/archive/sunxi-dev-6.14/0801-net-wireless-backport-aic8800-sdio-v2024_0327_3561b08f.patch new file mode 100644 index 000000000..8b00d029d --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/0801-net-wireless-backport-aic8800-sdio-v2024_0327_3561b08f.patch @@ -0,0 +1,84726 @@ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,252 @@ ++#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_CHAN_MAX_TXPWR_EN_FLAG (0x01U << 1) ++#define USER_TX_USE_ANA_F_FLAG (0x01U << 2) ++ ++#define CFG_USER_CHAN_MAX_TXPWR_EN 0 ++#define CFG_USER_TX_USE_ANA_F 0 ++ ++#define CFG_USER_EXT_FLAGS_EN (CFG_USER_CHAN_MAX_TXPWR_EN || CFG_USER_TX_USE_ANA_F) ++ ++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, 0x00000001 ++ #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 ++ }, // user_ext_flags ++ #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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800d80_compat.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2275 @@ ++#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 ++}; ++ ++ ++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, ++ 0x00ffce80, ++ 0x00ffce93, ++ 0x00ffcf90, ++ 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 ++ 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 ++}; ++ ++ ++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}, ++}; ++ ++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; ++ } ++ } ++ } ++ ++} ++ ++ ++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; ++ ++ 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]); ++ } ++ } ++ ++ 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())) { ++ txgain_cfg_size = sizeof(txgain_map_h); ++ txgain_cfg_array = (u32 *)txgain_map_h; ++ } else { ++ txgain_cfg_size = sizeof(txgain_map); ++ txgain_cfg_array = (u32 *)txgain_map; ++ } ++ 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 ++ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic8800dc_compat.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,37 @@ ++#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 ++ ++#endif ++ ++ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2051 @@ ++/** ++ ****************************************************************************** ++ * ++ * 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) ++{ ++ cmd_mgr->print(cmd_mgr); ++ cmd_mgr->drain(cmd_mgr); ++ 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) ++ 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 MODULE_IMPORT_NS ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#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; ++} ++ ++#ifdef CONFIG_DPD ++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 rftest 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 rftest bin fail: %d\n", ret); ++ return ret; ++ } ++ } ++ return ret; ++} ++ ++#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 ++ ++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 ++ #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 ++ #endif ++ 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) ++{ ++ if (AICBT_PT_INF == head_t->type) { ++ patch_info->info_len = head_t->len; ++ if(patch_info->info_len == 0) ++ return 0; ++ memcpy(&patch_info->adid_addrinf, head_t->data, patch_info->info_len * sizeof(uint32_t) * 2); ++ } ++ return 0; ++} ++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, ++ }; ++ 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; ++ } ++ } ++ ++ 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; ++ 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 ++}; ++ ++ ++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 (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; ++ } ++ } ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ 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); ++ btenable = 1; ++ ++ 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; ++ } ++ ++ 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){ ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,581 @@ ++/** ++ ****************************************************************************** ++ * ++ * 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 3000//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); ++#ifdef CONFIG_DPD ++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 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 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 ++ ++#ifdef CONFIG_DPD ++#define ROM_FMAC_CALIB_ADDR 0x00130000 ++#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 AICBSP_HWINFO_DEFAULT (-1) ++#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK ++#define AICBSP_FWLOG_EN_DEFAULT 0 ++ ++#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 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; ++ 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; ++}; ++ ++struct aicbsp_firmware { ++ const char *desc; ++ const char *bt_adid; ++ const char *bt_patch; ++ const char *bt_table; ++ const char *wl_fw; ++}; ++ ++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[]; ++ ++#endif +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_export.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,65 @@ ++#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; ++}; ++ ++#ifdef CONFIG_DPD ++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) ++ ++extern rf_misc_ram_lite_t dpd_res; ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,393 @@ ++#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|LOGINFO|LOGDEBUG|LOGTRACE; ++ ++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", ++ .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", ++ .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", ++ .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", ++ .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", ++ #ifdef CONFIG_SDIO_BT ++ .wl_fw = "fmacfwbt_8800d80_u02.bin" ++ #else ++ .wl_fw = "fmacfw_8800d80_u02.bin" ++ #endif ++ }, ++ ++ [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" ++ }, ++}; ++ ++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(); ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1980 @@ ++/** ++ * 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; ++static 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_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++ ++ ++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{ ++ 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; ++ ++ 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; ++ } ++ ++ func = func->card->sdio_func[1 - 1]; //replace 2 with 1 ++ host = func->card->host; ++ 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) { ++ 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; ++ } ++ host->caps |= MMC_CAP_NONREMOVABLE; ++ 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; ++ ++ sdio_dbg("%s\n", __func__); ++ if (aicbsp_sdiodev == NULL) { ++ sdio_dbg("%s: allready unregister\n", __func__); ++ return; ++ } ++ ++ bus_if = aicbsp_get_drvdata(&func->dev); ++ ++ if (!bus_if) { ++ AICWFDBG(LOGERROR, "%s bus_if is NULL \r\n", __func__); ++ return; ++ } ++ ++ func = aicbsp_sdiodev->func; ++ host = func->card->host; ++ host->caps &= ~MMC_CAP_NONREMOVABLE; ++ ++ sdiodev = bus_if->bus_priv.sdio; ++ if (!sdiodev) { ++ AICWFDBG(LOGERROR, "%s sdiodev is NULL \r\n", __func__); ++ return; ++ } ++ ++ aicwf_sdio_release(sdiodev); ++ aicwf_sdio_func_deinit(sdiodev); ++ ++ dev_set_drvdata(&sdiodev->func->dev, NULL); ++ kfree(sdiodev); ++ 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) ++{ ++ struct semaphore aic_chipup_sem; ++ ++ sema_init(&aic_chipup_sem, 0); ++ aicbsp_probe_semaphore = &aic_chipup_sem; ++ ++ 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) { ++ 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){ ++ 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){ ++ 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) ++ 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){ ++ 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) ++{ ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#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) { ++ 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)) ++ del_timer_sync(&sdiodev->timer); ++ } 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; ++ int ret = 0; ++ ++ sdio_dbg("%s\n", __func__); ++ ++ bus_if = aicbsp_get_drvdata(sdiodev->dev); ++ bus_if->state = BUS_DOWN_ST; ++ ++ 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->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) ++{ ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,148 @@ ++/** ++ * 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 ++}; ++ ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,465 @@ ++/** ++ * 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"); ++ bus_if->busrx_thread = kthread_run(aicwf_sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->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"); ++ ret = -1; ++ goto fail; ++ } ++ ++ if (IS_ERR(bus_if->busrx_thread)) { ++ bus_if->busrx_thread = NULL; ++ txrx_err("aicwf_bustx_thread run fail\n"); ++ ret = -1; ++ goto fail; ++ } ++ ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicsdio_txrxif.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_firmware_array.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,3 @@ ++int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf); ++ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aicwf_txq_prealloc.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,4 @@ ++ ++ ++void aicwf_prealloc_txq_free(void); ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/.gitignore 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/Makefile 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,136 @@ ++CONFIG_SDIO_SUPPORT := y ++CONFIG_SDIO_PWRCTRL := y ++CONFIG_AIC_FW_PATH = "/vendor/etc/firmware" ++#CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800" ++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_RESV_MEM_SUPPORT ?= y ++CONFIG_AMSDU_RX = n ++CONFIG_IRQ_FALL ?= n ++CONFIG_SDIO_BT = n ++ ++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_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 ++ ++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 ?= ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/md5.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_bsp/rwnx_version_gen.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 "2024_0327_3561b08f" +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic8800_btlpm.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bluetooth_main.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/aic_bsp_export.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/.gitignore 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,5 @@ ++config AIC8800_BTLPM_SUPPORT ++ tristate "AIC8800 bluetooth Support" ++ help ++ This is support for aic bluetooh driver. ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Makefile 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/rfkill.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_br_ext.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_bsp_export.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,58 @@ ++#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, ++}; ++ ++#ifdef CONFIG_DPD ++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) ++ ++extern rf_misc_ram_lite_t dpd_res; ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1310 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "aic_btsdio.h" ++#include "rwnx_msg_tx.h" ++ ++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; ++ } ++ ++ //printk("%s type %x len %d \n",__func__,type,len); ++ //bt_data_dump("bt_recv", ind->bt_data, 64); ++ ++ /*#if (CONFIG_BLUEDROID) || (HCI_VERSION_CODE < KERNEL_VERSION(3, 18, 0)) ++ if (hci_recv_fragment(hdev, type, ++ ind->bt_data[0], ++ ind->data_len) < 0) { ++ AICWFDBG(LOGERROR,"%s: Corrupted event packet", __func__); ++ hdev->stat.err_rx++; ++ } ++ #endif*/ ++ 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); ++} ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_btsdio.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,549 @@ ++#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 1 /* 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 ++ ++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); ++ ++#endif//_AICWF_SDIO_BT_H_ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,909 @@ ++#include "aic_vendor.h" ++#include "rwnx_defs.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "rwnx_version_gen.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 ++ ++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; ++} ++ ++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; ++ ++ 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)); ++ 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; ++ ++ 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_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) ++{ ++ /* TODO ++ * Add handle in the future ++ */ ++ return 0; ++} ++ ++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 }, ++}; ++ ++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 ++ }, ++ { ++ { ++ .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 = 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 ++ }, ++}; ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aic_vendor.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,346 @@ ++#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, ++}; ++ ++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 */ ++ /* Add more sub commands here */ ++ GSCAN_SUBCMD_MAX, ++ APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START, ++ APF_SUBCMD_SET_FILTER, ++}; ++ ++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, ++ // 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_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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,66 @@ ++#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" ++ ++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_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 ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_lvl_adj_req(rwnx_hw))) { ++ return -1; ++ } ++ ++ if ((ret = rwnx_send_txpwr_ofst2x_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; ++ ++} ++ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800d80.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,9 @@ ++#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); ++ ++#endif ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,542 @@ ++#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); ++ ++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, ++}; ++ ++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 ++ ++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 (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; ++ } ++ ++ 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; ++ } ++ } ++ #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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_compat_8800dc.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_debug.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_rx_prealloc.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2591 @@ ++/** ++ * aicwf_sdmmc.c ++ * ++ * SDIO function declarations ++ * ++ * Copyright (C) AICSemi 2018-2020 ++ */ ++#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" ++#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_GPIO_WAKEUP ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level); ++ ++#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 ++ ++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; ++} ++ ++#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 ++ ++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{ ++ return -1; ++ } ++} ++ ++ ++extern int rwnx_send_me_set_lp_level(struct rwnx_hw *rwnx_hw, u8 lp_level); ++ ++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; ++ ++ //sdio func init start ++ if (sdiodev->chipid != PRODUCT_ID_AIC8800D80) { ++ 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); ++} ++ ++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; ++ } ++ ++ ++ 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; ++ } ++#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(); ++ ++ 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) ++ int ret; ++#endif ++ ++ sdio_dbg("%s enter \n", __func__); ++//#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 ++ ++// 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)}, ++ { }, ++}; ++ ++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, ++ }, ++}; ++#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){ ++ 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 = 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) { ++ 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 = 10; ++ while (read_retry) { ++ u8 val; ++ ret = aicwf_sdio_readb(sdiodev, sdiodev->sdio_reg.sleep_reg, &val); ++ if (ret < 0) ++ txrx_err("sdio wakeup read fail\n"); ++ else if (val & 0x10) { ++ 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; ++ ++ 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) { ++ AICWFDBG(LOGSDPWRC, "%s s\n", __func__); ++ 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); ++ //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; ++} ++ ++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){ ++ 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){ ++ 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; ++ } ++ 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 ++ ++ 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 (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; ++ } ++ } 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); ++ ++#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 ++ ++ 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 || 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); ++ } 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}; ++ 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) ++ 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); ++ 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); ++} ++ ++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){ ++ 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 ++ ++#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 (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busirq thread stop\n"); ++ break; ++ } ++ ++ 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) ++ 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); ++ } ++ ++ 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 (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio bustx thread stop\n"); ++ break; ++ } ++ ++ if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { ++ if (sdiodev->bus_if->state == BUS_DOWN_ST) ++ 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); ++ } ++ } ++ ++ 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 (kthread_should_stop()) { ++ AICWFDBG(LOGERROR, "sdio busrx thread stop\n"); ++ break; ++ } ++ if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { ++ ++ if (bus_if->state == BUS_DOWN_ST) ++ 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); ++ } ++ } ++ 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 ++ struct aic_sdio_dev *sdiodev = from_timer(sdiodev, t, timer); ++#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; ++ ++ //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); ++ } ++ 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) { ++ 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); ++ 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)) ++ del_timer_sync(&sdiodev->timer); ++ } 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; ++#ifdef CONFIG_OOB ++ int ret; ++#endif ++ 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); ++ } ++#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->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); ++ ++ 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; ++ } ++ ++ 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; ++ } ++ ++#if 1 ++ 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"); ++ } ++#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); ++} ++ ++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 ++ ++ 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); ++ }else{ ++ printk("%s suspend \r\n", __func__); ++ ret = rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1); ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,186 @@ ++/** ++ * 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 ++ ++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_DEVICE_ID_AIC8801 0x0145 ++#define SDIO_DEVICE_ID_AIC8800DC 0xc08d ++#define SDIO_DEVICE_ID_AIC8800D80 0x0082 ++ ++enum AICWF_IC{ ++ PRODUCT_ID_AIC8801 = 0, ++ PRODUCT_ID_AIC8800DC, ++ PRODUCT_ID_AIC8800DW, ++ PRODUCT_ID_AIC8800D80 ++}; ++ ++ ++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 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; ++}; ++extern struct aicwf_rx_buff_list aic_rx_buff_list; ++int aicwf_sdio_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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,633 @@ ++#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); ++ del_timer(&ack_m->ack_info[i].timer); ++ 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; ++ del_timer(&ack_info->timer); ++ }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; ++ del_timer(&ack_info->timer); ++ } 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 = send_msg; ++ del_timer(&ack_info->timer); ++ }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; ++ ++ if (plen > MAX_TCP_ACK) ++ return 0; ++ ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_tcp_ack.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,111 @@ ++#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 */ ++ /*void *data; ++ void *tran_data; ++ unsigned long pcie_addr; ++ u8 type; ++ u8 mode; ++ u16 len; ++ unsigned long timeout;*/ ++ ++ /*unsigned int fifo_id; ++ struct sprdwl_msg_list *msglist;*/ ++ ++ /*unsigned char buffer_type; ++ struct sprdwl_xmit_msg_list *xmit_msg_list; ++ unsigned char msg_type; ++ ++ unsigned long last_time; ++ u8 ctxt_id;*/ ++ ++}; ++ ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,885 @@ ++/** ++ * 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; ++ ++ 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 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__); ++ ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ list_for_each_entry_safe(reord_info, tmp, ++ &rx_priv->stas_reord_list, list) { ++ reord_deinit_sta(rx_priv, reord_info); ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_txrxif.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,262 @@ ++/** ++ * 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 ++}; ++ ++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 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_usb.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/.gitignore 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,10 @@ ++*.o ++*.ko ++*.order ++*.symvers ++*.o.d ++*.o.cmd ++*.ko.cmd ++*.mod ++*.mod.c ++*.mod.cmd +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/hal_desc.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,353 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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[]; ++ ++/* 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; ++}; ++ ++/* 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_compat.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_host.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/ipc_shared.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,5 @@ ++config AIC8800_WLAN_SUPPORT ++ tristate "AIC8800 wlan Support" ++ help ++ This is support for aic wifi driver. ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_mac.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_msg.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,3082 @@ ++/** ++ **************************************************************************************** ++ * ++ * @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" ++ ++/* ++ **************************************************************************************** ++ */ ++///////////////////////////////////////////////////////////////////////////////// ++// 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, ++ ++ /// 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; ++}; ++ ++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_adj_tbl_2g4[3]; ++ s8_l pwrlvl_adj_tbl_5g[6]; ++} txpwr_lvl_adj_conf_t; ++ ++typedef struct ++{ ++ u8_l loss_enable; ++ u8_l loss_value; ++} 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; ++ }; ++}; ++ ++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; ++ ++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; ++ }; ++}; ++ ++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, ++}; ++ ++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; ++}; ++ ++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_vendor_hwconfig_cfm ++{ ++ u32_l hwconfig_id; ++ union { ++ struct mm_get_chip_temp_cfm chip_temp_cfm; ++ }; ++}; ++ ++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; ++}; ++ ++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; ++}; ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++/////////// 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_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; ++ /// 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[18]; ++}; ++ ++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_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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/lmac_types.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,380 @@ ++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_SDIO_PWRCTRL ?= 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_GPIO_WAKEUP ?= n ++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_FILTER_TCP_ACK =n ++CONFIG_RESV_MEM_SUPPORT ?= y ++CONFIG_GKI = n ++CONFIG_TEMP_COMP = n ++# CONFIG_MCC = n for sta and p2p concurrent in same channel. ++CONFIG_MCC = y ++ ++ifneq ($(CONFIG_WIRELESS_EXT), y) ++CONFIG_USE_WIRELESS_EXT = n ++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 =y ++ ++# 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 \ ++ 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_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_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_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_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_MCC) += -DCONFIG_MCC ++ ++ ++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_DETECT) += -DRADAR_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-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) ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/md5.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/reg_access.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/regdb.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2898 @@ ++#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_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, 5695, 160, 0, 27, 0, ++ NL80211_RRF_DFS | 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_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_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_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, ++}; ++ ++int reg_regdb_size = ARRAY_SIZE(reg_regdb); ++ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_bfmer.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cfgfile.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,539 @@ ++/** ++ ****************************************************************************** ++ * ++ * 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; ++} ++ ++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; ++ ++ //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)) { ++ 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 ++ ++ 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 { ++ 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 ++ 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 ++ 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) ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_cmds.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 3000//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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_compat.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,446 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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 ++ ++#define REGULATORY_IGNORE_STALE_KICKOFF 0 ++#else ++#define STA_TDLS_INITIATOR(sta) sta->tdls_initiator ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2455 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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); ++ } ++ ++ 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[13]; ++ 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", ++ &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]); ++ if(ret > 14) { ++ printk("param error > 14\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 != 14) { ++ printk("param error != 14\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\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]); ++ 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; ++ 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]) == -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_debugfs.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_defs.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,746 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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 */ ++}; ++#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 */ ++ ++enum rwnx_drv_connect_status { ++ RWNX_DRV_STATUS_DISCONNECTED = 0, ++ RWNX_DRV_STATUS_DISCONNECTING, ++ RWNX_DRV_STATUS_CONNECTING, ++ RWNX_DRV_STATUS_CONNECTED, ++}; ++ ++ ++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 ++}; ++ ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_dini.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_events.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_fw_trace.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_gki.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_irqs.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,7391 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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 ++ ++ ++#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) ++ ++#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|LOGINFO|LOGDEBUG|LOGTRACE; ++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 { ++ mutex_lock(&vif->wdev.mtx); ++ __acquire(&vif->wdev.mtx); ++ 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 >= 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 ++ mutex_unlock(&vif->wdev.mtx); ++ __release(&vif->wdev.mtx); ++ } ++ 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 */ ++ ++ ++/********************************************************************* ++ * 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 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 (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) && testmode == 0)){ ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_STATION || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_CLIENT) { ++ rwnx_send_coex_req(rwnx_hw, 0, 1); ++ } ++ } ++ #endif ++ ++ /* Device is now started */ ++ } ++ #ifdef CONFIG_COEX ++ else if ((RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO)) { ++ rwnx_send_coex_req(rwnx_hw, 1, 0); ++ } ++ #endif ++ ++ set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); ++ atomic_set(&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); ++ } ++ } ++ ++ #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){ ++ atomic_set(&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 ++#ifdef CONFIG_COEX ++ if (testmode == 0) ++ rwnx_send_coex_req(rwnx_hw, 1, 0); ++#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); ++ } ++ } ++#endif ++ } ++#ifdef CONFIG_COEX ++ else { ++ if (RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_AP || RWNX_VIF_TYPE(rwnx_vif) == NL80211_IFTYPE_P2P_GO) ++ rwnx_send_coex_req(rwnx_hw, 0, 1); ++ } ++#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); ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ //open lp mode ++ //rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 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, g_rwnx_plat->sdiodev->sdio_reg.wakeup_reg, 2); ++ if (ret < 0) { ++ sdio_err("reg:%d write failed!\n", g_rwnx_plat->sdiodev->sdio_reg.wakeup_reg); ++ } ++#endif//CONFIG_GPIO_WAKEUP ++ ++ return 0; ++} ++ ++#ifdef CONFIG_RFTEST ++enum { ++ SET_TX, ++ SET_TXSTOP, ++ SET_TXTONE, ++ SET_RX, ++ GET_RX_RESULT, ++ SET_RXSTOP, ++ SET_RXMETER, ++ SET_POWER, ++ SET_XTAL_CAP, ++ SET_XTAL_CAP_FINE, ++ GET_EFUSE, ++ 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, ++}; ++ ++typedef struct { ++ u8_l chan; ++ u8_l bw; ++ u8_l mode; ++ u8_l rate; ++ u16_l length; ++ u16_l tx_intv_us; ++} 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 ++ ++#define CMD_MAXARGS 10 ++ ++#if 0 ++#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; ++} ++ ++ ++int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) ++{ ++ int bytes_written = 0; ++ char *para = NULL; ++ char *cmd = NULL; ++ char *argv[CMD_MAXARGS + 1]; ++ int argc; ++#ifdef CONFIG_RFTEST ++ struct dbg_rftest_cmd_cfm cfm; ++ u8_l mac_addr[6]; ++ cmd_rf_settx_t settx_param; ++ cmd_rf_rx_t setrx_param; ++ int freq; ++ cmd_rf_getefuse_t getefuse_param; ++ cmd_rf_setfreq_t cmd_setfreq; ++ cmd_rf_setcobcal_t setcob_cal; ++ u8_l ana_pwr; ++ u8_l dig_pwr; ++ u8_l pwr; ++ u8_l xtal_cap; ++ u8_l xtal_cap_fine; ++ u8_l vendor_info; ++ cob_result_ptr_t *cob_result_ptr; ++ ++#endif ++ ++ u8_l state; ++ ++#ifdef CONFIG_GPIO_WAKEUP ++ u8_l setsusp_mode; ++ int ret = 0; ++#endif ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ argc = parse_line(command, argv); ++ if (argc == 0) { ++ return -1; ++ } ++ ++ do { ++#ifdef CONFIG_RFTEST ++ if (strcasecmp(argv[0], "GET_RX_RESULT") == 0) { ++ AICWFDBG(LOGINFO, "get_rx_result\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_RX_RESULT, 0, NULL, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 8); ++ bytes_written = 8; ++ } else if (strcasecmp(argv[0], "SET_TX") == 0) { ++ AICWFDBG(LOGINFO, "set_tx\n"); ++ if (argc < 6) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ 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 ++ } ++ 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 AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_TX, sizeof(cmd_rf_settx_t), (u8_l *)&settx_param, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "SET_TXSTOP") == 0) { ++ AICWFDBG(LOGINFO, "settx_stop\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_TXSTOP, 0, NULL, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_TXSTOP, 0, NULL, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "SET_TXTONE") == 0) { ++ AICWFDBG(LOGINFO, "set_tx_tone,argc:%d\n", argc); ++ if ((argc == 2) || (argc == 3)) { ++ u8_l func, buf[2]; ++ s8_l freq; ++ 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; ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_TXTONE, argc - 1, buf, NULL); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ } ++ } else if (strcasecmp(argv[0], "SET_RX") == 0) { ++ AICWFDBG(LOGINFO, "set_rx\n"); ++ if (argc < 3) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ setrx_param.chan = command_strtoul(argv[1], NULL, 10); ++ setrx_param.bw = command_strtoul(argv[2], NULL, 10); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_RX, sizeof(cmd_rf_rx_t), (u8_l *)&setrx_param, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "SET_RXSTOP") == 0) { ++ AICWFDBG(LOGINFO, "set_rxstop\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_RXSTOP, 0, NULL, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_RXSTOP, 0, NULL, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "SET_RX_METER") == 0) { ++ AICWFDBG(LOGINFO, "set_rx_meter\n"); ++ freq = (int)command_strtoul(argv[1], NULL, 10); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_RXMETER, sizeof(freq), (u8_l *)&freq, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_RXMETER, sizeof(freq), (u8_l *)&freq, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "SET_FREQ_CAL") == 0) { ++ AICWFDBG(LOGINFO, "set_freq_cal\n"); ++ if (argc < 2) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_FREQ_CAL, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "SET_FREQ_CAL_FINE") == 0) { ++ AICWFDBG(LOGINFO, "set_freq_cal_fine\n"); ++ if (argc < 2) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ cmd_setfreq.val = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "param:%x\r\n", cmd_setfreq.val); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_FREQ_CAL_FINE, sizeof(cmd_rf_setfreq_t), (u8_l *)&cmd_setfreq, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "GET_EFUSE") == 0) { ++ AICWFDBG(LOGINFO, "get_efuse\n"); ++ if (argc < 2) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ getefuse_param.block = command_strtoul(argv[1], NULL, 10); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_EFUSE, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_EFUSE, sizeof(cmd_rf_getefuse_t), (u8_l *)&getefuse_param, &cfm); ++ #endif ++ AICWFDBG(LOGINFO, "get val=%x\r\n", cfm.rftest_result[0]); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "SET_POWER") == 0) { ++ AICWFDBG(LOGINFO, "set_power\n"); ++ if(g_rwnx_plat->sdiodev->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) { ++ AICWFDBG(LOGERROR, "invalid param\r\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ ana_pwr = command_strtoul(argv[1], NULL, 10); ++ pwr = ana_pwr; ++ if (ana_pwr > 0x1e) { ++ AICWFDBG(LOGERROR, "invalid param\r\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } ++ AICWFDBG(LOGINFO, "pwr =%x\r\n", pwr); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_POWER, sizeof(pwr), (u8_l *)&pwr, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "SET_XTAL_CAP") == 0) { ++ AICWFDBG(LOGINFO, "set_xtal_cap\n"); ++ if (argc < 2) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ xtal_cap = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap =%x\r\n", xtal_cap); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_XTAL_CAP, sizeof(xtal_cap), (u8_l *)&xtal_cap, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "SET_XTAL_CAP_FINE") == 0) { ++ AICWFDBG(LOGINFO, "set_xtal_cap_fine\n"); ++ if (argc < 2) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ xtal_cap_fine = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "xtal_cap_fine =%x\r\n", xtal_cap_fine); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_XTAL_CAP_FINE, sizeof(xtal_cap_fine), (u8_l *)&xtal_cap_fine, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "SET_MAC_ADDR") == 0) { ++ printk("set_mac_addr\n"); ++ if (argc < 7) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ 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]); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ #endif ++ } else if (strcasecmp(argv[0], "GET_MAC_ADDR") == 0) { ++ u32_l addr0, addr1; ++ AICWFDBG(LOGINFO, "get mac addr\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_MAC_ADDR, 0, NULL, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 8); ++ bytes_written = 8; ++ addr0 = cfm.rftest_result[0]; ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->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); ++ } ++ } else if (strcasecmp(argv[0], "SET_BT_MAC_ADDR") == 0) { ++ AICWFDBG(LOGINFO, "set_bt_mac_addr\n"); ++ if (argc < 7) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ 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(g_rwnx_plat->sdiodev->rwnx_hw, SET_BT_MAC_ADDR, sizeof(mac_addr), (u8_l *)&mac_addr, NULL); ++ } else if (strcasecmp(argv[0], "GET_BT_MAC_ADDR")==0) { ++ u32_l addr0, addr1; ++ AICWFDBG(LOGINFO, "get bt mac addr\n"); ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_BT_MAC_ADDR, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 8); ++ bytes_written = 8; ++ addr0 = cfm.rftest_result[0]; ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->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); ++ } ++ } else if (strcasecmp(argv[0], "SET_VENDOR_INFO") == 0) { ++ vendor_info = command_strtoul(argv[1], NULL, 16); ++ AICWFDBG(LOGINFO, "set vendor info:%x\n", vendor_info); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, SET_VENDOR_INFO, 1, &vendor_info, &cfm); ++ #endif ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ bytes_written = 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ bytes_written = 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++ } else if (strcasecmp(argv[0], "GET_VENDOR_INFO") == 0) { ++ AICWFDBG(LOGINFO, "get vendor info\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); ++ #endif ++ #ifdef AICWF_USB_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->usbdev->rwnx_hw, GET_VENDOR_INFO, 0, NULL, &cfm); ++ #endif ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { ++ memcpy(command, &cfm.rftest_result[0], 2); ++ bytes_written = 2; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 1); ++ bytes_written = 1; ++ } ++ AICWFDBG(LOGINFO, "0x%x\n", cfm.rftest_result[0]); ++ } else if (strcasecmp(argv[0], "GET_FREQ_CAL") == 0) { ++ unsigned int val; ++ AICWFDBG(LOGINFO, "get freq cal\n"); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_FREQ_CAL, 0, NULL, &cfm); ++ #endif ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ val = cfm.rftest_result[0]; ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { ++ 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); ++ } ++ } else if (strcasecmp(argv[0], "RDWR_PWRMM") == 0) { ++ AICWFDBG(LOGINFO, "read/write txpwr manul mode\n"); ++ if (argc <= 1) { // read cur ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRMM, 0, NULL, &cfm); ++ #endif ++ } 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); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRMM, sizeof(pwrmm), (u8_l *)&pwrmm, &cfm); ++ #endif ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "RDWR_PWRIDX") == 0) { ++ u8_l func = 0; ++ #ifdef AICWF_SDIO_SUPPORT ++ if (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8801) { ++ AICWFDBG(LOGERROR, "unsupported cmd\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ #endif ++ AICWFDBG(LOGINFO, "read/write txpwr index\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRIDX, 0, NULL, &cfm); ++ #endif ++ } 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(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRIDX, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ memcpy(command, &cfm.rftest_result[0], 9); ++ bytes_written = 9; ++ } else if (strcasecmp(argv[0], "RDWR_PWRLVL") == 0) { ++ u8_l func = 0; ++ #ifdef AICWF_SDIO_SUPPORT ++ if ((g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800DC) ++ && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800DW) ++ && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800D80)) { ++ AICWFDBG(LOGINFO, "unsupported cmd\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ #endif ++ AICWFDBG(LOGINFO, "read/write txpwr level\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->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(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWRLVL, size, buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ if(g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80){ ++ memcpy(command, &cfm.rftest_result[0], 6 * 12); ++ bytes_written = 6 * 12; ++ } else { ++ memcpy(command, &cfm.rftest_result[0], 3 * 12); ++ bytes_written = 3 * 12; ++ } ++ } else if (strcasecmp(argv[0], "RDWR_PWROFST") == 0) { ++ u8_l func = 0; ++ int res_len = 0; ++ AICWFDBG(LOGINFO, "read/write txpwr offset\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFST, 0, NULL, &cfm); ++ #endif ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if ((argc > 4) && (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80)) { ++ 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}; ++ printk("set pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ #endif ++ } else if ((argc > 3) && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800D80)) { ++ 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}; ++ printk("set pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFST, sizeof(buf), buf, &cfm); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { // 3 = 3 (2.4g) ++ res_len = 3; ++ } else if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = 3 * 3 + 3 * 6; ++ } else { ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ bytes_written = res_len; ++ } else if (strcasecmp(argv[0], "RDWR_PWROFSTFINE") == 0) { ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write txpwr offset fine\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->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(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ memcpy(command, &cfm.rftest_result[0], 7); ++ bytes_written = 7; ++ } else if (strcasecmp(argv[0], "RDWR_DRVIBIT") == 0) { ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write pa drv_ibit\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_DRVIBIT, 0, NULL, &cfm); ++ #endif ++ } 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}; ++ printk("set drvibit:[%x]=%x\r\n", func, ibit); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_DRVIBIT, sizeof(buf), buf, &cfm); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ memcpy(command, &cfm.rftest_result[0], 16); ++ bytes_written = 16; ++ } else if (strcasecmp(argv[0], "RDWR_EFUSE_PWROFST") == 0) { ++ u8_l func = 0; ++ int res_len = 0; ++ AICWFDBG(LOGINFO, "read/write txpwr offset into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFST, 0, NULL, &cfm); ++ #endif ++ } else if (func <= 2) { // write 2.4g/5g pwr ofst ++ if ((argc > 4) && (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80)) { ++ 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}; ++ printk("set efuse pwrofst_%s:[%x][%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", type, chgrp, pwrofst); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ #endif ++ } else if ((argc > 3) && (g_rwnx_plat->sdiodev->chipid != PRODUCT_ID_AIC8800D80)) { ++ 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}; ++ printk("set efuse pwrofst_%s:[%x]=%d\r\n", (func == 1) ? "2.4g" : "5g", chgrp, pwrofst); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFST, sizeof(buf), buf, &cfm); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 ++ res_len = 3 * 2; ++ } else if (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800D80) { // 3 * 2 (2.4g) + 3 * 6 (5g) ++ res_len = 3 * 3 + 3 * 6; ++ } else { // 7 = 3(2.4g) + 4(5g) ++ res_len = 3 + 4; ++ } ++ memcpy(command, &cfm.rftest_result[0], res_len); ++ bytes_written = res_len; ++ } else if (strcasecmp(argv[0], "RDWR_EFUSE_DRVIBIT") == 0) { ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write pa drv_ibit into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_DRVIBIT, 0, NULL, &cfm); ++ #endif ++ } 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); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_DRVIBIT, sizeof(buf), buf, &cfm); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "RDWR_EFUSE_PWROFSTFINE") == 0) { ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write txpwr offset fine into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->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 efuse pwrofstfine:[%x][%x]=%d\r\n", func, chgrp, pwrofst); ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_PWROFSTFINE, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ if ((g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DC) || ++ (g_rwnx_plat->sdiodev->chipid == PRODUCT_ID_AIC8800DW)) { // 6 = 3 (2.4g) * 2 ++ memcpy(command, &cfm.rftest_result[0], 6); ++ bytes_written = 6; ++ } else { // 7 = 3(2.4g) + 4(5g) ++ memcpy(command, &cfm.rftest_result[0], 7); ++ bytes_written = 7; ++ } ++ } else if (strcasecmp(argv[0], "SET_PAPR") == 0) { ++ AICWFDBG(LOGINFO, "set papr\n"); ++ if (argc > 1) { ++ u8_l func = (u8_l) command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "papr %d\r\n", func); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_PAPR, sizeof(func), &func, NULL); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else if (strcasecmp(argv[0], "SET_NOTCH") == 0) { ++ if (argc > 1) { ++ u8_l func = (u8_l) command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set notch %d\r\n", func); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_NOTCH, sizeof(func), &func, NULL); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else if (strcasecmp(argv[0], "SET_SRRC") == 0) { ++ if (argc > 1) { ++ u8_l func = (u8_l) command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set srrc %d\r\n", func); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_SRRC, sizeof(func), &func, NULL); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else if (strcasecmp(argv[0], "SET_FSS") == 0) { ++ if (argc > 1) { ++ u8_l func = (u8_l) command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set fss: %d\r\n", func); ++ #ifdef AICWF_SDIO_SUPPORT ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, SET_FSS, sizeof(func), &func, NULL); ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else if (strcasecmp(argv[0], "RDWR_EFUSE_HE_OFF") == 0) { ++ if (argc > 1) { ++ u8_l func = command_strtoul(argv[1], NULL, 10); ++ AICWFDBG(LOGINFO, "set he off: %d\n", func); ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->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); ++ bytes_written = 4; ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else if (strcasecmp(argv[0], "SET_COB_CAL") == 0) { ++ AICWFDBG(LOGINFO, "set_cob_cal\n"); ++ if (argc < 3) { ++ AICWFDBG(LOGERROR, "wrong param\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ 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(g_rwnx_plat->sdiodev->rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ } else if (strcasecmp(argv[0], "GET_COB_CAL_RES")==0) { ++ AICWFDBG(LOGINFO, "get cob cal res\n"); ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->rwnx_hw, GET_COB_CAL_RES, 0, NULL, &cfm); ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ AICWFDBG(LOGINFO, "cap=0x%x, cap_fine=0x%x\n", cfm.rftest_result[0] & 0x0000ffff, (cfm.rftest_result[0] >> 16) & 0x0000ffff); ++ } else if (strcasecmp(argv[0], "DO_COB_TEST") == 0) { ++ AICWFDBG(LOGINFO, "do_cob_test\n"); ++ 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(g_rwnx_plat->sdiodev->rwnx_hw, SET_COB_CAL, sizeof(cmd_rf_setcobcal_t), (u8_l *)&setcob_cal, NULL); ++ msleep(2000); ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->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); ++ bytes_written = 16; ++ } else { ++ AICWFDBG(LOGERROR, "cob not idle\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else if (strcasecmp(argv[0], "RDWR_EFUSE_SDIOCFG") == 0) { ++ u8_l func = 0; ++ AICWFDBG(LOGINFO, "read/write sdiocfg_bit into efuse\n"); ++ if (argc > 1) { ++ func = (u8_l)command_strtoul(argv[1], NULL, 16); ++ } ++ if (func == 0) { // read cur ++ rwnx_send_rftest_req(g_rwnx_plat->sdiodev->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(g_rwnx_plat->sdiodev->rwnx_hw, RDWR_EFUSE_SDIOCFG, sizeof(buf), buf, &cfm); ++ } else { ++ AICWFDBG(LOGERROR, "wrong args\n"); ++ bytes_written = -EINVAL; ++ break; ++ } ++ } else { ++ AICWFDBG(LOGERROR, "wrong func: %x\n", func); ++ bytes_written = -EINVAL; ++ break; ++ } ++ memcpy(command, &cfm.rftest_result[0], 4); ++ bytes_written = 4; ++ } else if (strcasecmp(argv[0], "SETSUSPENDMODE") == 0 && testmode == 0) { ++ #ifdef AICWF_SDIO_SUPPORT ++ #ifdef CONFIG_GPIO_WAKEUP ++ setsusp_mode = command_strtoul(argv[1], NULL, 10); ++ rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode); ++ 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); ++ } ++ } ++ AICWFDBG(LOGINFO, "set suspend mode %d\n", setsusp_mode); ++ #endif//CONFIG_GPIO_WAKEUP ++ #endif ++ } else { ++ AICWFDBG(LOGERROR, "wrong cmd:%s in %s\n", cmd, __func__); ++ bytes_written = -EINVAL; ++ } ++#endif ++ } while (0); ++ kfree(cmd); ++ kfree(para); ++ return bytes_written; ++} ++ ++//Android private command ++ ++#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" ++ ++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; ++ ++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 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; ++ 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))) { ++ 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_SET_VENDOR_EXTENSION_IE ++ else if(!strncasecmp(command, CMD_SET_VENDOR_EX_IE, strlen(CMD_SET_VENDOR_EX_IE))){ ++ set_vendor_extension_ie(command); ++ } ++#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; ++ } ++#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); ++ return ret; ++} ++#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, ++ .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 ++ 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, 11, 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 ++ rwnx_hw = from_timer(rwnx_hw, t, p2p_alive_timer); ++ 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, 11, 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); ++ ++#ifdef CONFIG_COEX ++ if (type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_P2P_GO) ++ rwnx_send_coex_req(vif->rwnx_hw, 1, 0); ++ if (RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_AP || RWNX_VIF_TYPE(vif) == NL80211_IFTYPE_P2P_GO) ++ rwnx_send_coex_req(vif->rwnx_hw, 0, 1); ++#endif ++#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 ++ 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); ++ } ++ ++ 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)) { ++ del_timer_sync(&rwnx_hw->p2p_alive_timer); ++ } ++ ++ 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 0 ++ if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTED){ ++ AICWFDBG(LOGERROR, "%s driver was connected return it \r\n", __func__); ++ return -EALREADY; ++ } ++#endif ++ 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 -EALREADY; ++ } ++#endif ++ ++ atomic_set(&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); ++ ++ 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 0 ++ while(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGERROR, "%s driver connecting waiting 100ms \r\n", __func__); ++ msleep(100); ++ ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTED){ ++ atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ } ++#endif ++ if(atomic_read(&rwnx_vif->drv_conn_state) == RWNX_DRV_STATUS_CONNECTING){ ++ AICWFDBG(LOGINFO, "%s call cfg80211_connect_result reason:%d \r\n", ++ __func__, reason_code); ++ msleep(500); ++ } ++ ++ 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_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTING); ++ key_flag = true; ++ return(rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code)); ++ }else{ ++ cfg80211_connect_result(dev, NULL, NULL, 0, NULL, 0, ++ reason_code?reason_code:WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_ATOMIC); ++ atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ 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 ++ ++ //RWNX_DBG(RWNX_FN_ENTRY_STR); ++ printk("%s: %pM\n", __func__, mac); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) ++ if (params) ++ mac = params->mac; ++#endif ++ ++ 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]); ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ 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; ++ } ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ } ++#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]); ++ spin_lock_bh(&rx_priv->stas_reord_lock); ++ 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; ++ } ++ } ++ spin_unlock_bh(&rx_priv->stas_reord_lock); ++ } ++#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 ++ 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. ++ */ ++static int rwnx_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, ++ struct cfg80211_beacon_data *info) ++{ ++ 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 ++ buf = rwnx_build_bcn(bcn, info); ++ 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); ++ ++ 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 any remaining STA*/ ++ while (!list_empty(&rwnx_vif->ap.sta_list)) { ++ rwnx_cfg80211_del_station_compat(wiphy, dev, NULL); ++ } ++ ++ /* 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, ++ 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; ++} ++ ++/** ++ * @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. ++ */ ++static int rwnx_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) ++{ ++ 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, ++ enum nl80211_tx_power_setting type, int mbm) ++{ ++ 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; ++} ++ ++/** ++ * @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 ++ rwnx_cfg80211_set_monitor_channel(wiphy, NULL); ++ } ++ ++ //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; ++ 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 ++ ) ++{ ++ struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); ++ struct rwnx_vif *rwnx_vif = netdev_priv(dev); ++ struct apm_start_cac_cfm cfm; ++ ++ #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; ++ } ++ ++ error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, bcn_after->len); ++ if (error) { ++ 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 >= 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 ++ 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 TxIndex:%d ModRx:%d RxHTIndex:%d RxVHTIndex:%d RxHEIndex:%d RSSI:%d \r\n", __func__, ++ rate_info->formatModTx, rate_info->mcsIndexTx, 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]; ++ break; ++ case FORMATMOD_HT_MF: ++ case FORMATMOD_HT_GF: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx; ++ break; ++ case FORMATMOD_VHT: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ sinfo->txrate.mcs = rate_info->mcsIndexTx; ++ 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; ++ break; ++#else ++ case FORMATMOD_HE_MU: ++ case FORMATMOD_HE_SU: ++ case FORMATMOD_HE_ER: ++ sinfo->txrate.flags = RATE_INFO_FLAGS_VHT_MCS; ++ if(rate_info->mcsIndexTx > 9){ ++ sinfo->txrate.mcs = 9; ++ }else{ ++ sinfo->txrate.mcs = rate_info->mcsIndexTx; ++ } ++ 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->txrate.nss = 1; ++ 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; ++ sinfo->rxrate.nss = 1; ++ ++ #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_rate[legrates_lut[rx_vect1->leg_rate]]; ++ 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; ++ 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; ++ break; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ case FORMATMOD_HE_MU: ++ sinfo->rxrate.he_ru_alloc = rx_vect1->he.ru_size; ++ 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; ++ 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; ++ } ++ 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 (RWNX_VIF_TYPE(rwnx_vif) != NL80211_IFTYPE_MESH_POINT) ++ return -ENOTSUPP; ++ ++ 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; ++ ++ /* 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 ++ ++ 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 ++ rwnx_radar_set_domain(&rwnx_hw->radar, request->dfs_region); ++ 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) && testmode == 0)){ ++ rwnx_send_me_chan_config_req(rwnx_hw); ++ } ++} ++ ++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) { ++ 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){ ++ 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 ++ ++extern void *aicwf_prealloc_txq_alloc(size_t size); ++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); ++ ++ /* 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); ++ ++ /* 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) && 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) && testmode == 0)) { ++ rwnx_send_me_chan_config_req(rwnx_hw); ++ } ++ ++ *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); ++ ++ 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 ++ btchr_init(); ++ hdev_init(); ++#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 ++ ++ ++ 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)) ++ del_timer_sync(&defrag_ctrl->defrag_timer); ++ 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 ++ btchr_exit(); ++ hdev_exit(); ++#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 MODULE_IMPORT_NS ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,40 @@ ++/** ++ ****************************************************************************** ++ * ++ * @file rwnx_main.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ ****************************************************************************** ++ */ ++ ++#ifndef _RWNX_MAIN_H_ ++#define _RWNX_MAIN_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 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mesh.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1754 @@ ++/** ++****************************************************************************** ++* ++* @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, 1, 1) ++ COMMON_PARAM(amsdu_rx_max, 2, 2) ++ 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[]; ++ ++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; ++ } ++ ++ 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; ++ } ++ ++ } ++#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; ++ } ++ ++ ++ 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->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; ++ ++ 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] |= 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) ++ 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->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] |= 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){ ++ 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] |= 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) ++ 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; ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++ 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; ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++ 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->mod_params->sgi80 = true; ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid == PRODUCT_ID_AIC8800D80) { ++ rwnx_hw->mod_params->use_80 = true; ++ } ++ ++ if (rwnx_hw->sdiodev->chipid != PRODUCT_ID_AIC8800D80 && ++ 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; ++ ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,70 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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); ++ ++#endif /* _RWNX_MOD_PARAM_H_ */ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1567 @@ ++/** ++ **************************************************************************************** ++ * ++ * @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); ++ } 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_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; ++ } ++ ++ 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); ++ } ++ atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ }else{ ++ atomic_set(&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)); ++ ++ do { ++ bss = cfg80211_get_bss(wdev->wiphy, NULL, rwnx_vif->sta.bssid, ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ wdev->u.client.ssid, wdev->u.client.ssid_len, ++#else ++ wdev->ssid, wdev->ssid_len, ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) ++ wdev->conn_bss_type, ++ IEEE80211_PRIVACY_ANY); ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ++ IEEE80211_BSS_TYPE_ESS, ++ IEEE80211_PRIVACY_ANY); ++#else ++ WLAN_CAPABILITY_ESS, ++ WLAN_CAPABILITY_PRIVACY); ++#endif ++ ++ ++ if (!bss) { ++ printk("%s bss is NULL \r\n", __func__); ++ ++ printk("%s bss ssid(%d):%s conn_bss_type:%d bss2 ssid(%d):%s conn_bss_type:%d\r\n", ++ __func__, ++ (int)rwnx_vif->sta.ssid_len, ++ rwnx_vif->sta.ssid, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ++ IEEE80211_BSS_TYPE_ESS, ++#else ++ WLAN_CAPABILITY_ESS, ++#endif ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ (int)wdev->u.client.ssid_len, ++ wdev->u.client.ssid, ++#else ++ (int)wdev->ssid_len, ++ wdev->ssid, ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) ++ wdev->conn_bss_type ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) ++ IEEE80211_BSS_TYPE_ESS ++#else ++ WLAN_CAPABILITY_ESS ++#endif ++ ); ++ ++ ++ printk("%s rwnx_vif->sta.bssid %02x %02x %02x %02x %02x %02x \r\n", __func__, ++ rwnx_vif->sta.bssid[0], rwnx_vif->sta.bssid[1], rwnx_vif->sta.bssid[2], ++ rwnx_vif->sta.bssid[3], rwnx_vif->sta.bssid[4], rwnx_vif->sta.bssid[5]); ++ ++#if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION ++ wdev->u.client.ssid_len = (int)rwnx_vif->sta.ssid_len; ++ memcpy(wdev->u.client.ssid, rwnx_vif->sta.ssid, wdev->u.client.ssid_len); ++#else ++ wdev->ssid_len = (int)rwnx_vif->sta.ssid_len; ++ memcpy(wdev->ssid, rwnx_vif->sta.ssid, wdev->ssid_len); ++#endif ++ msleep(100); ++ retry_counter--; ++ if(retry_counter == 0){ ++ printk("%s bss recover fail \r\n", __func__); ++ break; ++ } ++ } ++ } while (!bss); ++ ++ 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) { ++ atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } else { ++ atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_DISCONNECTED); ++ rwnx_external_auth_disable(rwnx_vif); ++ } ++ 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 {//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); ++ atomic_set(&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); ++ atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++#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)*/ ++ atomic_set(&rwnx_vif->drv_conn_state, (int)RWNX_DRV_STATUS_CONNECTED); ++ } ++ } ++ netif_tx_start_all_queues(dev); ++ netif_carrier_on(dev); ++ ++ 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); ++ 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_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); ++ atomic_set(&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); ++ ++ 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 (wdev->conn_owner_nlportid != 0) { ++ rwnx_vif->sta.conn_owner_nlportid = wdev->conn_owner_nlportid; ++ } else { ++ AICWFDBG(LOGINFO, "%s try to recover conn_owner_nlportid\r\n", __func__); ++ wdev->conn_owner_nlportid = rwnx_vif->sta.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, ++}; ++ ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_rx.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,3677 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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 20 ++#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 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; ++ u8_l empty = 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", ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++ ++ ++#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 (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 ++ } ++ ++ 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", ++ __func__, reqid, RWNX_ID2STR(reqid), reqcfm, (int)in_irq(), (int)in_softirq(), (int)in_atomic()); ++ ++ 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 ++ #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 ++ #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) { ++ 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; ++} ++ ++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; ++} ++ ++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; ++ ++ int error = 0; ++ ++ 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]; ++ 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\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); ++ /* 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; ++ 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; ++ ++ 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 = 0; ++ ++ get_userconfig_txpwr_lvl_v3_in_fdrv(txpwr_lvl_v3); ++ get_userconfig_txpwr_loss(txpwr_loss); ++ ++ if (txpwr_loss->loss_enable == 1) { ++ AICWFDBG(LOGINFO, "%s:loss_value:%d\r\n", __func__, txpwr_loss->loss_value); ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11b_11ag_2g4[i] += txpwr_loss->loss_value; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_2g4[i] += txpwr_loss->loss_value; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_2g4[i] += txpwr_loss->loss_value; ++ ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11a_5g[i] += txpwr_loss->loss_value; ++ for (i = 0; i <= 9; i++) ++ txpwr_lvl_v3->pwrlvl_11n_11ac_5g[i] += txpwr_loss->loss_value; ++ for (i = 0; i <= 11; i++) ++ txpwr_lvl_v3->pwrlvl_11ax_5g[i] += txpwr_loss->loss_value; ++ } ++ ++ 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_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){ ++ 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); ++} ++ ++/****************************************************************************** ++ * 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->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) ++{ ++ struct me_chan_config_req *req; ++ struct wiphy *wiphy = rwnx_hw->wiphy; ++ int i; ++ ++ 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; ++ ++ 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); ++ 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); ++ 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); ++} ++ ++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(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); ++ } ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) ++ if (link_sta_params->he_capa) { ++ const struct ieee80211_he_cap_elem *he_capa = link_sta_params->he_capa; ++ 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] = 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; ++ } ++ #endif ++#endif ++ ++ 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) ++{ ++ struct me_set_lp_level_req *req; ++ ++ RWNX_DBG(RWNX_FN_ENTRY_STR); ++ ++ /* 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; ++ ++ /* 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; ++ req->chan.flags = 0; ++ 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 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.freq = chandef->chan->center_freq; ++ req->chan.flags = 0; ++ req->center_freq1 = chandef->center_freq1; ++ req->center_freq2 = chandef->center_freq2; ++ req->ch_width = bw2chnl[chandef->width]; ++ ++ /* 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_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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_msg_tx.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,186 @@ ++/** ++ **************************************************************************************** ++ * ++ * @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); ++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); ++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_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_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_lvl_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_v3_req(struct rwnx_hw *rwnx_hw); ++int rwnx_send_txpwr_lvl_adj_req(struct rwnx_hw *rwnx_hw); ++ ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mu_group.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_pci.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2108 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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_adj_conf_t txpwr_lvl_adj; ++ txpwr_loss_conf_t txpwr_loss; ++ txpwr_ofst_conf_t txpwr_ofst; ++ txpwr_ofst2x_conf_t txpwr_ofst2x; ++ 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_loss = { ++ .loss_enable = 1, ++ .loss_value = 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 ++ }, ++ }, ++ .xtal_cap = { ++ .enable = 0, ++ .xtal_cap = 24, ++ .xtal_cap_fine = 31, ++ }, ++}; ++ ++ ++#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 MODULE_IMPORT_NS ++MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver); ++#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_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); ++} ++ ++ ++#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_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, "ofst_5g_ofdm_highrate_chan_42")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[0] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_58")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[1] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_106")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[2] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_122")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[3] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_138")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[4] = rwnx_atoi(value); ++ } else if (!strcmp(command, "ofst_5g_ofdm_highrate_chan_155")) { ++ userconfig_info.txpwr_lvl_adj.pwrlvl_adj_tbl_5g[5] = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_enable")) { ++ userconfig_info.txpwr_loss.loss_enable = rwnx_atoi(value); ++ } else if (!strcmp(command, "loss_value")) { ++ userconfig_info.txpwr_loss.loss_value = 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][0] = 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); ++} ++ ++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_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]); ++} ++ ++/** ++ * 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); ++ } ++ return 0; ++} ++ ++void get_userconfig_txpwr_loss(txpwr_loss_conf_t *txpwr_loss) ++{ ++ txpwr_loss->loss_enable = userconfig_info.txpwr_loss.loss_enable; ++ txpwr_loss->loss_value = userconfig_info.txpwr_loss.loss_value; ++ ++ AICWFDBG(LOGINFO, "%s:loss_enable:%d\r\n", __func__, txpwr_loss->loss_enable); ++ AICWFDBG(LOGINFO, "%s:loss_value:%d\r\n", __func__, txpwr_loss->loss_value); ++} ++ ++/** ++ * 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,136 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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, ++}; ++ ++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); ++ ++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_adj_in_fdrv(txpwr_lvl_adj_conf_t *txpwr_lvl_adj); ++ ++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_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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_prof.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1644 @@ ++/** ++****************************************************************************** ++ * ++ * @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; ++ 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; ++ ++ 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 ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); ++ 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 ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,2501 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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 ++}; ++ ++ ++u16 legrates_lut_rate[] = { ++ 10, ++ 20, ++ 55, ++ 110, ++ 0, ++ 0, ++ 0, ++ 0, ++ 480, ++ 240, ++ 120, ++ 60, ++ 540, ++ 360, ++ 180, ++ 90 ++}; ++ ++ ++const u8 legrates_lut[] = { ++ 0, /* 0 */ ++ 1, /* 1 */ ++ 2, /* 2 */ ++ 3, /* 3 */ ++ -1, /* 4 */ ++ -1, /* 5 */ ++ -1, /* 6 */ ++ -1, /* 7 */ ++ 10, /* 8 */ ++ 8, /* 9 */ ++ 6, /* 10 */ ++ 4, /* 11 */ ++ 11, /* 12 */ ++ 9, /* 13 */ ++ 7, /* 14 */ ++ 5 /* 15 */ ++}; ++ ++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]; ++ 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; ++ 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"); ++ 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"); ++ 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]) == -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)) ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++ 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]; ++ 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); ++ if (timer_pending(&preorder_ctrl->reord_timer)) { ++ ret = del_timer_sync(&preorder_ctrl->reord_timer); ++ } ++ cancel_work_sync(&preorder_ctrl->reord_timer_work); ++ } ++ list_del(&reord_info->list); ++ 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(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 ++ struct reord_ctrl *preorder_ctrl = from_timer(preorder_ctrl, t, reord_timer); ++#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)) { ++ ret = del_timer(&preorder_ctrl->reord_timer); ++ } ++ } ++ ++ 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 ++ defrag_ctrl = from_timer(defrag_ctrl, t, defrag_timer); ++#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; ++ ++ if (hw_rxhdr->is_monitor_vif) { ++ status = RX_STAT_MONITOR; ++ printk("monitor rx\n"); ++ } ++ ++ 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; ++ struct hw_rxhdr hw_rxhdr_copy; ++ u8 rtap_len; ++ u16 frm_len; ++ ++ //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); ++ ++ // Move skb->data pointer to MAC Header or Ethernet header ++ 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; ++ ++ 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); ++ ++ //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 { ++ skb->data = (void *)hw_rxhdr; ++ ++ wiphy_err(rwnx_hw->wiphy, "RX status %d is invalid when MON_DATA is disabled\n", status); ++ goto check_len_update; ++ } ++ ++ skb_reset_tail_pointer(skb); ++ skb->len = 0; ++ 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) { ++ status |= RX_STAT_ALLOC; ++ 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 ++ cfg80211_rx_spurious_frame(rwnx_vif->ndev, hdr->addr2, GFP_ATOMIC); ++#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)) { ++ ret = del_timer(&defrag_info->defrag_timer); ++ } ++ 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, ++ sta->mac_addr, GFP_ATOMIC); ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_rx.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,392 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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; ++}; ++ ++extern const u8 legrates_lut[]; ++extern u16 legrates_lut_rate[]; ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_strs.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,785 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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); ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tdls.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_testmode.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1953 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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" ++ ++/****************************************************************************** ++ * 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]) ++ // rwnx_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) { ++ u16 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; ++ 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); ++ 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; ++ ++ 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 ++ // 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; ++#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 ++ 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 ++ // 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; ++} ++ ++/** ++ * 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 ++ //---------------------------------------------------------------------- ++ ++ /* 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_tx.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,188 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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; ++}; ++ ++/** ++ * 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) */ ++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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,1370 @@ ++/** ++ ****************************************************************************** ++ * ++ * @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; ++ 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_txq.h 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,402 @@ ++/** ++ **************************************************************************************** ++ * ++ * @file rwnx_txq.h ++ * ++ * Copyright (C) RivieraWaves 2012-2019 ++ * ++ **************************************************************************************** ++ */ ++#ifndef _RWNX_TXQ_H_ ++#define _RWNX_TXQ_H_ ++ ++#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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_utils.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_v7.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version_gen.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 "2024_0327_3561b08f" +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.c 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,86 @@ ++#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) ++{ ++ struct wakeup_source *ws; ++ ws = wakeup_source_create(name); ++ wakeup_source_add(ws); ++ return ws; ++} ++ ++void rwnx_wakeup_deinit(struct wakeup_source *ws) ++{ ++ if (ws && ws->active) ++ __pm_relax(ws); ++ wakeup_source_remove(ws); ++ wakeup_source_destroy(ws); ++} ++ ++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); ++} ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_wakelock.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/sdio_host.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.c 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/usb_host.h 2024-06-14 03:58:38.000000000 +0200 +@@ -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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/.gitignore linux-6.9.4/drivers/net/wireless/aic8800_sdio/.gitignore +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/.gitignore 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/.gitignore 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,5 @@ ++*.symvers ++*.order ++*.symvers.cmd ++*.order.cmd ++.tmp_versions/ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/Kconfig linux-6.9.4/drivers/net/wireless/aic8800_sdio/Kconfig +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/Kconfig 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,18 @@ ++config AIC_WLAN_SUPPORT ++ bool "AIC wireless Support" ++ default n ++ help ++ This is support for aic wireless chip. ++ ++config AIC_FW_PATH ++ depends on AIC_WLAN_SUPPORT ++ string "Firmware & config file path" ++ default "/vendor/etc/firmware" ++ #default "/lib/firmware/aic8800_sdio" ++ help ++ Path to the firmware & config file. ++ ++if AIC_WLAN_SUPPORT ++source "drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig" ++source "drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig" ++endif +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/aic8800_sdio/Makefile linux-6.9.4/drivers/net/wireless/aic8800_sdio/Makefile +--- linux-6.9.4/drivers/net/wireless/aic8800_sdio/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.9.4/drivers/net/wireless/aic8800_sdio/Makefile 2024-06-14 03:58:38.000000000 +0200 +@@ -0,0 +1,91 @@ ++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 = n ++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 ++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 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 --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/Kconfig linux-6.9.4/drivers/net/wireless/Kconfig +--- linux-6.9.4/drivers/net/wireless/Kconfig 2024-06-14 17:05:16.121340851 +0200 ++++ linux-6.9.4/drivers/net/wireless/Kconfig 2024-06-14 17:02:21.148011271 +0200 +@@ -37,6 +37,7 @@ + source "drivers/net/wireless/ti/Kconfig" + source "drivers/net/wireless/zydas/Kconfig" + source "drivers/net/wireless/quantenna/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/Kconfig" + + source "drivers/net/wireless/virtual/Kconfig" + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.9.4/drivers/net/wireless/Makefile linux-6.9.4/drivers/net/wireless/Makefile +--- linux-6.9.4/drivers/net/wireless/Makefile 2024-06-14 17:05:16.121340851 +0200 ++++ linux-6.9.4/drivers/net/wireless/Makefile 2024-06-14 17:02:21.148011271 +0200 +@@ -22,5 +22,6 @@ + obj-$(CONFIG_WLAN_VENDOR_ST) += st/ + obj-$(CONFIG_WLAN_VENDOR_TI) += ti/ + obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/ ++obj-$(CONFIG_AIC_SDIO_WLAN_SUPPORT) += aic8800_sdio/ + + obj-$(CONFIG_WLAN) += virtual/ diff --git a/patch/kernel/archive/sunxi-dev-6.14/0802-net-wireless-mm2-fixes-aic8800-sdio-v2024_0327_3561b08f.patch b/patch/kernel/archive/sunxi-dev-6.14/0802-net-wireless-mm2-fixes-aic8800-sdio-v2024_0327_3561b08f.patch new file mode 100644 index 000000000..50bc0aa79 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/0802-net-wireless-mm2-fixes-aic8800-sdio-v2024_0327_3561b08f.patch @@ -0,0 +1,388 @@ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c 2024-11-03 17:06:15.410016386 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_driver.c 2024-11-03 17:04:11.540015950 +0100 +@@ -472,7 +472,7 @@ + #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" ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + + int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) + { +@@ -1489,15 +1489,15 @@ + *(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); ++ printk("%s bt btmode[%d]:%d", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].btmode); ++ printk("%s bt uart_baud[%d]:%d", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_baud); ++ printk("%s bt uart_flowctrl[%d]:%d", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].uart_flowctrl); ++ printk("%s bt lpm_enable[%d]:%d", __func__, sdiodev->chipid, aicbt_info[sdiodev->chipid].lpm_enable); ++ printk("%s bt tx_pwr[%d]:%d", __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); ++ printk("aicbsp: bt patch version: %s", (char *)p->data); + continue; + } + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c 2024-11-03 17:06:15.410016386 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_bsp/aic_bsp_main.c 2024-11-03 17:04:11.540015950 +0100 +@@ -15,7 +15,8 @@ + #define DRV_AUTHOR "AICSemi" + #define DRV_VERS_MOD "1.0" + +-int aicwf_dbg_level_bsp = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; ++//int aicwf_dbg_level_bsp = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; ++int aicwf_dbg_level_bsp = LOGERROR; + + static struct platform_device *aicbsp_pdev; + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c 2024-11-03 17:06:15.420016386 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_btlpm/lpm.c 2024-11-03 17:04:11.540015950 +0100 +@@ -769,6 +769,16 @@ + } + #endif + ++enum of_gpio_flags { ++ OF_GPIO_ACTIVE_LOW = 0x1, ++ OF_GPIO_SINGLE_ENDED = 0x2, ++ OF_GPIO_OPEN_DRAIN = 0x4, ++ OF_GPIO_TRANSITORY = 0x8, ++ OF_GPIO_PULL_UP = 0x10, ++ OF_GPIO_PULL_DOWN = 0x20, ++ OF_GPIO_PULL_DISABLE = 0x40, ++}; ++ + static int bluesleep_probe(struct platform_device *pdev) + { + #if 1 +@@ -783,7 +793,7 @@ + if (!bsi) + return -ENOMEM; + +- bsi->host_wake = of_get_named_gpio_flags(np, "bt_hostwake", 0, &config); ++ bsi->host_wake = of_get_named_gpio(np, "bt_hostwake", 0); + if (!gpio_is_valid(bsi->host_wake)) { + BT_ERR("get gpio bt_hostwake failed\n"); + ret = -EINVAL; +@@ -791,7 +801,7 @@ + } + + /* set host_wake_assert */ +- bsi->host_wake_assert = (config == OF_GPIO_ACTIVE_LOW) ? 0 : 1; ++ bsi->host_wake_assert = (config == GPIOF_ACTIVE_LOW) ? 0 : 1; + BT_DBG("bt_hostwake gpio=%d assert=%d\n", bsi->host_wake, bsi->host_wake_assert); + + if (assert_level != -1) { +@@ -838,7 +848,7 @@ + #endif + } + +- bsi->ext_wake = of_get_named_gpio_flags(np, "bt_wake", 0, &config); ++ bsi->ext_wake = of_get_named_gpio(np, "bt_wake", 0); + if (!gpio_is_valid(bsi->ext_wake)) { + BT_ERR("get gpio bt_wake failed\n"); + ret = -EINVAL; +@@ -911,11 +921,11 @@ + return 0; + + err3: +- devm_gpio_free(dev, bsi->ext_wake); ++ //todo devm_gpio_free(dev, bsi->ext_wake); + err2: + device_init_wakeup(dev, false); + err1: +- devm_gpio_free(dev, bsi->host_wake); ++ //todo devm_gpio_free(dev, bsi->host_wake); + err0: + devm_kfree(dev, bsi); + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c 2024-11-03 17:06:15.423349720 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/aicwf_sdio.c 2024-11-03 17:04:11.540015950 +0100 +@@ -529,15 +529,15 @@ + + 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__); ++ AICWFDBG(LOGINFO, "%s USE AIC8801\r", __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__); ++ AICWFDBG(LOGINFO, "%s USE AIC8800DC\r", __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__); ++ AICWFDBG(LOGINFO, "%s USE AIC8800D80\r", __func__); + return 0; + }else{ + return -1; +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile 2024-11-03 17:06:15.423349720 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Makefile 2024-11-03 17:04:11.540015950 +0100 +@@ -132,7 +132,7 @@ + + # extra DEBUG config + CONFIG_RWNX_SW_PROFILING ?= n +-CONFIG_RWNX_DBG ?= y ++CONFIG_RWNX_DBG ?= n + CONFIG_DEBUG_FS ?= n + + obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o +@@ -203,6 +203,8 @@ + ccflags-y += -DNX_TX_MAX_RATES=4 + ccflags-y += -DNX_CHAN_CTXT_CNT=3 + ++ccflags-y += -Wno-incompatible-pointer-types ++ + # FW ARCH: + ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM + ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4 +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c 2024-11-03 17:06:15.426683053 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_main.c 2024-11-03 17:04:11.540015950 +0100 +@@ -510,7 +510,8 @@ + + + extern uint8_t scanning; +-int aicwf_dbg_level = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; ++//int aicwf_dbg_level = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; ++int aicwf_dbg_level = LOGERROR; + module_param(aicwf_dbg_level, int, 0660); + int testmode = 0; + char aic_fw_path[200]; +@@ -770,7 +771,11 @@ + cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL); + #endif + } else { ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) ++ wiphy_lock(vif->wdev.wiphy); ++#else + mutex_lock(&vif->wdev.mtx); ++#endif + __acquire(&vif->wdev.mtx); + spin_lock_bh(&rwnx_hw->cb_lock); + rwnx_chanctx_unlink(vif); +@@ -782,13 +787,17 @@ + rwnx_txq_vif_stop(vif, RWNX_TXQ_STOP_CHAN, rwnx_hw); + spin_unlock_bh(&rwnx_hw->cb_lock); + #if (LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION3) +- cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 0, 0); ++ cfg80211_ch_switch_notify(vif->ndev, &csa->chandef, 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(6, 7, 0)) ++ wiphy_lock(vif->wdev.wiphy); ++#else + mutex_unlock(&vif->wdev.mtx); ++#endif + __release(&vif->wdev.mtx); + } + rwnx_del_csa(vif); +@@ -3013,10 +3022,11 @@ + 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; ++ !(!memcmp(master_vif->ndev->dev_addr, params->macaddr, ETH_ALEN))) ++ { ++ memcmp(master_vif->ndev->dev_addr_shadow, params->macaddr, ETH_ALEN); ++ found = true; ++ break; + } + } + +@@ -5561,7 +5571,7 @@ + } else { + INIT_WORK(&csa->work, rwnx_csa_finish); + #if LINUX_VERSION_CODE >= HIGH_KERNEL_VERSION4 +- cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false, 0); ++ cfg80211_ch_switch_started_notify(dev, &csa->chandef, 0, params->count, false); + #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) +@@ -6565,8 +6575,8 @@ + .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, ++ //todo .tdls_mgmt = rwnx_cfg80211_tdls_mgmt, ++ //todo .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, +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c 2024-11-03 17:06:15.430016386 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_mod_params.c 2024-11-03 17:04:11.540015950 +0100 +@@ -1546,9 +1546,6 @@ + // 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; + wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; + wiphy_apply_custom_regulatory(wiphy, regdomain); +@@ -1580,9 +1577,6 @@ + // 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; + wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; + wiphy_apply_custom_regulatory(wiphy, &rwnx_regdom); +@@ -1725,11 +1719,15 @@ + // 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; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0) ++ // nop ++#else ++ wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; ++#endif ++ wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; + +- wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF; +- wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED; ++ if (!rwnx_hw->mod_params->custregd) ++ return; + + rtnl_lock(); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) +@@ -1743,10 +1741,7 @@ + #endif + + else{ +- wiphy_err(wiphy,"\n" +- "*******************************************************\n" +- "** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES **\n" +- "*******************************************************\n"); ++ // + } + rtnl_unlock(); + #endif +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c 2024-11-03 17:06:15.430016386 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_platform.c 2024-11-03 17:04:11.540015950 +0100 +@@ -271,7 +271,7 @@ + #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" ++#define MD5PINRT "file md5:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + + static int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device) + { +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c 2024-11-03 17:06:15.430016386 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_radar.c 2024-11-03 16:42:50.616678220 +0100 +@@ -1399,7 +1399,7 @@ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + &ctxt->chan_def, + #endif +- NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); ++ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0); + rwnx_send_apm_stop_cac_req(rwnx_hw, radar->cac_vif); + rwnx_chanctx_unlink(radar->cac_vif); + +@@ -1499,7 +1499,7 @@ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) + &ctxt->chan_def, + #endif +- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); ++ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); + rwnx_chanctx_unlink(radar->cac_vif); + } + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h 2024-11-03 17:06:15.433349720 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/aic8800_fdrv/rwnx_version.h 2024-11-03 17:04:11.540015950 +0100 +@@ -6,7 +6,7 @@ + static inline void rwnx_print_version(void) + { + AICWFDBG(LOGINFO, RWNX_VERS_BANNER"\n"); +- AICWFDBG(LOGINFO, "RELEASE_DATE:%s \r\n", RELEASE_DATE); ++ AICWFDBG(LOGINFO, "RELEASE_DATE:%s \r", RELEASE_DATE); + } + + #endif /* _RWNX_VERSION_H_ */ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/.gitignore linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/.gitignore +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/.gitignore 2024-11-03 17:06:15.433349720 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/.gitignore 1970-01-01 01:00:00.000000000 +0100 +@@ -1,5 +0,0 @@ +-*.symvers +-*.order +-*.symvers.cmd +-*.order.cmd +-.tmp_versions/ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Kconfig linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Kconfig +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Kconfig 2024-11-03 17:06:15.433349720 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Kconfig 2024-11-03 17:04:11.540015950 +0100 +@@ -1,18 +1,17 @@ +-config AIC_WLAN_SUPPORT +- bool "AIC wireless Support" ++config AIC_SDIO_WLAN_SUPPORT ++ bool "AIC 8800 SDIO wireless Support" + default n + help +- This is support for aic wireless chip. ++ This is support for aic 8800 wireless chip with SDIO interface. + + config AIC_FW_PATH +- depends on AIC_WLAN_SUPPORT ++ depends on AIC_SDIO_WLAN_SUPPORT + string "Firmware & config file path" +- default "/vendor/etc/firmware" +- #default "/lib/firmware/aic8800_sdio" ++ default "/lib/firmware/aic8800_sdio" + help + Path to the firmware & config file. + +-if AIC_WLAN_SUPPORT +-source "drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig" +-source "drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig" ++if AIC_SDIO_WLAN_SUPPORT ++source "drivers/net/wireless/aic8800_sdio/aic8800_fdrv/Kconfig" ++source "drivers/net/wireless/aic8800_sdio/aic8800_btlpm/Kconfig" + endif +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Makefile linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Makefile +--- linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Makefile 2024-11-03 17:06:15.433349720 +0100 ++++ linux-6.12-rc5/drivers/net/wireless/aic8800_sdio/Makefile 2024-11-03 17:04:11.543349283 +0100 +@@ -1,12 +1,10 @@ + CONFIG_AIC8800_BTLPM_SUPPORT := m + CONFIG_AIC8800_WLAN_SUPPORT := m +-CONFIG_AIC_WLAN_SUPPORT := m ++CONFIG_AIC_SDIO_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) ++obj-$(CONFIG_AIC_SDIO_WLAN_SUPPORT) += aic8800_bsp/ + + ########## config option ########## + export CONFIG_USE_FW_REQUEST = n diff --git a/patch/kernel/archive/sunxi-dev-6.14/1103-mfd-axp20x-Allow-multiple-regulators.patch b/patch/kernel/archive/sunxi-dev-6.14/1103-mfd-axp20x-Allow-multiple-regulators.patch new file mode 100644 index 000000000..7fd333498 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/1103-mfd-axp20x-Allow-multiple-regulators.patch @@ -0,0 +1,60 @@ +From 12045a9ab272974528afea72781f5308c662a1d0 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Tue, 1 Oct 2024 22:28:41 +0100 +Subject: [PATCH 03/37] mfd: axp20x: Allow multiple regulators + +At the moment trying to register a second AXP chip makes the probe fail, +as some sysfs registration fails due to a duplicate name: + +... +[ 3.688215] axp20x-i2c 0-0035: AXP20X driver loaded +[ 3.695610] axp20x-i2c 0-0036: AXP20x variant AXP323 found +[ 3.706151] sysfs: cannot create duplicate filename '/bus/platform/devices/axp20x-regulator' +[ 3.714718] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.0-rc1-00026-g50bf2e2c079d-dirty #192 +[ 3.724020] Hardware name: Avaota A1 (DT) +[ 3.728029] Call trace: +[ 3.730477] dump_backtrace+0x94/0xec +[ 3.734146] show_stack+0x18/0x24 +[ 3.737462] dump_stack_lvl+0x80/0xf4 +[ 3.741128] dump_stack+0x18/0x24 +[ 3.744444] sysfs_warn_dup+0x64/0x80 +[ 3.748109] sysfs_do_create_link_sd+0xf0/0xf8 +[ 3.752553] sysfs_create_link+0x20/0x40 +[ 3.756476] bus_add_device+0x64/0x104 +[ 3.760229] device_add+0x310/0x760 +[ 3.763717] platform_device_add+0x10c/0x238 +[ 3.767990] mfd_add_device+0x4ec/0x5c8 +[ 3.771829] mfd_add_devices+0x88/0x11c +[ 3.775666] axp20x_device_probe+0x70/0x184 +[ 3.779851] axp20x_i2c_probe+0x9c/0xd8 +... + +This is because we use PLATFORM_DEVID_NONE for the mfd_add_devices() +call, which would number the child devices in the same 0-based way, even +for the second (or any other) instance. + +Use PLATFORM_DEVID_AUTO instead, which automatically assigns +non-conflicting device numbers. + +Signed-off-by: Andre Przywara +Reviewed-by: Chen-Yu Tsai +--- + drivers/mfd/axp20x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c +index 5ceea359289..bc08ae43326 100644 +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -1419,7 +1419,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) + } + } + +- ret = mfd_add_devices(axp20x->dev, PLATFORM_DEVID_NONE, axp20x->cells, ++ ret = mfd_add_devices(axp20x->dev, PLATFORM_DEVID_AUTO, axp20x->cells, + axp20x->nr_cells, NULL, 0, NULL); + + if (ret) { +-- +2.46.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.14/1137-net-phy-add-Maxio-MAE0621A-phy-driver.patch b/patch/kernel/archive/sunxi-dev-6.14/1137-net-phy-add-Maxio-MAE0621A-phy-driver.patch new file mode 100644 index 000000000..cda59311d --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/1137-net-phy-add-Maxio-MAE0621A-phy-driver.patch @@ -0,0 +1,368 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: John Doe +Date: Sat, 15 Mar 2025 00:57:55 -0300 +Subject: [PATCH] Add Maxio MAE0621A PHY driver + +Signed-off-by: John Doe +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 + + drivers/net/phy/Kconfig | 5 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/maxio.c | 254 ++++++++++ + drivers/net/phy/phy_device.c | 9 + + 5 files changed, 274 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index d04543e5697b..c8cf84fa4091 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -7826,10 +7826,11 @@ int stmmac_suspend(struct device *dev) + + priv->speed = SPEED_UNKNOWN; + return 0; + } + EXPORT_SYMBOL_GPL(stmmac_suspend); ++#define MAXIO_PHY_MAE0621A_ID 0x7b744411 + + static void stmmac_reset_rx_queue(struct stmmac_priv *priv, u32 queue) + { + struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue]; + +@@ -7922,10 +7923,14 @@ int stmmac_resume(struct device *dev) + + stmmac_reset_queues_param(priv); + + stmmac_free_tx_skbufs(priv); + stmmac_clear_descriptors(priv, &priv->dma_conf); ++ if (ndev->phydev->drv->config_init) { ++ if (ndev->phydev->phy_id == MAXIO_PHY_MAE0621A_ID) ++ ndev->phydev->drv->config_init(ndev->phydev); ++ } + + stmmac_hw_setup(ndev, false); + stmmac_init_coalesce(priv); + stmmac_set_rx_mode(ndev); + +diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +index 41c15a2c2037..6a5de0ce5723 100644 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -360,10 +360,15 @@ config RENESAS_PHY + config ROCKCHIP_PHY + tristate "Rockchip Ethernet PHYs" + help + Currently supports the integrated Ethernet PHY. + ++config MAXIO_PHY ++ tristate "Maxio PHYs" ++ help ++ Supports the Maxio MAExxxx PHY. ++ + config SMSC_PHY + tristate "SMSC PHYs" + select CRC16 + help + Currently supports the LAN83C185, LAN8187 and LAN8700 PHYs +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index c8dac6e92278..2bdde53a3885 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -94,10 +94,11 @@ obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja.o + obj-$(CONFIG_NXP_CBTX_PHY) += nxp-cbtx.o + obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o + obj-y += qcom/ + obj-$(CONFIG_QSEMI_PHY) += qsemi.o + obj-$(CONFIG_REALTEK_PHY) += realtek/ ++obj-$(CONFIG_MAXIO_PHY) += maxio.o + obj-$(CONFIG_RENESAS_PHY) += uPD60620.o + obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o + obj-$(CONFIG_SMSC_PHY) += smsc.o + obj-$(CONFIG_STE10XP) += ste10Xp.o + obj-$(CONFIG_TERANETICS_PHY) += teranetics.o +diff --git a/drivers/net/phy/maxio.c b/drivers/net/phy/maxio.c +new file mode 100644 +index 000000000000..fd227e86794f +--- /dev/null ++++ b/drivers/net/phy/maxio.c +@@ -0,0 +1,254 @@ ++/* ++ * drivers/net/phy/maxio.c ++ * ++ * Driver for maxio PHYs ++ * ++ * Author: zhao yang ++ * ++ * Copyright (c) 2004 maxio technology, Inc. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAXIO_PAGE_SELECT 0x1f ++#define MAXIO_MAE0621A_INER 0x12 ++#define MAXIO_MAE0621A_INER_LINK_STATUS BIT(4) ++#define MAXIO_MAE0621A_INSR 0x1d ++#define MAXIO_MAE0621A_TX_DELAY (BIT(6)|BIT(7)) ++#define MAXIO_MAE0621A_RX_DELAY (BIT(4)|BIT(5)) ++#define MAXIO_MAE0621A_CLK_MODE_REG 0x02 ++#define MAXIO_MAE0621A_WORK_STATUS_REG 0x1d ++ ++ ++static int maxio_read_paged(struct phy_device *phydev, int page, u32 regnum) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = phy_read(phydev, MAXIO_PAGE_SELECT); ++ if (oldpage >= 0) { ++ phy_write(phydev, MAXIO_PAGE_SELECT, page); ++ ret = phy_read(phydev, regnum); ++ } ++ phy_write(phydev, MAXIO_PAGE_SELECT, oldpage); ++ ++ return ret; ++} ++ ++static int maxio_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val) ++{ ++ int ret = 0, oldpage; ++ ++ oldpage = phy_read(phydev, MAXIO_PAGE_SELECT); ++ if (oldpage >= 0) { ++ phy_write(phydev, MAXIO_PAGE_SELECT, page); ++ ret = phy_write(phydev, regnum, val); ++ } ++ phy_write(phydev, MAXIO_PAGE_SELECT, oldpage); ++ ++ return ret; ++} ++ ++static int maxio_mae0621a_clk_init(struct phy_device *phydev) ++{ ++ u32 workmode,clkmode,oldpage; ++ ++ oldpage = phy_read(phydev, MAXIO_PAGE_SELECT); ++ if (oldpage == 0xFFFF) { ++ oldpage = phy_read(phydev, MAXIO_PAGE_SELECT); ++ } ++ ++ //soft reset ++ phy_write(phydev, MAXIO_PAGE_SELECT, 0x0); ++ phy_write(phydev, MII_BMCR, BMCR_RESET | phy_read(phydev, MII_BMCR)); ++ ++ //get workmode ++ phy_write(phydev, MAXIO_PAGE_SELECT, 0xa43); ++ workmode = phy_read(phydev, MAXIO_MAE0621A_WORK_STATUS_REG); ++ ++ //get clkmode ++ phy_write( phydev, MAXIO_PAGE_SELECT, 0xd92 ); ++ clkmode = phy_read( phydev, MAXIO_MAE0621A_CLK_MODE_REG ); ++ ++ //abnormal ++ if (0 == (workmode&BIT(5))) { ++ if (0 == (clkmode&BIT(8))) { ++ //oscillator ++ phy_write(phydev, 0x02, clkmode | BIT(8)); ++ printk("****maxio_mae0621a_clk_init**clkmode**0x210a: 0x%x\n", phydev->phy_id); ++ } else { ++ //crystal ++ printk("****maxio_mae0621a_clk_init**clkmode**0x200a: 0x%x\n", phydev->phy_id); ++ phy_write(phydev, 0x02, clkmode &(~ BIT(8))); ++ } ++ } ++ phy_write(phydev, MAXIO_PAGE_SELECT, 0x0); ++ ++ phy_write(phydev, MAXIO_PAGE_SELECT, oldpage); ++ ++ return 0; ++} ++ ++static int maxio_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) ++{ ++ int ret = 0, oldpage; ++ oldpage = phy_read(phydev, MAXIO_PAGE_SELECT); ++ ++ if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {// eee info ++ phy_write(phydev, MAXIO_PAGE_SELECT ,0); ++ phy_write(phydev, 0xd, MDIO_MMD_AN); ++ phy_write(phydev, 0xe, MDIO_AN_EEE_ADV); ++ phy_write(phydev, 0xd, 0x4000 | MDIO_MMD_AN); ++ ret = phy_read(phydev, 0x0e); ++ } else { ++ ret = -EOPNOTSUPP; ++ } ++ phy_write(phydev, MAXIO_PAGE_SELECT, oldpage); ++ ++ return ret; ++} ++ ++static int maxio_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, u16 val) ++{ ++ int ret = 0, oldpage; ++ oldpage = phy_read(phydev, MAXIO_PAGE_SELECT); ++ ++ if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) { // eee info ++ phy_write(phydev, MAXIO_PAGE_SELECT ,0); ++ ret |= phy_write(phydev, 0xd, MDIO_MMD_AN); ++ ret |= phy_write(phydev, 0xe, MDIO_AN_EEE_ADV); ++ ret |= phy_write(phydev, 0xd, 0x4000 | MDIO_MMD_AN); ++ ret |= phy_write(phydev, 0xe, val); ++ msleep(100); ++ ret |= genphy_restart_aneg(phydev); ++ } else { ++ ret = -EOPNOTSUPP; ++ } ++ phy_write(phydev, MAXIO_PAGE_SELECT, oldpage); ++ ++ return ret; ++} ++ ++static int maxio_mae0621a_config_aneg(struct phy_device *phydev) ++{ ++ return genphy_config_aneg(phydev); ++} ++ ++ ++static int maxio_mae0621a_config_init(struct phy_device *phydev) ++{ ++ struct device *dev = &phydev->mdio.dev; ++ u16 val; ++ int ret; ++ u32 broken = 0; ++ ++ maxio_mae0621a_clk_init(phydev); ++ ++ //disable eee ++ printk("eee value: 0x%x \n",maxio_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV)); ++ maxio_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0); ++ printk("eee value: 0x%x \n",maxio_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV)); ++ broken |= MDIO_EEE_100TX; ++ broken |= MDIO_EEE_1000T; ++ memcpy(phydev->eee_broken_modes, broken, sizeof(phydev->eee_broken_modes)); ++ ++ //enable auto_speed_down ++ ret = maxio_write_paged(phydev, 0xd8f, 0x0, 0x300 ); ++ ++ //adjust TX/RX delay ++ switch (phydev->interface) { ++ case PHY_INTERFACE_MODE_RGMII: ++ val = 0x0; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ val = MAXIO_MAE0621A_TX_DELAY | MAXIO_MAE0621A_RX_DELAY; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ val = MAXIO_MAE0621A_RX_DELAY; ++ break; ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ val = MAXIO_MAE0621A_TX_DELAY; ++ break; ++ default: /* the rest of the modes imply leaving delays as is. */ ++ goto delay_skip; ++ } ++ ++ ret = maxio_read_paged(phydev, 0xd96, 0x0); ++ if (ret < 0) { ++ dev_err(dev, "Failed to update the TX delay register\n"); ++ return ret; ++ } ++ ++ ret =maxio_write_paged(phydev, 0xd96, 0x0, val|ret ); ++ if (ret < 0) { ++ dev_err(dev, "Failed to update the TX delay register\n"); ++ return ret; ++ } else if (ret == 0) { ++ dev_dbg(dev, ++ "2ns delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n", ++ val ? "enabled" : "disabled"); ++ } ++delay_skip: ++ ++ phy_write(phydev, MII_BMCR, BMCR_RESET | phy_read(phydev, MII_BMCR)); ++ msleep(1); ++ phy_write(phydev, MAXIO_PAGE_SELECT, 0x0); ++ ++ return 0; ++} ++ ++ ++static int maxio_mae0621a_resume(struct phy_device *phydev) ++{ ++ int ret = genphy_resume(phydev); ++ ++ ret |= phy_write(phydev, MII_BMCR, BMCR_RESET | phy_read(phydev, MII_BMCR)); ++ ++ msleep(20); ++ ++ return ret; ++} ++ ++int maxio_mae0621a_suspend(struct phy_device *phydev) ++{ ++ genphy_suspend(phydev); ++ phy_write(phydev, MAXIO_PAGE_SELECT ,0); ++ ++ return 0; ++} ++ ++static int maxio_mae0621a_status(struct phy_device *phydev) ++{ ++ return genphy_read_status(phydev); ++} ++ ++static int maxio_mae0621a_probe(struct phy_device *phydev) ++{ ++ int ret = maxio_mae0621a_clk_init(phydev); ++ mdelay(100); ++ return ret; ++} ++ ++static struct phy_driver maxio_nc_drvs[] = { ++ { ++ .phy_id = 0x7b744411, ++ .phy_id_mask = 0x7fffffff, ++ .name = "MAE0621A Gigabit Ethernet", ++ .features = PHY_GBIT_FEATURES, ++ .probe = maxio_mae0621a_probe, ++ .config_init = maxio_mae0621a_config_init, ++ .config_aneg = maxio_mae0621a_config_aneg, ++ .read_status = maxio_mae0621a_status, ++ .suspend = maxio_mae0621a_suspend, ++ .resume = maxio_mae0621a_resume, ++ }, ++}; ++module_phy_driver(maxio_nc_drvs); ++ ++MODULE_DESCRIPTION("Maxio PHY driver"); ++MODULE_AUTHOR("Zhao Yang"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 46713d27412b..1a9514360673 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -858,10 +858,19 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, + */ + static int get_phy_c22_id(struct mii_bus *bus, int addr, u32 *phy_id) + { + int phy_reg; + ++#ifdef CONFIG_MAXIO_PHY ++ /* ++ *An MDIO connects to multiple PHYs requiring write before read. ++ *This operation does not affect one MDIO connected to a single PHY ++ *MII_PHYSID2 is a read-only register and writine to it has no effect ++ */ ++ mdiobus_write(bus,addr,MII_PHYSID2,0); ++#endif ++ + /* Grab the bits from PHYIR1, and put them in the upper half */ + phy_reg = mdiobus_read(bus, addr, MII_PHYSID1); + if (phy_reg < 0) { + /* returning -ENODEV doesn't stop bus scanning */ + return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO; +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.14/1139-net-ethernet-allwinner-add-gmac200-support.patch b/patch/kernel/archive/sunxi-dev-6.14/1139-net-ethernet-allwinner-add-gmac200-support.patch new file mode 100644 index 000000000..99f67bc5e --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/1139-net-ethernet-allwinner-add-gmac200-support.patch @@ -0,0 +1,3238 @@ + +Code is backport from BSP kernel + +Signed-off-by: Piotr Oniszczuk + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.c linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.c +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.c 2025-01-21 15:58:05.577494134 +0100 +@@ -0,0 +1,829 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++* Allwinner DWMAC driver. ++* ++* Copyright(c) 2022-2027 Allwinnertech Co., Ltd. ++* ++* This file is licensed under the terms of the GNU General Public ++* License version 2. This program is licensed "as is" without any ++* warranty of any kind, whether express or implied. ++*/ ++#define SUNXI_MODNAME "stmmac" ++#include "sunxi-log.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "stmmac/stmmac.h" ++#include "stmmac/stmmac_platform.h" ++ ++#include "dwmac-sunxi.h" ++ ++#define DWMAC_MODULE_VERSION "0.3.0" ++ ++#define MAC_ADDR_LEN 18 ++#define SUNXI_DWMAC_MAC_ADDRESS "80:3f:5d:09:8b:26" ++#define MAC_IRQ_NAME 8 ++ ++static char mac_str[MAC_ADDR_LEN] = SUNXI_DWMAC_MAC_ADDRESS; ++module_param_string(mac_str, mac_str, MAC_ADDR_LEN, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mac_str, "MAC Address String.(xx:xx:xx:xx:xx:xx)"); ++ ++//todo #ifdef MODULE ++//extern int get_custom_mac_address(int fmt, char *name, char *addr); ++//#endif ++ ++static int sunxi_dwmac200_set_syscon(struct sunxi_dwmac *chip) ++{ ++ u32 reg_val = 0; ++ ++ /* Clear interface mode bits */ ++ reg_val &= ~(SUNXI_DWMAC200_SYSCON_ETCS | SUNXI_DWMAC200_SYSCON_EPIT); ++ if (chip->variant->interface & PHY_INTERFACE_MODE_RMII) ++ reg_val &= ~SUNXI_DWMAC200_SYSCON_RMII_EN; ++ ++ switch (chip->interface) { ++ case PHY_INTERFACE_MODE_MII: ++ /* default */ ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ reg_val |= SUNXI_DWMAC200_SYSCON_EPIT; ++ reg_val |= FIELD_PREP(SUNXI_DWMAC200_SYSCON_ETCS, ++ chip->rgmii_clk_ext ? SUNXI_DWMAC_ETCS_EXT_GMII : SUNXI_DWMAC_ETCS_INT_GMII); ++ if (chip->rgmii_clk_ext) ++ sunxi_info(chip->dev, "RGMII use external transmit clock\n"); ++ else ++ sunxi_info(chip->dev, "RGMII use internal transmit clock\n"); ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ reg_val |= SUNXI_DWMAC200_SYSCON_RMII_EN; ++ reg_val &= ~SUNXI_DWMAC200_SYSCON_ETCS; ++ break; ++ default: ++ sunxi_err(chip->dev, "Unsupported interface mode: %s", phy_modes(chip->interface)); ++ return -EINVAL; ++ } ++ ++ writel(reg_val, chip->syscfg_base + SUNXI_DWMAC200_SYSCON_REG); ++ return 0; ++} ++ ++static int sunxi_dwmac200_set_delaychain(struct sunxi_dwmac *chip, enum sunxi_dwmac_delaychain_dir dir, u32 delay) ++{ ++ u32 reg_val = readl(chip->syscfg_base + SUNXI_DWMAC200_SYSCON_REG); ++ int ret = -EINVAL; ++ ++ switch (dir) { ++ case SUNXI_DWMAC_DELAYCHAIN_TX: ++ if (delay <= chip->variant->tx_delay_max) { ++ reg_val &= ~SUNXI_DWMAC200_SYSCON_ETXDC; ++ reg_val |= FIELD_PREP(SUNXI_DWMAC200_SYSCON_ETXDC, delay); ++ ret = 0; ++ } ++ break; ++ case SUNXI_DWMAC_DELAYCHAIN_RX: ++ if (delay <= chip->variant->rx_delay_max) { ++ reg_val &= ~SUNXI_DWMAC200_SYSCON_ERXDC; ++ reg_val |= FIELD_PREP(SUNXI_DWMAC200_SYSCON_ERXDC, delay); ++ ret = 0; ++ } ++ break; ++ } ++ ++ if (!ret) ++ writel(reg_val, chip->syscfg_base + SUNXI_DWMAC200_SYSCON_REG); ++ ++ return ret; ++} ++ ++static u32 sunxi_dwmac200_get_delaychain(struct sunxi_dwmac *chip, enum sunxi_dwmac_delaychain_dir dir) ++{ ++ u32 delay = 0; ++ u32 reg_val = readl(chip->syscfg_base + SUNXI_DWMAC200_SYSCON_REG); ++ ++ switch (dir) { ++ case SUNXI_DWMAC_DELAYCHAIN_TX: ++ delay = FIELD_GET(SUNXI_DWMAC200_SYSCON_ETXDC, reg_val); ++ break; ++ case SUNXI_DWMAC_DELAYCHAIN_RX: ++ delay = FIELD_GET(SUNXI_DWMAC200_SYSCON_ERXDC, reg_val); ++ break; ++ default: ++ sunxi_err(chip->dev, "Unknow delaychain dir %d\n", dir); ++ } ++ ++ return delay; ++} ++ ++static int sunxi_dwmac210_set_delaychain(struct sunxi_dwmac *chip, enum sunxi_dwmac_delaychain_dir dir, u32 delay) ++{ ++ u32 reg_val = readl(chip->syscfg_base + SUNXI_DWMAC210_CFG_REG); ++ int ret = -EINVAL; ++ ++ switch (dir) { ++ case SUNXI_DWMAC_DELAYCHAIN_TX: ++ if (delay <= chip->variant->tx_delay_max) { ++ reg_val &= ~(SUNXI_DWMAC210_CFG_ETXDC_H | SUNXI_DWMAC210_CFG_ETXDC_L); ++ reg_val |= FIELD_PREP(SUNXI_DWMAC210_CFG_ETXDC_H, delay >> 3); ++ reg_val |= FIELD_PREP(SUNXI_DWMAC210_CFG_ETXDC_L, delay); ++ ret = 0; ++ } ++ break; ++ case SUNXI_DWMAC_DELAYCHAIN_RX: ++ if (delay <= chip->variant->rx_delay_max) { ++ reg_val &= ~SUNXI_DWMAC210_CFG_ERXDC; ++ reg_val |= FIELD_PREP(SUNXI_DWMAC210_CFG_ERXDC, delay); ++ ret = 0; ++ } ++ break; ++ } ++ ++ if (!ret) ++ writel(reg_val, chip->syscfg_base + SUNXI_DWMAC210_CFG_REG); ++ ++ return ret; ++} ++ ++static u32 sunxi_dwmac210_get_delaychain(struct sunxi_dwmac *chip, enum sunxi_dwmac_delaychain_dir dir) ++{ ++ u32 delay = 0; ++ u32 tx_l, tx_h; ++ u32 reg_val = readl(chip->syscfg_base + SUNXI_DWMAC210_CFG_REG); ++ ++ switch (dir) { ++ case SUNXI_DWMAC_DELAYCHAIN_TX: ++ tx_h = FIELD_GET(SUNXI_DWMAC210_CFG_ETXDC_H, reg_val); ++ tx_l = FIELD_GET(SUNXI_DWMAC210_CFG_ETXDC_L, reg_val); ++ delay = (tx_h << 3 | tx_l); ++ break; ++ case SUNXI_DWMAC_DELAYCHAIN_RX: ++ delay = FIELD_GET(SUNXI_DWMAC210_CFG_ERXDC, reg_val); ++ break; ++ } ++ ++ return delay; ++} ++ ++static int sunxi_dwmac110_get_version(struct sunxi_dwmac *chip, u16 *ip_tag, u16 *ip_vrm) ++{ ++ u32 reg_val; ++ ++ if (!ip_tag || !ip_vrm) ++ return -EINVAL; ++ ++ reg_val = readl(chip->syscfg_base + SUNXI_DWMAC110_VERSION_REG); ++ *ip_tag = FIELD_GET(SUNXI_DWMAC110_VERSION_IP_TAG, reg_val); ++ *ip_vrm = FIELD_GET(SUNXI_DWMAC110_VERSION_IP_VRM, reg_val); ++ return 0; ++} ++ ++static int sunxi_dwmac_power_on(struct sunxi_dwmac *chip) ++{ ++ int ret; ++ ++ /* set dwmac pin bank voltage to 3.3v */ ++ if (!IS_ERR(chip->dwmac3v3_supply)) { ++ ret = regulator_set_voltage(chip->dwmac3v3_supply, 3300000, 3300000); ++ if (ret) { ++ sunxi_err(chip->dev, "Set dwmac3v3-supply voltage 3300000 failed %d\n", ret); ++ goto err_dwmac3v3; ++ } ++ ++ ret = regulator_enable(chip->dwmac3v3_supply); ++ if (ret) { ++ sunxi_err(chip->dev, "Enable dwmac3v3-supply failed %d\n", ret); ++ goto err_dwmac3v3; ++ } ++ } ++ ++ /* set phy voltage to 3.3v */ ++ if (!IS_ERR(chip->phy3v3_supply)) { ++ ret = regulator_set_voltage(chip->phy3v3_supply, 3300000, 3300000); ++ if (ret) { ++ sunxi_err(chip->dev, "Set phy3v3-supply voltage 3300000 failed %d\n", ret); ++ goto err_phy3v3; ++ } ++ ++ ret = regulator_enable(chip->phy3v3_supply); ++ if (ret) { ++ sunxi_err(chip->dev, "Enable phy3v3-supply failed\n"); ++ goto err_phy3v3; ++ } ++ } ++ ++ return 0; ++ ++err_phy3v3: ++ regulator_disable(chip->dwmac3v3_supply); ++err_dwmac3v3: ++ return ret; ++} ++ ++static void sunxi_dwmac_power_off(struct sunxi_dwmac *chip) ++{ ++ if (!IS_ERR(chip->phy3v3_supply)) ++ regulator_disable(chip->phy3v3_supply); ++ if (!IS_ERR(chip->dwmac3v3_supply)) ++ regulator_disable(chip->dwmac3v3_supply); ++} ++ ++static int sunxi_dwmac_clk_init(struct sunxi_dwmac *chip) ++{ ++ int ret; ++ ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) ++ reset_control_deassert(chip->hsi_rst); ++ reset_control_deassert(chip->ahb_rst); ++ ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) { ++ ret = clk_prepare_enable(chip->hsi_ahb); ++ if (ret) { ++ sunxi_err(chip->dev, "enable hsi_ahb failed\n"); ++ goto err_ahb; ++ } ++ ret = clk_prepare_enable(chip->hsi_axi); ++ if (ret) { ++ sunxi_err(chip->dev, "enable hsi_axi failed\n"); ++ goto err_axi; ++ } ++ } ++ ++ if (chip->variant->flags & SUNXI_DWMAC_NSI_CLK_GATE) { ++ ret = clk_prepare_enable(chip->nsi_clk); ++ if (ret) { ++ sunxi_err(chip->dev, "enable nsi clk failed\n"); ++ goto err_nsi; ++ } ++ } ++ ++ if (chip->soc_phy_clk_en) { ++ ret = clk_prepare_enable(chip->phy_clk); ++ if (ret) { ++ sunxi_err(chip->dev, "Enable phy clk failed\n"); ++ goto err_phy; ++ } ++ } ++ ++ return 0; ++ ++err_phy: ++ if (chip->variant->flags & SUNXI_DWMAC_NSI_CLK_GATE) ++ clk_disable_unprepare(chip->nsi_clk); ++err_nsi: ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) { ++ clk_disable_unprepare(chip->hsi_axi); ++err_axi: ++ clk_disable_unprepare(chip->hsi_ahb); ++ } ++err_ahb: ++ reset_control_assert(chip->ahb_rst); ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) ++ reset_control_assert(chip->hsi_rst); ++ return ret; ++} ++ ++static void sunxi_dwmac_clk_exit(struct sunxi_dwmac *chip) ++{ ++ if (chip->soc_phy_clk_en) ++ clk_disable_unprepare(chip->phy_clk); ++ if (chip->variant->flags & SUNXI_DWMAC_NSI_CLK_GATE) ++ clk_disable_unprepare(chip->nsi_clk); ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) { ++ clk_disable_unprepare(chip->hsi_axi); ++ clk_disable_unprepare(chip->hsi_ahb); ++ } ++ reset_control_assert(chip->ahb_rst); ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) ++ reset_control_assert(chip->hsi_rst); ++} ++ ++static int sunxi_dwmac_hw_init(struct sunxi_dwmac *chip) ++{ ++ int ret; ++ ++ ret = chip->variant->set_syscon(chip); ++ if (ret < 0) { ++ sunxi_err(chip->dev, "Set syscon failed\n"); ++ goto err; ++ } ++ ++ ret = chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX, chip->tx_delay); ++ if (ret < 0) { ++ sunxi_err(chip->dev, "Invalid TX clock delay: %d\n", chip->tx_delay); ++ goto err; ++ } ++ ++ ret = chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX, chip->rx_delay); ++ if (ret < 0) { ++ sunxi_err(chip->dev, "Invalid RX clock delay: %d\n", chip->rx_delay); ++ goto err; ++ } ++ ++err: ++ return ret; ++} ++ ++static void sunxi_dwmac_hw_exit(struct sunxi_dwmac *chip) ++{ ++ writel(0, chip->syscfg_base); ++} ++ ++static int sunxi_dwmac_ecc_init(struct sunxi_dwmac *chip) ++{ ++ struct net_device *ndev = dev_get_drvdata(chip->dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct plat_stmmacenet_data *plat_dat = priv->plat; ++ ++ plat_dat->safety_feat_cfg = devm_kzalloc(chip->dev, sizeof(*plat_dat->safety_feat_cfg), GFP_KERNEL); ++ if (!plat_dat->safety_feat_cfg) ++ return -ENOMEM; ++ ++ plat_dat->safety_feat_cfg->tsoee = 0; /* TSO memory ECC Disabled */ ++ plat_dat->safety_feat_cfg->mrxpee = 0; /* MTL Rx Parser ECC Disabled */ ++ plat_dat->safety_feat_cfg->mestee = 0; /* MTL EST ECC Disabled */ ++ plat_dat->safety_feat_cfg->mrxee = 1; /* MTL Rx FIFO ECC Enable */ ++ plat_dat->safety_feat_cfg->mtxee = 1; /* MTL Tx FIFO ECC Enable */ ++ plat_dat->safety_feat_cfg->epsi = 0; /* Not Enable Parity on Slave Interface port */ ++ plat_dat->safety_feat_cfg->edpp = 1; /* Enable Data path Parity Protection */ ++ plat_dat->safety_feat_cfg->prtyen = 1; /* Enable FSM parity feature */ ++ plat_dat->safety_feat_cfg->tmouten = 1; /* Enable FSM timeout feature */ ++ ++ return 0; ++} ++ ++static int sunxi_dwmac_init(struct platform_device *pdev, void *priv) ++{ ++ struct sunxi_dwmac *chip = priv; ++ int ret; ++ ++ ret = sunxi_dwmac_power_on(chip); ++ if (ret) { ++ sunxi_err(&pdev->dev, "Power on dwmac failed\n"); ++ return ret; ++ } ++ ++ ret = sunxi_dwmac_clk_init(chip); ++ if (ret) { ++ sunxi_err(&pdev->dev, "Clk init dwmac failed\n"); ++ goto err_clk; ++ } ++ ++ ret = sunxi_dwmac_hw_init(chip); ++ if (ret) ++ sunxi_warn(&pdev->dev, "Hw init dwmac failed\n"); ++ ++ return 0; ++ ++err_clk: ++ sunxi_dwmac_power_off(chip); ++ return ret; ++} ++ ++static void sunxi_dwmac_exit(struct platform_device *pdev, void *priv) ++{ ++ struct sunxi_dwmac *chip = priv; ++ ++ sunxi_dwmac_hw_exit(chip); ++ sunxi_dwmac_clk_exit(chip); ++ sunxi_dwmac_power_off(chip); ++} ++ ++static void sunxi_dwmac_parse_delay_maps(struct sunxi_dwmac *chip) ++{ ++ struct platform_device *pdev = to_platform_device(chip->dev); ++ struct device_node *np = pdev->dev.of_node; ++ int ret, maps_cnt; ++ u32 *maps; ++ ++ maps_cnt = of_property_count_elems_of_size(np, "delay-maps", sizeof(u32)); ++ if (maps_cnt <= 0) { ++ sunxi_info(&pdev->dev, "Not found delay-maps in dts\n"); ++ return; ++ } ++ ++ maps = devm_kcalloc(&pdev->dev, maps_cnt, sizeof(u32), GFP_KERNEL); ++ if (!maps) ++ return; ++ ++ ret = of_property_read_u32_array(np, "delay-maps", maps, maps_cnt); ++ if (ret) { ++ sunxi_err(&pdev->dev, "Failed to parse delay-maps\n"); ++ goto err_parse_maps; ++ } ++/* todo ++ int i; ++ const u8 array_size = 3; ++ u16 soc_ver; ++ ++ soc_ver = (u16)sunxi_get_soc_ver(); ++ for (i = 0; i < (maps_cnt / array_size); i++) { ++ if (soc_ver == maps[i * array_size]) { ++ chip->rx_delay = maps[i * array_size + 1]; ++ chip->tx_delay = maps[i * array_size + 2]; ++ sunxi_info(&pdev->dev, "Overwrite delay-maps parameters, rx-delay:%d, tx-delay:%d\n", ++ chip->rx_delay, chip->tx_delay); ++ } ++ } ++*/ ++err_parse_maps: ++ devm_kfree(&pdev->dev, maps); ++} ++ ++static void sunxi_dwmac_request_mtl_irq(struct platform_device *pdev, struct sunxi_dwmac *chip, ++ struct plat_stmmacenet_data *plat_dat) ++{ ++ u32 queues; ++ char int_name[MAC_IRQ_NAME]; ++ ++ for (queues = 0; queues < plat_dat->tx_queues_to_use; queues++) { ++ sprintf(int_name, "%s%d_%s", "tx", queues, "irq"); ++ chip->res->tx_irq[queues] = platform_get_irq_byname_optional(pdev, int_name); ++ if (chip->res->tx_irq[queues] < 0) ++ chip->res->tx_irq[queues] = 0; ++ } ++ ++ for (queues = 0; queues < plat_dat->rx_queues_to_use; queues++) { ++ sprintf(int_name, "%s%d_%s", "rx", queues, "irq"); ++ chip->res->rx_irq[queues] = platform_get_irq_byname_optional(pdev, int_name); ++ if (chip->res->rx_irq[queues] < 0) ++ chip->res->rx_irq[queues] = 0; ++ } ++} ++ ++static int sunxi_dwmac_resource_get(struct platform_device *pdev, struct sunxi_dwmac *chip, ++ struct plat_stmmacenet_data *plat_dat) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ struct resource *res; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res) { ++ sunxi_err(dev, "Get phy memory failed\n"); ++ return -ENODEV; ++ } ++ ++ chip->syscfg_base = devm_ioremap_resource(dev, res); ++ if (!chip->syscfg_base) { ++ sunxi_err(dev, "Phy memory mapping failed\n"); ++ return -ENOMEM; ++ } ++ ++ chip->rgmii_clk_ext = of_property_read_bool(np, "aw,rgmii-clk-ext"); ++ chip->soc_phy_clk_en = of_property_read_bool(np, "aw,soc-phy-clk-en") || ++ of_property_read_bool(np, "aw,soc-phy25m"); ++ if (chip->soc_phy_clk_en) { ++ chip->phy_clk = devm_clk_get(dev, "phy"); ++ if (IS_ERR(chip->phy_clk)) { ++ chip->phy_clk = devm_clk_get(dev, "phy25m"); ++ if (IS_ERR(chip->phy_clk)) { ++ sunxi_err(dev, "Get phy25m clk failed\n"); ++ return -EINVAL; ++ } ++ } ++ sunxi_info(dev, "Phy use soc fanout\n"); ++ } else ++ sunxi_info(dev, "Phy use ext osc\n"); ++ ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) { ++ chip->hsi_ahb = devm_clk_get(dev, "hsi_ahb"); ++ if (IS_ERR(chip->hsi_ahb)) { ++ sunxi_err(dev, "Get hsi_ahb clk failed\n"); ++ return -EINVAL; ++ } ++ chip->hsi_axi = devm_clk_get(dev, "hsi_axi"); ++ if (IS_ERR(chip->hsi_axi)) { ++ sunxi_err(dev, "Get hsi_axi clk failed\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (chip->variant->flags & SUNXI_DWMAC_NSI_CLK_GATE) { ++ chip->nsi_clk = devm_clk_get(dev, "nsi"); ++ if (IS_ERR(chip->nsi_clk)) { ++ sunxi_err(dev, "Get nsi clk failed\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (chip->variant->flags & SUNXI_DWMAC_MEM_ECC) { ++ sunxi_info(dev, "Support mem ecc\n"); ++ chip->res->sfty_ce_irq = platform_get_irq_byname_optional(pdev, "mac_eccirq"); ++ if (chip->res->sfty_ce_irq < 0) { ++ sunxi_err(&pdev->dev, "Get ecc irq failed\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (chip->variant->flags & SUNXI_DWMAC_HSI_CLK_GATE) { ++ chip->hsi_rst = devm_reset_control_get_shared(chip->dev, "hsi"); ++ if (IS_ERR(chip->hsi_rst)) { ++ sunxi_err(dev, "Get hsi reset failed\n"); ++ return -EINVAL; ++ } ++ } ++ ++ chip->ahb_rst = devm_reset_control_get_optional_shared(chip->dev, "ahb"); ++ if (IS_ERR(chip->ahb_rst)) { ++ sunxi_err(dev, "Get mac reset failed\n"); ++ return -EINVAL; ++ } ++ ++ chip->dwmac3v3_supply = devm_regulator_get_optional(&pdev->dev, "dwmac3v3"); ++ if (IS_ERR(chip->dwmac3v3_supply)) ++ sunxi_warn(dev, "Not found dwmac3v3-supply\n"); ++ ++ chip->phy3v3_supply = devm_regulator_get_optional(&pdev->dev, "phy3v3"); ++ if (IS_ERR(chip->phy3v3_supply)) ++ sunxi_warn(dev, "Not found phy3v3-supply\n"); ++ ++ ret = of_property_read_u32(np, "tx-delay", &chip->tx_delay); ++ if (ret) { ++ sunxi_warn(dev, "Get gmac tx-delay failed, use default 0\n"); ++ chip->tx_delay = 0; ++ } ++ ++ ret = of_property_read_u32(np, "rx-delay", &chip->rx_delay); ++ if (ret) { ++ sunxi_warn(dev, "Get gmac rx-delay failed, use default 0\n"); ++ chip->rx_delay = 0; ++ } ++ ++ sunxi_dwmac_parse_delay_maps(chip); ++ ++ if (chip->variant->flags & SUNXI_DWMAC_MULTI_MSI) ++ sunxi_dwmac_request_mtl_irq(pdev, chip, plat_dat); ++ ++ return 0; ++} ++ ++#ifndef MODULE ++static void sunxi_dwmac_set_mac(u8 *dst, u8 *src) ++{ ++ int i; ++ char *p = src; ++ ++ for (i = 0; i < ETH_ALEN; i++, p++) ++ dst[i] = simple_strtoul(p, &p, 16); ++} ++#endif ++ ++static int sunxi_dwmac_probe(struct platform_device *pdev) ++{ ++ struct plat_stmmacenet_data *plat_dat; ++ struct stmmac_resources stmmac_res; ++ struct sunxi_dwmac *chip; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ ret = stmmac_get_platform_resources(pdev, &stmmac_res); ++ if (ret) ++ return ret; ++ ++ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); ++ if (!chip) { ++ sunxi_err(&pdev->dev, "Alloc sunxi dwmac err\n"); ++ return -ENOMEM; ++ } ++ ++ chip->variant = of_device_get_match_data(&pdev->dev); ++ if (!chip->variant) { ++ sunxi_err(&pdev->dev, "Missing dwmac-sunxi variant\n"); ++ return -EINVAL; ++ } ++ ++ chip->dev = dev; ++ chip->res = &stmmac_res; ++ ++ plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); ++ ++ if (IS_ERR(plat_dat)) ++ return PTR_ERR(plat_dat); ++ ++ ret = sunxi_dwmac_resource_get(pdev, chip, plat_dat); ++ if (ret < 0) ++ return -EINVAL; ++ ++#ifdef MODULE ++//todo get_custom_mac_address(1, "eth", stmmac_res.mac); ++#else ++//todo sunxi_dwmac_set_mac(stmmac_res.mac, mac_str); ++#endif ++ ++ ++ plat_dat->bsp_priv = chip; ++ plat_dat->init = sunxi_dwmac_init; ++ plat_dat->exit = sunxi_dwmac_exit; ++ /* must use 0~4G space */ ++ plat_dat->host_dma_width = 32; ++ ++ /* Disable Split Header (SPH) feature for sunxi platfrom as default ++ * The same issue also detect on intel platfrom, see 41eebbf90dfbcc8ad16d4755fe2cdb8328f5d4a7. ++ */ ++ if (chip->variant->flags & SUNXI_DWMAC_SPH_DISABLE) ++ plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE; ++ if (chip->variant->flags & SUNXI_DWMAC_MULTI_MSI) ++ plat_dat->flags |= STMMAC_FLAG_MULTI_MSI_EN; ++ chip->interface = plat_dat->mac_interface; ++ ++ plat_dat->clk_csr = 4; /* MDC = AHB(200M)/102 = 2M */ ++ ++ ret = sunxi_dwmac_init(pdev, plat_dat->bsp_priv); ++ if (ret) ++ goto err_init; ++ ++ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); ++ if (ret) ++ goto err_dvr_probe; ++ ++ if (chip->variant->flags & SUNXI_DWMAC_MEM_ECC) { ++ ret = sunxi_dwmac_ecc_init(chip); ++ if (ret < 0) { ++ sunxi_err(chip->dev, "Init ecc failed\n"); ++ goto err_cfg; ++ } ++ } ++ ++ sunxi_dwmac_sysfs_init(&pdev->dev); ++ ++ sunxi_info(&pdev->dev, "probe success (Version %s)\n", DWMAC_MODULE_VERSION); ++ ++ return 0; ++ ++err_cfg: ++ stmmac_dvr_remove(&pdev->dev); ++err_dvr_probe: ++ sunxi_dwmac_exit(pdev, chip); ++err_init: ++ //stmmac_remove_config_dt(pdev, plat_dat); ++ return ret; ++} ++ ++static void sunxi_dwmac_remove(struct platform_device *pdev) ++{ ++ sunxi_dwmac_sysfs_exit(&pdev->dev); ++ stmmac_pltfr_remove(pdev); ++} ++ ++static void sunxi_dwmac_shutdown(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ ++ sunxi_dwmac_exit(pdev, chip); ++} ++ ++static int __maybe_unused sunxi_dwmac_suspend(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct platform_device *pdev = to_platform_device(dev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ int ret; ++ ++ /* suspend error workaround */ ++ if (ndev && ndev->phydev) { ++ chip->uevent_suppress = dev_get_uevent_suppress(&ndev->phydev->mdio.dev); ++ dev_set_uevent_suppress(&ndev->phydev->mdio.dev, true); ++ } ++ ++ ret = stmmac_suspend(dev); ++ sunxi_dwmac_exit(pdev, chip); ++ stmmac_bus_clks_config(priv, false); ++ ++ return ret; ++} ++ ++static int __maybe_unused sunxi_dwmac_resume(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct platform_device *pdev = to_platform_device(dev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ int ret; ++ ++ stmmac_bus_clks_config(priv, true); ++ sunxi_dwmac_init(pdev, chip); ++ ret = stmmac_resume(dev); ++ ++ if (ndev && ndev->phydev) { ++ /* State machine change phy state too early before mdio bus resume. ++ * WARN_ON would print in mdio_bus_phy_resume if state not equal to PHY_HALTED/PHY_READY/PHY_UP. ++ * Workaround is change the state back to PHY_UP and modify the state machine work so the judgment can be passed. ++ */ ++ rtnl_lock(); ++ mutex_lock(&ndev->phydev->lock); ++ if (ndev->phydev->state == PHY_UP || ndev->phydev->state == PHY_NOLINK) { ++ if (ndev->phydev->state == PHY_NOLINK) ++ ndev->phydev->state = PHY_UP; ++ phy_queue_state_machine(ndev->phydev, HZ); ++ } ++ mutex_unlock(&ndev->phydev->lock); ++ rtnl_unlock(); ++ ++ /* suspend error workaround */ ++ dev_set_uevent_suppress(&ndev->phydev->mdio.dev, chip->uevent_suppress); ++ } ++ ++ return ret; ++} ++ ++static SIMPLE_DEV_PM_OPS(sunxi_dwmac_pm_ops, sunxi_dwmac_suspend, sunxi_dwmac_resume); ++ ++static const struct sunxi_dwmac_variant dwmac200_variant = { ++ .interface = PHY_INTERFACE_MODE_RMII | PHY_INTERFACE_MODE_RGMII, ++ .flags = SUNXI_DWMAC_SPH_DISABLE, ++ .rx_delay_max = 31, ++ .tx_delay_max = 7, ++ .set_syscon = sunxi_dwmac200_set_syscon, ++ .set_delaychain = sunxi_dwmac200_set_delaychain, ++ .get_delaychain = sunxi_dwmac200_get_delaychain, ++}; ++ ++static const struct sunxi_dwmac_variant dwmac210_variant = { ++ .interface = PHY_INTERFACE_MODE_RMII | PHY_INTERFACE_MODE_RGMII, ++ .flags = SUNXI_DWMAC_SPH_DISABLE | SUNXI_DWMAC_MULTI_MSI, ++ .rx_delay_max = 31, ++ .tx_delay_max = 31, ++ .set_syscon = sunxi_dwmac200_set_syscon, ++ .set_delaychain = sunxi_dwmac210_set_delaychain, ++ .get_delaychain = sunxi_dwmac210_get_delaychain, ++}; ++ ++static const struct sunxi_dwmac_variant dwmac220_variant = { ++ .interface = PHY_INTERFACE_MODE_RMII | PHY_INTERFACE_MODE_RGMII, ++ .flags = SUNXI_DWMAC_SPH_DISABLE | SUNXI_DWMAC_NSI_CLK_GATE | SUNXI_DWMAC_MULTI_MSI | SUNXI_DWMAC_MEM_ECC, ++ .rx_delay_max = 31, ++ .tx_delay_max = 31, ++ .set_syscon = sunxi_dwmac200_set_syscon, ++ .set_delaychain = sunxi_dwmac210_set_delaychain, ++ .get_delaychain = sunxi_dwmac210_get_delaychain, ++}; ++ ++static const struct sunxi_dwmac_variant dwmac110_variant = { ++ .interface = PHY_INTERFACE_MODE_RMII | PHY_INTERFACE_MODE_RGMII, ++ .flags = SUNXI_DWMAC_SPH_DISABLE | SUNXI_DWMAC_NSI_CLK_GATE | SUNXI_DWMAC_HSI_CLK_GATE | SUNXI_DWMAC_MULTI_MSI, ++ .rx_delay_max = 31, ++ .tx_delay_max = 31, ++ .set_syscon = sunxi_dwmac200_set_syscon, ++ .set_delaychain = sunxi_dwmac210_set_delaychain, ++ .get_delaychain = sunxi_dwmac210_get_delaychain, ++ .get_version = sunxi_dwmac110_get_version, ++}; ++ ++static const struct of_device_id sunxi_dwmac_match[] = { ++ { .compatible = "allwinner,sunxi-gmac-200", .data = &dwmac200_variant }, ++ { .compatible = "allwinner,sunxi-gmac-210", .data = &dwmac210_variant }, ++ { .compatible = "allwinner,sunxi-gmac-220", .data = &dwmac220_variant }, ++ { .compatible = "allwinner,sunxi-gmac-110", .data = &dwmac110_variant }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sunxi_dwmac_match); ++ ++static struct platform_driver sunxi_dwmac_driver = { ++ .probe = sunxi_dwmac_probe, ++ .remove = sunxi_dwmac_remove, ++ .shutdown = sunxi_dwmac_shutdown, ++ .driver = { ++ .name = "dwmac-sunxi", ++ .pm = &sunxi_dwmac_pm_ops, ++ .of_match_table = sunxi_dwmac_match, ++ }, ++}; ++module_platform_driver(sunxi_dwmac_driver); ++ ++#ifndef MODULE ++static int __init sunxi_dwmac_set_mac_addr(char *str) ++{ ++ char *p = str; ++ ++ if (str && strlen(str)) ++ memcpy(mac_str, p, MAC_ADDR_LEN); ++ ++ return 0; ++} ++__setup("mac_addr=", sunxi_dwmac_set_mac_addr); ++#endif /* MODULE */ ++ ++MODULE_DESCRIPTION("Allwinner DWMAC driver"); ++MODULE_AUTHOR("wujiayi "); ++MODULE_AUTHOR("xuminghui "); ++MODULE_AUTHOR("Piotr Oniszczuk "); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(DWMAC_MODULE_VERSION); +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.h linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.h +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi.h 2025-01-21 15:58:05.577494134 +0100 +@@ -0,0 +1,176 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++* Allwinner DWMAC driver header. ++* ++* Copyright(c) 2022-2027 Allwinnertech Co., Ltd. ++* ++* This file is licensed under the terms of the GNU General Public ++* License version 2. This program is licensed "as is" without any ++* warranty of any kind, whether express or implied. ++*/ ++ ++#ifndef _DWMAC_SUNXI_H_ ++#define _DWMAC_SUNXI_H_ ++ ++#include ++#include ++ ++/* DWCMAC5 ECC Debug Register ++ * These macro do not defined in mainline code dwmac5.h ++ */ ++#define MTL_DBG_CTL 0x00000c08 ++#define EIEC BIT(18) ++#define EIAEE BIT(17) ++#define EIEE BIT(16) ++#define FIFOSEL GENMASK(13, 12) ++#define FIFOWREN BIT(11) ++#define FIFORDEN BIT(10) ++#define RSTSEL BIT(9) ++#define RSTALL BIT(8) ++#define DBGMOD BIT(1) ++#define FDBGEN BIT(0) ++#define MTL_DBG_STS 0x00000c0c ++#define FIFOBUSY BIT(0) ++#define MTL_FIFO_DEBUG_DATA 0x00000c10 ++#define MTL_ECC_ERR_STS_RCTL 0x00000cd0 ++#define CUES BIT(5) ++#define CCES BIT(4) ++#define EMS GENMASK(3, 1) ++#define EESRE BIT(0) ++#define MTL_ECC_ERR_ADDR_STATUS 0x00000cd4 ++#define EUEAS GENMASK(31, 16) ++#define ECEAS GENMASK(15, 0) ++#define MTL_ECC_ERR_CNTR_STATUS 0x00000cd8 ++#define EUECS GENMASK(19, 16) ++#define ECECS GENMASK(7, 0) ++#define MTL_DPP_ECC_EIC 0x00000ce4 ++#define EIM BIT(16) ++#define BLEI GENMASK(7, 0) ++ ++/* GMAC-200 Register */ ++#define SUNXI_DWMAC200_SYSCON_REG (0x00) ++ #define SUNXI_DWMAC200_SYSCON_BPS_EFUSE GENMASK(31, 28) ++ #define SUNXI_DWMAC200_SYSCON_XMII_SEL BIT(27) ++ #define SUNXI_DWMAC200_SYSCON_EPHY_MODE GENMASK(26, 25) ++ #define SUNXI_DWMAC200_SYSCON_PHY_ADDR GENMASK(24, 20) ++ #define SUNXI_DWMAC200_SYSCON_BIST_CLK_EN BIT(19) ++ #define SUNXI_DWMAC200_SYSCON_CLK_SEL BIT(18) ++ #define SUNXI_DWMAC200_SYSCON_LED_POL BIT(17) ++ #define SUNXI_DWMAC200_SYSCON_SHUTDOWN BIT(16) ++ #define SUNXI_DWMAC200_SYSCON_PHY_SEL BIT(15) ++ #define SUNXI_DWMAC200_SYSCON_ENDIAN_MODE BIT(14) ++ #define SUNXI_DWMAC200_SYSCON_RMII_EN BIT(13) ++ #define SUNXI_DWMAC200_SYSCON_ETXDC GENMASK(12, 10) ++ #define SUNXI_DWMAC200_SYSCON_ERXDC GENMASK(9, 5) ++ #define SUNXI_DWMAC200_SYSCON_ERXIE BIT(4) ++ #define SUNXI_DWMAC200_SYSCON_ETXIE BIT(3) ++ #define SUNXI_DWMAC200_SYSCON_EPIT BIT(2) ++ #define SUNXI_DWMAC200_SYSCON_ETCS GENMASK(1, 0) ++ ++/* GMAC-210 Register */ ++#define SUNXI_DWMAC210_CFG_REG (0x00) ++ #define SUNXI_DWMAC210_CFG_ETXDC_H GENMASK(17, 16) ++ #define SUNXI_DWMAC210_CFG_PHY_SEL BIT(15) ++ #define SUNXI_DWMAC210_CFG_ENDIAN_MODE BIT(14) ++ #define SUNXI_DWMAC210_CFG_RMII_EN BIT(13) ++ #define SUNXI_DWMAC210_CFG_ETXDC_L GENMASK(12, 10) ++ #define SUNXI_DWMAC210_CFG_ERXDC GENMASK(9, 5) ++ #define SUNXI_DWMAC210_CFG_ERXIE BIT(4) ++ #define SUNXI_DWMAC210_CFG_ETXIE BIT(3) ++ #define SUNXI_DWMAC210_CFG_EPIT BIT(2) ++ #define SUNXI_DWMAC210_CFG_ETCS GENMASK(1, 0) ++#define SUNXI_DWMAC210_PTP_TIMESTAMP_L_REG (0x40) ++#define SUNXI_DWMAC210_PTP_TIMESTAMP_H_REG (0x48) ++#define SUNXI_DWMAC210_STAT_INT_REG (0x4C) ++ #define SUNXI_DWMAC210_STAT_PWR_DOWN_ACK BIT(4) ++ #define SUNXI_DWMAC210_STAT_SBD_TX_CLK_GATE BIT(3) ++ #define SUNXI_DWMAC210_STAT_LPI_INT BIT(1) ++ #define SUNXI_DWMAC210_STAT_PMT_INT BIT(0) ++#define SUNXI_DWMAC210_CLK_GATE_CFG_REG (0x80) ++ #define SUNXI_DWMAC210_CLK_GATE_CFG_RX BIT(7) ++ #define SUNXI_DWMAC210_CLK_GATE_CFG_PTP_REF BIT(6) ++ #define SUNXI_DWMAC210_CLK_GATE_CFG_CSR BIT(5) ++ #define SUNXI_DWMAC210_CLK_GATE_CFG_TX BIT(4) ++ #define SUNXI_DWMAC210_CLK_GATE_CFG_APP BIT(3) ++ ++/* GMAC-110 Register */ ++#define SUNXI_DWMAC110_CFG_REG SUNXI_DWMAC210_CFG_REG ++ /* SUNXI_DWMAC110_CFG_REG is same with SUNXI_DWMAC210_CFG_REG */ ++#define SUNXI_DWMAC110_CLK_GATE_CFG_REG (0x04) ++ #define SUNXI_DWMAC110_CLK_GATE_CFG_RX BIT(3) ++ #define SUNXI_DWMAC110_CLK_GATE_CFG_TX BIT(2) ++ #define SUNXI_DWMAC110_CLK_GATE_CFG_APP BIT(1) ++ #define SUNXI_DWMAC110_CLK_GATE_CFG_CSR BIT(0) ++#define SUNXI_DWMAC110_VERSION_REG (0xfc) ++ #define SUNXI_DWMAC110_VERSION_IP_TAG GENMASK(31, 16) ++ #define SUNXI_DWMAC110_VERSION_IP_VRM GENMASK(15, 0) ++ ++#define SUNXI_DWMAC_ETCS_MII 0x0 ++#define SUNXI_DWMAC_ETCS_EXT_GMII 0x1 ++#define SUNXI_DWMAC_ETCS_INT_GMII 0x2 ++ ++/* MAC flags defined */ ++#define SUNXI_DWMAC_SPH_DISABLE BIT(0) ++#define SUNXI_DWMAC_NSI_CLK_GATE BIT(1) ++#define SUNXI_DWMAC_MULTI_MSI BIT(2) ++#define SUNXI_DWMAC_MEM_ECC BIT(3) ++#define SUNXI_DWMAC_HSI_CLK_GATE BIT(4) ++ ++struct sunxi_dwmac; ++ ++enum sunxi_dwmac_delaychain_dir { ++ SUNXI_DWMAC_DELAYCHAIN_TX, ++ SUNXI_DWMAC_DELAYCHAIN_RX, ++}; ++ ++enum sunxi_dwmac_ecc_fifo_type { ++ SUNXI_DWMAC_ECC_FIFO_TX, ++ SUNXI_DWMAC_ECC_FIFO_RX, ++}; ++ ++struct sunxi_dwmac_variant { ++ u32 flags; ++ u32 interface; ++ u32 rx_delay_max; ++ u32 tx_delay_max; ++ int (*set_syscon)(struct sunxi_dwmac *chip); ++ int (*set_delaychain)(struct sunxi_dwmac *chip, enum sunxi_dwmac_delaychain_dir dir, u32 delay); ++ u32 (*get_delaychain)(struct sunxi_dwmac *chip, enum sunxi_dwmac_delaychain_dir dir); ++ int (*get_version)(struct sunxi_dwmac *chip, u16 *ip_tag, u16 *ip_vrm); ++}; ++ ++struct sunxi_dwmac_mii_reg { ++ u32 addr; ++ u16 reg; ++ u16 value; ++}; ++ ++struct sunxi_dwmac { ++ const struct sunxi_dwmac_variant *variant; ++ struct sunxi_dwmac_mii_reg mii_reg; ++ struct clk *phy_clk; ++ struct clk *nsi_clk; ++ struct clk *hsi_ahb; ++ struct clk *hsi_axi; ++ struct reset_control *ahb_rst; ++ struct reset_control *hsi_rst; ++ struct device *dev; ++ void __iomem *syscfg_base; ++ struct regulator *dwmac3v3_supply; ++ struct regulator *phy3v3_supply; ++ ++ u32 tx_delay; /* adjust transmit clock delay */ ++ u32 rx_delay; /* adjust receive clock delay */ ++ ++ bool rgmii_clk_ext; ++ bool soc_phy_clk_en; ++ int interface; ++ unsigned int uevent_suppress; /* suspend error workaround: control kobject_uevent_env */ ++ ++ struct stmmac_resources *res; ++}; ++ ++#include "dwmac-sunxi-sysfs.h" ++ ++#endif /* _DWMAC_SUNXI_H_ */ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.c linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.c +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.c 2025-01-21 15:58:05.577494134 +0100 +@@ -0,0 +1,927 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++* Allwinner DWMAC driver sysfs. ++* ++* Copyright(c) 2022-2027 Allwinnertech Co., Ltd. ++* ++*/ ++ ++#include "sunxi-log.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "stmmac/stmmac.h" ++ ++#include "dwmac-sunxi-sysfs.h" ++ ++struct sunxi_dwmac_hdr { ++ __be32 version; ++ __be64 magic; ++ u8 id; ++ u32 tx; ++ u32 rx; ++} __packed; ++ ++#define SUNXI_DWMAC_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) + \ ++ sizeof(struct sunxi_dwmac_hdr)) ++#define SUNXI_DWMAC_PKT_MAGIC 0xdeadcafecafedeadULL ++#define SUNXI_DWMAC_TIMEOUT msecs_to_jiffies(2) ++ ++struct sunxi_dwmac_packet_attr { ++ u32 tx; ++ u32 rx; ++ unsigned char *src; ++ unsigned char *dst; ++ u32 ip_src; ++ u32 ip_dst; ++ int tcp; ++ int sport; ++ int dport; ++ int dont_wait; ++ int timeout; ++ int size; ++ int max_size; ++ u8 id; ++ u16 queue_mapping; ++ u64 timestamp; ++}; ++ ++struct sunxi_dwmac_loop_priv { ++ struct sunxi_dwmac_packet_attr *packet; ++ struct packet_type pt; ++ struct completion comp; ++ int ok; ++}; ++ ++struct sunxi_dwmac_calibrate { ++ u8 id; ++ u32 tx_delay; ++ u32 rx_delay; ++ u32 window_tx; ++ u32 window_rx; ++}; ++ ++/** ++ * sunxi_dwmac_parse_read_str - parse the input string for write attri. ++ * @str: string to be parsed, eg: "0x00 0x01". ++ * @addr: store the phy addr. eg: 0x00. ++ * @reg: store the reg addr. eg: 0x01. ++ * ++ * return 0 if success, otherwise failed. ++ */ ++static int sunxi_dwmac_parse_read_str(char *str, u16 *addr, u16 *reg) ++{ ++ char *ptr = str; ++ char *tstr = NULL; ++ int ret; ++ ++ /** ++ * Skip the leading whitespace, find the true split symbol. ++ * And it must be 'address value'. ++ */ ++ tstr = strim(str); ++ ptr = strchr(tstr, ' '); ++ if (!ptr) ++ return -EINVAL; ++ ++ /** ++ * Replaced split symbol with a %NUL-terminator temporary. ++ * Will be fixed at end. ++ */ ++ *ptr = '\0'; ++ ret = kstrtos16(tstr, 16, addr); ++ if (ret) ++ goto out; ++ ++ ret = kstrtos16(skip_spaces(ptr + 1), 16, reg); ++ ++out: ++ return ret; ++} ++ ++/** ++ * sunxi_dwmac_parse_write_str - parse the input string for compare attri. ++ * @str: string to be parsed, eg: "0x00 0x11 0x11". ++ * @addr: store the phy addr. eg: 0x00. ++ * @reg: store the reg addr. eg: 0x11. ++ * @val: store the value. eg: 0x11. ++ * ++ * return 0 if success, otherwise failed. ++ */ ++static int sunxi_dwmac_parse_write_str(char *str, u16 *addr, ++ u16 *reg, u16 *val) ++{ ++ u16 result_addr[3] = { 0 }; ++ char *ptr = str; ++ char *ptr2 = NULL; ++ int i, ret; ++ ++ for (i = 0; i < ARRAY_SIZE(result_addr); i++) { ++ ptr = skip_spaces(ptr); ++ ptr2 = strchr(ptr, ' '); ++ if (ptr2) ++ *ptr2 = '\0'; ++ ++ ret = kstrtou16(ptr, 16, &result_addr[i]); ++ ++ if (!ptr2 || ret) ++ break; ++ ++ ptr = ptr2 + 1; ++ } ++ ++ *addr = result_addr[0]; ++ *reg = result_addr[1]; ++ *val = result_addr[2]; ++ ++ return ret; ++} ++ ++static struct sk_buff *sunxi_dwmac_get_skb(struct stmmac_priv *priv, ++ struct sunxi_dwmac_packet_attr *attr) ++{ ++ struct sk_buff *skb = NULL; ++ struct udphdr *uhdr = NULL; ++ struct tcphdr *thdr = NULL; ++ struct sunxi_dwmac_hdr *shdr; ++ struct ethhdr *ehdr; ++ struct iphdr *ihdr; ++ int iplen, size; ++ ++ size = attr->size + SUNXI_DWMAC_PKT_SIZE; ++ ++ if (attr->tcp) ++ size += sizeof(*thdr); ++ else ++ size += sizeof(*uhdr); ++ ++ if (attr->max_size && (attr->max_size > size)) ++ size = attr->max_size; ++ ++ skb = netdev_alloc_skb(priv->dev, size); ++ if (!skb) ++ return NULL; ++ ++ prefetchw(skb->data); ++ ++ ehdr = skb_push(skb, ETH_HLEN); ++ skb_reset_mac_header(skb); ++ ++ skb_set_network_header(skb, skb->len); ++ ihdr = skb_put(skb, sizeof(*ihdr)); ++ ++ skb_set_transport_header(skb, skb->len); ++ if (attr->tcp) ++ thdr = skb_put(skb, sizeof(*thdr)); ++ else ++ uhdr = skb_put(skb, sizeof(*uhdr)); ++ ++ eth_zero_addr(ehdr->h_source); ++ eth_zero_addr(ehdr->h_dest); ++ if (attr->src) ++ ether_addr_copy(ehdr->h_source, attr->src); ++ if (attr->dst) ++ ether_addr_copy(ehdr->h_dest, attr->dst); ++ ++ ehdr->h_proto = htons(ETH_P_IP); ++ ++ if (attr->tcp) { ++ thdr->source = htons(attr->sport); ++ thdr->dest = htons(attr->dport); ++ thdr->doff = sizeof(*thdr) / 4; ++ thdr->check = 0; ++ } else { ++ uhdr->source = htons(attr->sport); ++ uhdr->dest = htons(attr->dport); ++ uhdr->len = htons(sizeof(*shdr) + sizeof(*uhdr) + attr->size); ++ if (attr->max_size) ++ uhdr->len = htons(attr->max_size - ++ (sizeof(*ihdr) + sizeof(*ehdr))); ++ uhdr->check = 0; ++ } ++ ++ ihdr->ihl = 5; ++ ihdr->ttl = 32; ++ ihdr->version = 4; ++ if (attr->tcp) ++ ihdr->protocol = IPPROTO_TCP; ++ else ++ ihdr->protocol = IPPROTO_UDP; ++ iplen = sizeof(*ihdr) + sizeof(*shdr) + attr->size; ++ if (attr->tcp) ++ iplen += sizeof(*thdr); ++ else ++ iplen += sizeof(*uhdr); ++ ++ if (attr->max_size) ++ iplen = attr->max_size - sizeof(*ehdr); ++ ++ ihdr->tot_len = htons(iplen); ++ ihdr->frag_off = 0; ++ ihdr->saddr = htonl(attr->ip_src); ++ ihdr->daddr = htonl(attr->ip_dst); ++ ihdr->tos = 0; ++ ihdr->id = 0; ++ ip_send_check(ihdr); ++ ++ shdr = skb_put(skb, sizeof(*shdr)); ++ shdr->version = 0; ++ shdr->magic = cpu_to_be64(SUNXI_DWMAC_PKT_MAGIC); ++ shdr->id = attr->id; ++ shdr->tx = attr->tx; ++ shdr->rx = attr->rx; ++ ++ if (attr->size) ++ skb_put(skb, attr->size); ++ if (attr->max_size && (attr->max_size > skb->len)) ++ skb_put(skb, attr->max_size - skb->len); ++ ++ skb->csum = 0; ++ skb->ip_summed = CHECKSUM_PARTIAL; ++ if (attr->tcp) { ++ thdr->check = ~tcp_v4_check(skb->len, ihdr->saddr, ihdr->daddr, 0); ++ skb->csum_start = skb_transport_header(skb) - skb->head; ++ skb->csum_offset = offsetof(struct tcphdr, check); ++ } else { ++ udp4_hwcsum(skb, ihdr->saddr, ihdr->daddr); ++ } ++ ++ skb->protocol = htons(ETH_P_IP); ++ skb->pkt_type = PACKET_HOST; ++ skb->dev = priv->dev; ++ ++ if (attr->timestamp) ++ skb->tstamp = ns_to_ktime(attr->timestamp); ++ ++ return skb; ++} ++ ++static int sunxi_dwmac_loopback_validate(struct sk_buff *skb, ++ struct net_device *ndev, ++ struct packet_type *pt, ++ struct net_device *orig_ndev) ++{ ++ struct sunxi_dwmac_loop_priv *tpriv = pt->af_packet_priv; ++ unsigned char *src = tpriv->packet->src; ++ unsigned char *dst = tpriv->packet->dst; ++ struct sunxi_dwmac_hdr *shdr; ++ struct ethhdr *ehdr; ++ struct udphdr *uhdr; ++ struct tcphdr *thdr; ++ struct iphdr *ihdr; ++ ++ skb = skb_unshare(skb, GFP_ATOMIC); ++ if (!skb) ++ goto out; ++ ++ if (skb_linearize(skb)) ++ goto out; ++ if (skb_headlen(skb) < (SUNXI_DWMAC_PKT_SIZE - ETH_HLEN)) ++ goto out; ++ ++ ehdr = (struct ethhdr *)skb_mac_header(skb); ++ if (dst) { ++ if (!ether_addr_equal_unaligned(ehdr->h_dest, dst)) ++ goto out; ++ } ++ if (src) { ++ if (!ether_addr_equal_unaligned(ehdr->h_source, src)) ++ goto out; ++ } ++ ++ ihdr = ip_hdr(skb); ++ ++ if (tpriv->packet->tcp) { ++ if (ihdr->protocol != IPPROTO_TCP) ++ goto out; ++ ++ thdr = (struct tcphdr *)((u8 *)ihdr + 4 * ihdr->ihl); ++ if (thdr->dest != htons(tpriv->packet->dport)) ++ goto out; ++ ++ shdr = (struct sunxi_dwmac_hdr *)((u8 *)thdr + sizeof(*thdr)); ++ } else { ++ if (ihdr->protocol != IPPROTO_UDP) ++ goto out; ++ ++ uhdr = (struct udphdr *)((u8 *)ihdr + 4 * ihdr->ihl); ++ if (uhdr->dest != htons(tpriv->packet->dport)) ++ goto out; ++ ++ shdr = (struct sunxi_dwmac_hdr *)((u8 *)uhdr + sizeof(*uhdr)); ++ } ++ ++ if (shdr->magic != cpu_to_be64(SUNXI_DWMAC_PKT_MAGIC)) ++ goto out; ++ if (tpriv->packet->id != shdr->id) ++ goto out; ++ if (tpriv->packet->tx != shdr->tx || tpriv->packet->rx != shdr->rx) ++ goto out; ++ ++ tpriv->ok = true; ++ complete(&tpriv->comp); ++out: ++ kfree_skb(skb); ++ return 0; ++} ++ ++static int sunxi_dwmac_loopback_run(struct stmmac_priv *priv, ++ struct sunxi_dwmac_packet_attr *attr) ++{ ++ struct sunxi_dwmac_loop_priv *tpriv; ++ struct sk_buff *skb = NULL; ++ int ret = 0; ++ ++ tpriv = kzalloc(sizeof(*tpriv), GFP_KERNEL); ++ if (!tpriv) ++ return -ENOMEM; ++ ++ tpriv->ok = false; ++ init_completion(&tpriv->comp); ++ ++ tpriv->pt.type = htons(ETH_P_IP); ++ tpriv->pt.func = sunxi_dwmac_loopback_validate; ++ tpriv->pt.dev = priv->dev; ++ tpriv->pt.af_packet_priv = tpriv; ++ tpriv->packet = attr; ++ ++ if (!attr->dont_wait) ++ dev_add_pack(&tpriv->pt); ++ ++ skb = sunxi_dwmac_get_skb(priv, attr); ++ if (!skb) { ++ ret = -ENOMEM; ++ goto cleanup; ++ } ++ ++ ret = dev_direct_xmit(skb, attr->queue_mapping); ++ if (ret) ++ goto cleanup; ++ ++ if (attr->dont_wait) ++ goto cleanup; ++ ++ if (!attr->timeout) ++ attr->timeout = SUNXI_DWMAC_TIMEOUT; ++ ++ wait_for_completion_timeout(&tpriv->comp, attr->timeout); ++ ret = tpriv->ok ? 0 : -ETIMEDOUT; ++ ++cleanup: ++ if (!attr->dont_wait) ++ dev_remove_pack(&tpriv->pt); ++ kfree(tpriv); ++ return ret; ++} ++ ++static int sunxi_dwmac_test_delaychain(struct sunxi_dwmac *chip, struct sunxi_dwmac_calibrate *cali) ++{ ++ struct net_device *ndev = dev_get_drvdata(chip->dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ unsigned char src[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ++ unsigned char dst[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; ++ struct sunxi_dwmac_packet_attr attr = { }; ++ ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX, cali->tx_delay); ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX, cali->rx_delay); ++ ++ attr.src = src; ++ attr.dst = dst; ++ attr.tcp = true; ++ attr.queue_mapping = 0; ++ stmmac_get_systime(priv, priv->ptpaddr, &attr.timestamp); ++ attr.id = cali->id; ++ attr.tx = cali->tx_delay; ++ attr.rx = cali->rx_delay; ++ ++ return sunxi_dwmac_loopback_run(priv, &attr); ++} ++ ++static int sunxi_dwmac_calibrate_scan_window(struct sunxi_dwmac *chip, struct sunxi_dwmac_calibrate *cali) ++{ ++ struct net_device *ndev = dev_get_drvdata(chip->dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ char *buf, *ptr; ++ int tx_sum, rx_sum, count; ++ u32 tx, rx; ++ int ret = 0; ++ ++ buf = devm_kzalloc(chip->dev, PAGE_SIZE, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ netif_testing_on(ndev); ++ ++ ret = phy_loopback(priv->dev->phydev, true); ++ if (ret) ++ goto err; ++ ++ tx_sum = rx_sum = count = 0; ++ ++ for (tx = 0; tx < cali->window_tx; tx++) { ++ ptr = buf; ++ ptr += scnprintf(ptr, PAGE_SIZE - (ptr - buf), "TX(0x%02x): ", tx); ++ for (rx = 0; rx < cali->window_rx; rx++) { ++ cali->id++; ++ cali->tx_delay = tx; ++ cali->rx_delay = rx; ++ if (sunxi_dwmac_test_delaychain(chip, cali) < 0) { ++ ptr += scnprintf(ptr, PAGE_SIZE - (ptr - buf), "X"); ++ } else { ++ tx_sum += tx; ++ rx_sum += rx; ++ count++; ++ ptr += scnprintf(ptr, PAGE_SIZE - (ptr - buf), "-"); ++ } ++ } ++ ptr += scnprintf(ptr, PAGE_SIZE - (ptr - buf), "\n"); ++ printk(buf); ++ } ++ ++ if (tx_sum && rx_sum && count) { ++ cali->tx_delay = tx_sum / count; ++ cali->rx_delay = rx_sum / count; ++ } else { ++ cali->tx_delay = cali->rx_delay = 0; ++ } ++ ++ phy_loopback(priv->dev->phydev, false); ++ ++err: ++ netif_testing_off(ndev); ++ devm_kfree(chip->dev, buf); ++ return ret; ++} ++ ++static ssize_t sunxi_dwmac_calibrate_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ struct phy_device *phydev = priv->dev->phydev; ++ struct sunxi_dwmac_calibrate *cali; ++ u32 old_tx, old_rx; ++ int ret; ++ ++ if (!ndev || !phydev) { ++ sunxi_err(chip->dev, "Not found netdevice or phy\n"); ++ return -EINVAL; ++ } ++ ++ if (!netif_carrier_ok(ndev) || !phydev->link) { ++ sunxi_err(chip->dev, "Netdevice or phy not link\n"); ++ return -EINVAL; ++ } ++ ++ if (phydev->speed < SPEED_1000) { ++ sunxi_err(chip->dev, "Speed %s no need calibrate\n", phy_speed_to_str(phydev->speed)); ++ return -EINVAL; ++ } ++ ++ cali = devm_kzalloc(dev, sizeof(*cali), GFP_KERNEL); ++ if (!cali) ++ return -ENOMEM; ++ ++ old_tx = chip->variant->get_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX); ++ old_rx = chip->variant->get_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX); ++ ++ cali->window_tx = chip->variant->tx_delay_max + 1; ++ cali->window_rx = chip->variant->rx_delay_max + 1; ++ ++ ret = sunxi_dwmac_calibrate_scan_window(chip, cali); ++ if (ret) { ++ sunxi_err(dev, "Calibrate scan window tx:%d rx:%d failed\n", cali->window_tx, cali->window_rx); ++ goto err; ++ } ++ ++ if (cali->tx_delay && cali->rx_delay) { ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX, cali->tx_delay); ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX, cali->rx_delay); ++ sunxi_info(chip->dev, "Calibrate suitable delay tx:%d rx:%d\n", cali->tx_delay, cali->rx_delay); ++ } else { ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX, old_tx); ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX, old_rx); ++ sunxi_warn(chip->dev, "Calibrate cannot find suitable delay\n"); ++ } ++ ++err: ++ devm_kfree(dev, cali); ++ return count; ++} ++ ++static int sunxi_dwmac_test_ecc_inject(struct stmmac_priv *priv, enum sunxi_dwmac_ecc_fifo_type type, u8 bit) ++{ ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ static const u32 wdata[2] = {0x55555555, 0x55555555}; ++ u32 rdata[ARRAY_SIZE(wdata)]; ++ u32 mtl_dbg_ctl, mtl_dpp_ecc_eic; ++ u32 val; ++ int i, ret = 0; ++ ++ mtl_dbg_ctl = readl(priv->ioaddr + MTL_DBG_CTL); ++ mtl_dpp_ecc_eic = readl(priv->ioaddr + MTL_DPP_ECC_EIC); ++ ++ mtl_dbg_ctl &= ~EIAEE; /* disable ecc error injection on address */ ++ mtl_dbg_ctl |= DBGMOD | FDBGEN; /* ecc debug mode enable */ ++ mtl_dpp_ecc_eic &= ~EIM; /* indicate error injection on data */ ++ mtl_dpp_ecc_eic |= FIELD_PREP(BLEI, 36); /* inject bit location is bit0 and bit36 */ ++ ++ /* ecc select inject bit */ ++ switch (bit) { ++ case 0: ++ mtl_dbg_ctl &= ~EIEE; /* ecc inject error disable */ ++ break; ++ case 1: ++ mtl_dbg_ctl &= ~EIEC; /* ecc inject insert 1-bit error */ ++ mtl_dbg_ctl |= EIEE; /* ecc inject error enable */ ++ break; ++ case 2: ++ mtl_dbg_ctl |= EIEC; /* ecc inject insert 2-bit error */ ++ mtl_dbg_ctl |= EIEE; /* ecc inject error enable */ ++ break; ++ default: ++ ret = -EINVAL; ++ sunxi_err(chip->dev, "test unsupport ecc inject bit %d\n", bit); ++ goto err; ++ } ++ ++ /* ecc select fifo */ ++ mtl_dbg_ctl &= ~FIFOSEL; ++ switch (type) { ++ case SUNXI_DWMAC_ECC_FIFO_TX: ++ mtl_dbg_ctl |= FIELD_PREP(FIFOSEL, 0x0); ++ break; ++ case SUNXI_DWMAC_ECC_FIFO_RX: ++ mtl_dbg_ctl |= FIELD_PREP(FIFOSEL, 0x3); ++ break; ++ default: ++ ret = -EINVAL; ++ sunxi_err(chip->dev, "test unsupport ecc inject fifo type %d\n", type); ++ goto err; ++ } ++ ++ writel(mtl_dpp_ecc_eic, priv->ioaddr + MTL_DPP_ECC_EIC); ++ writel(mtl_dbg_ctl, priv->ioaddr + MTL_DBG_CTL); ++ ++ /* write fifo debug data */ ++ mtl_dbg_ctl &= ~FIFORDEN; ++ mtl_dbg_ctl |= FIFOWREN; ++ for (i = 0; i < ARRAY_SIZE(wdata); i++) { ++ writel(wdata[i], priv->ioaddr + MTL_FIFO_DEBUG_DATA); ++ writel(mtl_dbg_ctl, priv->ioaddr + MTL_DBG_CTL); ++ ret = readl_poll_timeout_atomic(priv->ioaddr + MTL_DBG_STS, val, !(val & FIFOBUSY), 10, 200000); ++ if (ret) { ++ sunxi_err(chip->dev, "timeout with ecc debug fifo write busy (%#x)\n", val); ++ goto err; ++ } ++ } ++ ++ /* read fifo debug data */ ++ mtl_dbg_ctl &= ~FIFOWREN; ++ mtl_dbg_ctl |= FIFORDEN; ++ for (i = 0; i < ARRAY_SIZE(wdata); i++) { ++ writel(mtl_dbg_ctl, priv->ioaddr + MTL_DBG_CTL); ++ ret = readl_poll_timeout_atomic(priv->ioaddr + MTL_DBG_STS, val, !(val & FIFOBUSY), 10, 200000); ++ if (ret) { ++ sunxi_err(chip->dev, "test timeout with ecc debug fifo read busy (%#x)\n", val); ++ goto err; ++ } ++ rdata[i] = readl(priv->ioaddr + MTL_FIFO_DEBUG_DATA); ++ } ++ ++ /* compare data */ ++ switch (bit) { ++ case 0: ++ case 1: ++ /* for ecc error inject 0/1 bit, read should be same with write */ ++ for (i = 0; i < ARRAY_SIZE(wdata); i++) { ++ if (rdata[i] != wdata[i]) { ++ ret = -EINVAL; ++ break; ++ } ++ } ++ break; ++ case 2: ++ /* for ecc error inject 2 bit, read should be different with write */ ++ for (i = 0; i < ARRAY_SIZE(wdata); i++) { ++ if (rdata[i] == wdata[i]) { ++ ret = -EINVAL; ++ break; ++ } ++ } ++ break; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(wdata); i++) ++ sunxi_info(chip->dev, "fifo %d write [%#x] -> read [%#x]\n", i, wdata[i], rdata[i]); ++ ++err: ++ /* ecc debug mode disable */ ++ mtl_dbg_ctl &= ~(EIEE | EIEC | FIFOWREN | FIFORDEN); ++ writel(mtl_dbg_ctl, priv->ioaddr + MTL_DBG_CTL); ++ ++ return ret; ++} ++ ++static ssize_t sunxi_dwmac_ecc_inject_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return scnprintf(buf, PAGE_SIZE, ++ "Usage:\n" ++ "echo \"[dir] [inject_bit]\" > ecc_inject\n\n" ++ "[dir] : 0(tx) 1(rx)\n" ++ "[inject_bit] : 0/1/2\n"); ++} ++ ++static ssize_t sunxi_dwmac_ecc_inject_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ struct phy_device *phydev = priv->dev->phydev; ++ static const char *dir_str[] = {"tx", "rx"}; ++ u16 dir, inject_bit; ++ u64 ret; ++ ++ if (!ndev || !phydev) { ++ sunxi_err(chip->dev, "netdevice or phy not found\n"); ++ return -EINVAL; ++ } ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(chip->dev, "netdevice is not running\n"); ++ return -EINVAL; ++ } ++ ++ if (!(chip->variant->flags & SUNXI_DWMAC_MEM_ECC)) { ++ sunxi_err(chip->dev, "ecc not support or enabled\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ ret = sunxi_dwmac_parse_read_str((char *)buf, &dir, &inject_bit); ++ if (ret) ++ return ret; ++ ++ switch (dir) { ++ case 0: ++ dir = SUNXI_DWMAC_ECC_FIFO_TX; ++ break; ++ case 1: ++ dir = SUNXI_DWMAC_ECC_FIFO_RX; ++ break; ++ default: ++ sunxi_err(chip->dev, "test unsupport ecc dir %d\n", dir); ++ return -EINVAL; ++ } ++ ++ netif_testing_on(ndev); ++ ++ /* ecc inject test */ ++ ret = sunxi_dwmac_test_ecc_inject(priv, dir, inject_bit); ++ if (ret) ++ sunxi_info(chip->dev, "test ecc %s inject %d bit : FAILED\n", dir_str[dir], inject_bit); ++ else ++ sunxi_info(chip->dev, "test ecc %s inject %d bit : PASS\n", dir_str[dir], inject_bit); ++ ++ netif_testing_off(ndev); ++ ++ return count; ++} ++ ++static ssize_t sunxi_dwmac_tx_delay_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ u32 delay = chip->variant->get_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX); ++ ++ return scnprintf(buf, PAGE_SIZE, ++ "Usage:\n" ++ "echo [0~%d] > tx_delay\n\n" ++ "now tx_delay: %d\n", ++ chip->variant->tx_delay_max, delay); ++} ++ ++static ssize_t sunxi_dwmac_tx_delay_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ int ret; ++ u32 delay; ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(dev, "Eth is not running\n"); ++ return count; ++ } ++ ++ ret = kstrtou32(buf, 0, &delay); ++ if (ret) ++ return ret; ++ ++ if (delay > chip->variant->tx_delay_max) { ++ sunxi_err(dev, "Tx_delay exceed max %d\n", chip->variant->tx_delay_max); ++ return -EINVAL; ++ } ++ ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_TX, delay); ++ ++ return count; ++} ++ ++static ssize_t sunxi_dwmac_rx_delay_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ u32 delay = chip->variant->get_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX); ++ ++ return scnprintf(buf, PAGE_SIZE, ++ "Usage:\n" ++ "echo [0~%d] > rx_delay\n\n" ++ "now rx_delay: %d\n", ++ chip->variant->rx_delay_max, delay); ++} ++ ++static ssize_t sunxi_dwmac_rx_delay_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ int ret; ++ u32 delay; ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(dev, "Eth is not running\n"); ++ return count; ++ } ++ ++ ret = kstrtou32(buf, 0, &delay); ++ if (ret) ++ return ret; ++ ++ if (delay > chip->variant->rx_delay_max) { ++ sunxi_err(dev, "Rx_delay exceed max %d\n", chip->variant->rx_delay_max); ++ return -EINVAL; ++ } ++ ++ chip->variant->set_delaychain(chip, SUNXI_DWMAC_DELAYCHAIN_RX, delay); ++ ++ return count; ++} ++ ++static ssize_t sunxi_dwmac_mii_read_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(dev, "Eth is not running\n"); ++ return 0; ++ } ++ ++ chip->mii_reg.value = mdiobus_read(priv->mii, chip->mii_reg.addr, chip->mii_reg.reg); ++ return sprintf(buf, "ADDR[0x%02x]:REG[0x%02x] = 0x%04x\n", ++ chip->mii_reg.addr, chip->mii_reg.reg, chip->mii_reg.value); ++} ++ ++static ssize_t sunxi_dwmac_mii_read_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ int ret; ++ u16 reg, addr; ++ char *ptr; ++ ++ ptr = (char *)buf; ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(dev, "Eth is not running\n"); ++ return count; ++ } ++ ++ ret = sunxi_dwmac_parse_read_str(ptr, &addr, ®); ++ if (ret) ++ return ret; ++ ++ chip->mii_reg.addr = addr; ++ chip->mii_reg.reg = reg; ++ ++ return count; ++} ++ ++static ssize_t sunxi_dwmac_mii_write_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ u16 bef_val, aft_val; ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(dev, "Eth is not running\n"); ++ return 0; ++ } ++ ++ bef_val = mdiobus_read(priv->mii, chip->mii_reg.addr, chip->mii_reg.reg); ++ mdiobus_write(priv->mii, chip->mii_reg.addr, chip->mii_reg.reg, chip->mii_reg.value); ++ aft_val = mdiobus_read(priv->mii, chip->mii_reg.addr, chip->mii_reg.reg); ++ return sprintf(buf, "before ADDR[0x%02x]:REG[0x%02x] = 0x%04x\n" ++ "after ADDR[0x%02x]:REG[0x%02x] = 0x%04x\n", ++ chip->mii_reg.addr, chip->mii_reg.reg, bef_val, ++ chip->mii_reg.addr, chip->mii_reg.reg, aft_val); ++} ++ ++static ssize_t sunxi_dwmac_mii_write_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ int ret; ++ u16 reg, addr, val; ++ char *ptr; ++ ++ ptr = (char *)buf; ++ ++ if (!netif_running(ndev)) { ++ sunxi_err(dev, "Eth is not running\n"); ++ return count; ++ } ++ ++ ret = sunxi_dwmac_parse_write_str(ptr, &addr, ®, &val); ++ if (ret) ++ return ret; ++ ++ chip->mii_reg.reg = reg; ++ chip->mii_reg.addr = addr; ++ chip->mii_reg.value = val; ++ ++ return count; ++} ++ ++static ssize_t sunxi_dwmac_version_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_dwmac *chip = priv->plat->bsp_priv; ++ u16 ip_tag, ip_vrm; ++ ssize_t count = 0; ++ ++ if (chip->variant->get_version) { ++ chip->variant->get_version(chip, &ip_tag, &ip_vrm); ++ count = sprintf(buf, "IP TAG: %x\nIP VRM: %x\n", ip_tag, ip_vrm); ++ } ++ ++ return count; ++} ++ ++static struct device_attribute sunxi_dwmac_tool_attr[] = { ++ __ATTR(calibrate, 0220, NULL, sunxi_dwmac_calibrate_store), ++ __ATTR(rx_delay, 0664, sunxi_dwmac_rx_delay_show, sunxi_dwmac_rx_delay_store), ++ __ATTR(tx_delay, 0664, sunxi_dwmac_tx_delay_show, sunxi_dwmac_tx_delay_store), ++ __ATTR(mii_read, 0664, sunxi_dwmac_mii_read_show, sunxi_dwmac_mii_read_store), ++ __ATTR(mii_write, 0664, sunxi_dwmac_mii_write_show, sunxi_dwmac_mii_write_store), ++ __ATTR(ecc_inject, 0664, sunxi_dwmac_ecc_inject_show, sunxi_dwmac_ecc_inject_store), ++ __ATTR(version, 0444, sunxi_dwmac_version_show, NULL), ++}; ++ ++void sunxi_dwmac_sysfs_init(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(sunxi_dwmac_tool_attr); i++) ++ device_create_file(dev, &sunxi_dwmac_tool_attr[i]); ++} ++ ++void sunxi_dwmac_sysfs_exit(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(sunxi_dwmac_tool_attr); i++) ++ device_remove_file(dev, &sunxi_dwmac_tool_attr[i]); ++} +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.h linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.h +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/dwmac-sunxi-sysfs.h 2025-01-21 15:58:05.577494134 +0100 +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++* ++* Allwinner DWMAC driver sysfs haeder. ++* ++* Copyright(c) 2022-2027 Allwinnertech Co., Ltd. ++* ++*/ ++ ++#ifndef _DWMAC_SUNXI_SYSFS_H_ ++#define _DWMAC_SUNXI_SYSFS_H_ ++ ++#include "dwmac-sunxi.h" ++ ++void sunxi_dwmac_sysfs_init(struct device *dev); ++void sunxi_dwmac_sysfs_exit(struct device *dev); ++ ++#endif /* _DWMAC_SUNXI_SYSFS_H_ */ ++ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Kconfig linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Kconfig +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Kconfig 2025-01-23 10:54:36.827432742 +0100 +@@ -0,0 +1,34 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++menu "Stmmac Drivers" ++ ++config SUNXI55I_GMAC200 ++ tristate "Allwinner A523 GMAC-200 driver" ++ depends on OF && (ARCH_SUNXI || COMPILE_TEST) ++ select STMMAC_ETH ++ select STMMAC_PLATFORM ++ select SUNXI55I_STMMAC ++ ++ help ++ Support for Allwinner A523 GMAC-200/GMAC-300 ethernet controllers. ++ ++ This selects Allwinner A523 SoC glue layer support for the ++ stmmac device driver. This driver is used for ++ GMAC-200/GMAC-300 ethernet controller. ++ ++if SUNXI55I_GMAC200 ++config SUNXI55I_STMMAC ++ tristate "Allwinner A523 GMAC-200 STMMAC support" ++ depends on OF && (ARCH_SUNXI || COMPILE_TEST) ++ help ++ Support stmmac device driver for Allwinner A523 GMAC-200/GMAC-300. ++ ++config SUNXI55I_STMMAC_UIO ++ tristate "Allwinner A523 GMAC-200 UIO ethernet controller" ++ default n ++ select UIO ++ help ++ Say M here if you want to use the sunxi-uio.ko for DPDK on A523. ++ ++endif ++ ++endmenu +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Makefile linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Makefile +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/Makefile 2025-01-23 10:41:37.537411780 +0100 +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ccflags-y += -I $(srctree)/include/linux/ ++ccflags-y += -I $(srctree)/drivers/net/ethernet/stmicro/ ++ccflags-y += -DDYNAMIC_DEBUG_MODULE ++ ++obj-$(CONFIG_SUNXI55I_STMMAC) += sunxi-stmmac.o ++sunxi-stmmac-objs += dwmac-sunxi.o dwmac-sunxi-sysfs.o ++obj-$(CONFIG_SUNXI55I_STMMAC_UIO) += sunxi-uio.o +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-log.h linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-log.h +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-log.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-log.h 2025-01-21 15:58:05.577494134 +0100 +@@ -0,0 +1,174 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++ * Allwinner's log functions ++ * ++ * Copyright (c) 2023, lvda ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ */ ++ ++#ifndef __SUNXI_LOG_H__ ++#define __SUNXI_LOG_H__ ++ ++#define SUNXI_LOG_VERSION "V0.7" ++/* Allow user to define their own MODNAME with `SUNXI_MODNAME` */ ++#ifndef SUNXI_MODNAME ++#define SUNXI_MODNAME KBUILD_MODNAME ++#endif ++ ++#ifdef pr_fmt ++#undef pr_fmt ++#endif ++ ++#ifdef dev_fmt ++#undef dev_fmt ++#endif ++ ++#define pr_fmt(fmt) "sunxi:" SUNXI_MODNAME fmt ++#define dev_fmt pr_fmt ++ ++#include ++#include ++ ++/* ++ * Copy from dev_name(). Someone like to use "dev_name" as local variable, ++ * which will case compile error. ++ */ ++static inline const char *sunxi_log_dev_name(const struct device *dev) ++{ ++ /* Use the init name until the kobject becomes available */ ++ if (dev->init_name) ++ return dev->init_name; ++ ++ return kobject_name(&dev->kobj); ++} ++ ++/* ++ * Parameter Description: ++ * 1. dev: Optional parameter. If the context cannot obtain dev, fill in NULL ++ * 2. fmt: Format specifier ++ * 3. err_code: Error code. Only used in sunxi_err_std() ++ * 4. ...: Variable arguments ++ */ ++ ++#if IS_ENABLED(CONFIG_AW_LOG_VERBOSE) ++ ++/* void sunxi_err(struct device *dev, char *fmt, ...); */ ++#define sunxi_err(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_err("-%s:[ERR]:%s +%d %s(): "fmt, sunxi_log_dev_name(dev), __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ else \ ++ pr_err(":[ERR]:%s +%d %s(): "fmt, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_err_std(struct device *dev, int err_code, char *fmt, ...); */ ++#define sunxi_err_std(dev, err_code, fmt, ...) \ ++ do { if (dev) \ ++ pr_err("-%s:[ERR%d]:%s +%d %s(): "fmt, sunxi_log_dev_name(dev), err_code, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ else \ ++ pr_err(":[ERR%d]:%s +%d %s(): "fmt, err_code, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_warn(struct device *dev, char *fmt, ...); */ ++#define sunxi_warn(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_warn("-%s:[WARN]:%s +%d %s(): "fmt, sunxi_log_dev_name(dev), __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ else \ ++ pr_warn(":[WARN]:%s +%d %s(): "fmt, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_info(struct device *dev, char *fmt, ...); */ ++#define sunxi_info(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_info("-%s:[INFO]:%s +%d %s(): "fmt, sunxi_log_dev_name(dev), __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ else \ ++ pr_info(":[INFO]:%s +%d %s(): "fmt, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_debug(struct device *dev, char *fmt, ...); */ ++#define sunxi_debug(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_debug("-%s:[DEBUG]:%s +%d %s(): "fmt, sunxi_log_dev_name(dev), __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ else \ ++ pr_debug(":[DEBUG]:%s +%d %s(): "fmt, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++#else /* !CONFIG_AW_LOG_VERBOSE */ ++ ++/* void sunxi_err(struct device *dev, char *fmt, ...); */ ++#define sunxi_err(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_err("-%s:[ERR]: "fmt, sunxi_log_dev_name(dev), ## __VA_ARGS__); \ ++ else \ ++ pr_err(":[ERR]: "fmt, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_err_std(struct device *dev, int err_code, char *fmt, ...); */ ++#define sunxi_err_std(dev, err_code, fmt, ...) \ ++ do { if (dev) \ ++ pr_err("-%s:[ERR%d]: "fmt, sunxi_log_dev_name(dev), err_code, ## __VA_ARGS__); \ ++ else \ ++ pr_err(":[ERR%d]: "fmt, err_code, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_warn(struct device *dev, char *fmt, ...); */ ++#define sunxi_warn(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_warn("-%s:[WARN]: "fmt, sunxi_log_dev_name(dev), ## __VA_ARGS__); \ ++ else \ ++ pr_warn(":[WARN]: "fmt, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_info(struct device *dev, char *fmt, ...); */ ++#define sunxi_info(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_info("-%s:[INFO]: "fmt, sunxi_log_dev_name(dev), ## __VA_ARGS__); \ ++ else \ ++ pr_info(":[INFO]: "fmt, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_debug(struct device *dev, char *fmt, ...); */ ++#define sunxi_debug(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_debug("-%s:[DEBUG]: "fmt, sunxi_log_dev_name(dev), ## __VA_ARGS__); \ ++ else \ ++ pr_debug(":[DEBUG]: "fmt, ## __VA_ARGS__); \ ++ } while (0) ++ ++#endif /* CONFIG_AW_LOG_VERBOSE */ ++ ++/* void sunxi_debug_verbose(struct device *dev, char *fmt, ...); */ ++#define sunxi_debug_verbose(dev, fmt, ...) \ ++ do { if (dev) \ ++ pr_debug("-%s:[DEBUG]:%s +%d %s(): "fmt, sunxi_log_dev_name(dev), __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ else \ ++ pr_debug(":[DEBUG]:%s +%d %s(): "fmt, __FILE__, __LINE__, __func__, ## __VA_ARGS__); \ ++ } while (0) ++ ++/* void sunxi_debug_line(struct device *dev); */ ++#define sunxi_debug_line(dev) \ ++ do { if (dev) \ ++ pr_debug("-%s:[DEBUG]:%s +%d %s()\n", sunxi_log_dev_name(dev), __FILE__, __LINE__, __func__); \ ++ else \ ++ pr_debug(":[DEBUG]:%s +%d %s()\n", __FILE__, __LINE__, __func__); \ ++ } while (0) ++ ++/* ++ * TODO: ++ * print_hex_dump_debug ++ * print_hex_dump_bytes ++ * trace_printk ++ * printk_ratelimited ++*/ ++ ++#endif +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-uio.c linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-uio.c +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-uio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac-200/sunxi-uio.c 2025-01-21 15:58:05.577494134 +0100 +@@ -0,0 +1,1015 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/** ++ * Copyright 2023 Allwinnertech ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "stmmac/stmmac_ptp.h" ++#include "stmmac/stmmac.h" ++#include "hwif.h" ++ ++#define DRIVER_NAME "sunxi_uio" ++#define DRIVER_VERSION "0.0.1" ++ ++#define TC_DEFAULT 64 ++static int tc = TC_DEFAULT; ++ ++#define DEFAULT_BUFSIZE 1536 ++static int buf_sz = DEFAULT_BUFSIZE; ++ ++#define STMMAC_RX_COPYBREAK 256 ++ ++/** ++ * sunxi_uio ++ * local information for uio module driver ++ * ++ * @dev: device pointer ++ * @ndev: network device pointer ++ * @name: uio name ++ * @uio: uio information ++ * @map_num: number of uio memory regions ++ */ ++struct sunxi_uio { ++ struct device *dev; ++ struct net_device *ndev; ++ char name[16]; ++ struct uio_info uio; ++ int map_num; ++}; ++ ++static int sunxi_uio_open(struct uio_info *info, struct inode *inode) ++{ ++ return 0; ++} ++ ++static int sunxi_uio_release(struct uio_info *info, ++ struct inode *inode) ++{ ++ return 0; ++} ++ ++static int sunxi_uio_mmap(struct uio_info *info, ++ struct vm_area_struct *vma) ++{ ++ u32 ret, pfn; ++ ++ pfn = (info->mem[vma->vm_pgoff].addr) >> PAGE_SHIFT; ++ ++ if (vma->vm_pgoff) ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ else ++ vma->vm_page_prot = pgprot_device(vma->vm_page_prot); ++ ++ ret = remap_pfn_range(vma, vma->vm_start, pfn, ++ vma->vm_end - vma->vm_start, vma->vm_page_prot); ++ if (ret) { ++ /* Error Handle */ ++ pr_err("remap_pfn_range failed"); ++ } ++ return ret; ++} ++ ++/** ++ * sunxi_uio_free_dma_rx_desc_resources - free RX dma desc resources ++ * @priv: private structure ++ */ ++static void sunxi_uio_free_dma_rx_desc_resources(struct stmmac_priv *priv) ++{ ++ u32 queue, rx_count = priv->plat->rx_queues_to_use; ++ ++ /* Free RX queue resources */ ++ for (queue = 0; queue < rx_count; queue++) { ++ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; ++ ++ /* Free DMA regions of consistent memory previously allocated */ ++ if (!priv->extend_desc) ++ dma_free_coherent(priv->device, priv->dma_rx_size * ++ sizeof(struct dma_desc), ++ rx_q->dma_rx, rx_q->dma_rx_phy); ++ else ++ dma_free_coherent(priv->device, priv->dma_rx_size * ++ sizeof(struct dma_extended_desc), ++ rx_q->dma_erx, rx_q->dma_rx_phy); ++ } ++} ++ ++/** ++ * sunxi_uio_free_dma_tx_desc_resources - free TX dma desc resources ++ * @priv: private structure ++ */ ++static void sunxi_uio_free_dma_tx_desc_resources(struct stmmac_priv *priv) ++{ ++ u32 queue, tx_count = priv->plat->tx_queues_to_use; ++ ++ /* Free TX queue resources */ ++ for (queue = 0; queue < tx_count; queue++) { ++ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; ++ size_t size; ++ void *addr; ++ ++ if (priv->extend_desc) { ++ size = sizeof(struct dma_extended_desc); ++ addr = tx_q->dma_etx; ++ } else if (tx_q->tbs & STMMAC_TBS_AVAIL) { ++ size = sizeof(struct dma_edesc); ++ addr = tx_q->dma_entx; ++ } else { ++ size = sizeof(struct dma_desc); ++ addr = tx_q->dma_tx; ++ } ++ ++ size *= priv->dma_tx_size; ++ ++ dma_free_coherent(priv->device, size, addr, tx_q->dma_tx_phy); ++ } ++} ++ ++/** ++ * sunxi_uio_alloc_dma_rx_desc_resources - alloc RX resources. ++ * @priv: private structure ++ * Description: according to which descriptor can be used (extend or basic) ++ * this function allocates the resources for TX and RX paths. In case of ++ * reception, for example, it pre-allocated the RX socket buffer in order to ++ * allow zero-copy mechanism. ++ */ ++static int sunxi_uio_alloc_dma_rx_desc_resources(struct stmmac_priv *priv) ++{ ++ u32 queue, rx_count = priv->plat->rx_queues_to_use; ++ int ret = -ENOMEM; ++ ++ /* RX queues buffers and DMA */ ++ for (queue = 0; queue < rx_count; queue++) { ++ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; ++ ++ if (priv->extend_desc) { ++ rx_q->dma_erx = dma_alloc_coherent(priv->device, ++ priv->dma_rx_size * ++ sizeof(struct dma_extended_desc), ++ &rx_q->dma_rx_phy, ++ GFP_KERNEL); ++ if (!rx_q->dma_erx) ++ goto err_dma; ++ } else { ++ rx_q->dma_rx = dma_alloc_coherent(priv->device, ++ priv->dma_rx_size * ++ sizeof(struct dma_desc), ++ &rx_q->dma_rx_phy, ++ GFP_KERNEL); ++ if (!rx_q->dma_rx) ++ goto err_dma; ++ } ++ } ++ ++ return 0; ++ ++err_dma: ++ sunxi_uio_free_dma_rx_desc_resources(priv); ++ ++ return ret; ++} ++ ++/** ++ * sunxi_uio_alloc_dma_tx_desc_resources - alloc TX resources. ++ * @priv: private structure ++ * Description: according to which descriptor can be used (extend or basic) ++ * this function allocates the resources for TX and RX paths. In case of ++ * reception, for example, it pre-allocated the RX socket buffer in order to ++ * allow zero-copy mechanism. ++ */ ++static int sunxi_uio_alloc_dma_tx_desc_resources(struct stmmac_priv *priv) ++{ ++ u32 queue, tx_count = priv->plat->tx_queues_to_use; ++ int ret = -ENOMEM; ++ ++ /* TX queues buffers and DMA */ ++ for (queue = 0; queue < tx_count; queue++) { ++ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; ++ size_t size; ++ void *addr; ++ ++ tx_q->queue_index = queue; ++ tx_q->priv_data = priv; ++ ++ if (priv->extend_desc) ++ size = sizeof(struct dma_extended_desc); ++ else if (tx_q->tbs & STMMAC_TBS_AVAIL) ++ size = sizeof(struct dma_edesc); ++ else ++ size = sizeof(struct dma_desc); ++ ++ size *= priv->dma_tx_size; ++ ++ addr = dma_alloc_coherent(priv->device, size, ++ &tx_q->dma_tx_phy, GFP_KERNEL); ++ if (!addr) ++ goto err_dma; ++ ++ if (priv->extend_desc) ++ tx_q->dma_etx = addr; ++ else if (tx_q->tbs & STMMAC_TBS_AVAIL) ++ tx_q->dma_entx = addr; ++ else ++ tx_q->dma_tx = addr; ++ } ++ ++ return 0; ++ ++err_dma: ++ sunxi_uio_free_dma_tx_desc_resources(priv); ++ return ret; ++} ++ ++/** ++ * sunxi_uio_alloc_dma_desc_resources - alloc TX/RX resources. ++ * @priv: private structure ++ * Description: according to which descriptor can be used (extend or basic) ++ * this function allocates the resources for TX and RX paths. In case of ++ * reception, for example, it pre-allocated the RX socket buffer in order to ++ * allow zero-copy mechanism. ++ */ ++static int sunxi_uio_alloc_dma_desc_resources(struct stmmac_priv *priv) ++{ ++ /* RX Allocation */ ++ int ret = sunxi_uio_alloc_dma_rx_desc_resources(priv); ++ ++ if (ret) ++ return ret; ++ ++ ret = sunxi_uio_alloc_dma_tx_desc_resources(priv); ++ ++ return ret; ++} ++ ++/** ++ * sunxi_uio_free_dma_desc_resources - free dma desc resources ++ * @priv: private structure ++ */ ++static void sunxi_uio_free_dma_desc_resources(struct stmmac_priv *priv) ++{ ++ /* Release the DMA RX socket buffers */ ++ sunxi_uio_free_dma_rx_desc_resources(priv); ++ ++ /* Release the DMA TX socket buffers */ ++ sunxi_uio_free_dma_tx_desc_resources(priv); ++} ++ ++/** ++ * sunxi_uio_init_phy - PHY initialization ++ * @dev: net device structure ++ * Description: it initializes the driver's PHY state, and attaches the PHY ++ * to the mac driver. ++ * Return value: ++ * 0 on success ++ */ ++static int sunxi_uio_init_phy(struct net_device *dev) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ struct device_node *node; ++ int ret; ++ ++ node = priv->plat->phylink_node; ++ ++ if (node) ++ ret = phylink_of_phy_connect(priv->phylink, node, 0); ++ ++ /* Some DT bindings do not set-up the PHY handle. Let's try to ++ * manually parse it ++ */ ++ if (!node || ret) { ++ int addr = priv->plat->phy_addr; ++ struct phy_device *phydev; ++ ++ phydev = mdiobus_get_phy(priv->mii, addr); ++ if (!phydev) { ++ netdev_err(priv->dev, "no phy at addr %d\n", addr); ++ return -ENODEV; ++ } ++ ++ ret = phylink_connect_phy(priv->phylink, phydev); ++ } ++ ++ if (!priv->plat->pmt) { ++ struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; ++ ++ phylink_ethtool_get_wol(priv->phylink, &wol); ++ device_set_wakeup_capable(priv->device, !!wol.supported); ++ } ++ ++ return ret; ++} ++ ++/** ++ * sunxi_uio_init_dma_engine - DMA init. ++ * @priv: driver private structure ++ * Description: ++ * It inits the DMA invoking the specific MAC/GMAC callback. ++ * Some DMA parameters can be passed from the platform; ++ * in case of these are not passed a default is kept for the MAC or GMAC. ++ */ ++static int sunxi_uio_init_dma_engine(struct stmmac_priv *priv) ++{ ++ u32 rx_channels_count = priv->plat->rx_queues_to_use; ++ u32 tx_channels_count = priv->plat->tx_queues_to_use; ++ u32 dma_csr_ch = max(rx_channels_count, tx_channels_count); ++ struct stmmac_rx_queue *rx_q; ++ struct stmmac_tx_queue *tx_q; ++ u32 chan = 0; ++ int atds = 0, ret = 0; ++ ++ if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) { ++ dev_err(priv->device, "Invalid DMA configuration\n"); ++ return -EINVAL; ++ } ++ ++ if (priv->extend_desc && priv->mode == STMMAC_RING_MODE) ++ atds = 1; ++ ++ ret = stmmac_reset(priv, priv->ioaddr); ++ if (ret) { ++ dev_err(priv->device, "Failed to reset the dma\n"); ++ return ret; ++ } ++ ++ /* DMA Configuration */ ++ stmmac_dma_init(priv, priv->ioaddr, priv->plat->dma_cfg, atds); ++ ++ if (priv->plat->axi) ++ stmmac_axi(priv, priv->ioaddr, priv->plat->axi); ++ ++ /* DMA CSR Channel configuration */ ++ for (chan = 0; chan < dma_csr_ch; chan++) ++ stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan); ++ ++ /* DMA RX Channel Configuration */ ++ for (chan = 0; chan < rx_channels_count; chan++) { ++ rx_q = &priv->rx_queue[chan]; ++ ++ stmmac_init_rx_chan(priv, priv->ioaddr, priv->plat->dma_cfg, ++ rx_q->dma_rx_phy, chan); ++ ++ rx_q->rx_tail_addr = rx_q->dma_rx_phy + ++ (priv->dma_rx_size * ++ sizeof(struct dma_desc)); ++ stmmac_set_rx_tail_ptr(priv, priv->ioaddr, ++ rx_q->rx_tail_addr, chan); ++ } ++ ++ /* DMA TX Channel Configuration */ ++ for (chan = 0; chan < tx_channels_count; chan++) { ++ tx_q = &priv->tx_queue[chan]; ++ ++ stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg, ++ tx_q->dma_tx_phy, chan); ++ ++ tx_q->tx_tail_addr = tx_q->dma_tx_phy; ++ stmmac_set_tx_tail_ptr(priv, priv->ioaddr, ++ tx_q->tx_tail_addr, chan); ++ } ++ ++ return ret; ++} ++ ++static void sunxi_uio_set_rings_length(struct stmmac_priv *priv) ++{ ++ u32 rx_channels_count = priv->plat->rx_queues_to_use; ++ u32 tx_channels_count = priv->plat->tx_queues_to_use; ++ u32 chan; ++ ++ /* set TX ring length */ ++ for (chan = 0; chan < tx_channels_count; chan++) ++ stmmac_set_tx_ring_len(priv, priv->ioaddr, ++ (priv->dma_tx_size - 1), chan); ++ ++ /* set RX ring length */ ++ for (chan = 0; chan < rx_channels_count; chan++) ++ stmmac_set_rx_ring_len(priv, priv->ioaddr, ++ (priv->dma_rx_size - 1), chan); ++} ++ ++/** ++ * sunxi_uio_set_tx_queue_weight - Set TX queue weight ++ * @priv: driver private structure ++ * Description: It is used for setting TX queues weight ++ */ ++static void sunxi_uio_set_tx_queue_weight(struct stmmac_priv *priv) ++{ ++ u32 tx_queues_count = priv->plat->tx_queues_to_use; ++ u32 weight, queue; ++ ++ for (queue = 0; queue < tx_queues_count; queue++) { ++ weight = priv->plat->tx_queues_cfg[queue].weight; ++ stmmac_set_mtl_tx_queue_weight(priv, priv->hw, weight, queue); ++ } ++} ++ ++/** ++ * sunxi_uio_configure_cbs - Configure CBS in TX queue ++ * @priv: driver private structure ++ * Description: It is used for configuring CBS in AVB TX queues ++ */ ++static void sunxi_uio_configure_cbs(struct stmmac_priv *priv) ++{ ++ u32 tx_queues_count = priv->plat->tx_queues_to_use; ++ u32 mode_to_use, queue; ++ ++ /* queue 0 is reserved for legacy traffic */ ++ for (queue = 1; queue < tx_queues_count; queue++) { ++ mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use; ++ if (mode_to_use == MTL_QUEUE_DCB) ++ continue; ++ ++ stmmac_config_cbs(priv, priv->hw, ++ priv->plat->tx_queues_cfg[queue].send_slope, ++ priv->plat->tx_queues_cfg[queue].idle_slope, ++ priv->plat->tx_queues_cfg[queue].high_credit, ++ priv->plat->tx_queues_cfg[queue].low_credit, ++ queue); ++ } ++} ++ ++/** ++ * sunxi_uio_rx_queue_dma_chan_map - Map RX queue to RX dma channel ++ * @priv: driver private structure ++ * Description: It is used for mapping RX queues to RX dma channels ++ */ ++static void sunxi_uio_rx_queue_dma_chan_map(struct stmmac_priv *priv) ++{ ++ u32 rx_queues_count = priv->plat->rx_queues_to_use; ++ u32 queue, chan; ++ ++ for (queue = 0; queue < rx_queues_count; queue++) { ++ chan = priv->plat->rx_queues_cfg[queue].chan; ++ stmmac_map_mtl_to_dma(priv, priv->hw, queue, chan); ++ } ++} ++ ++/** ++ * sunxi_uio_mac_config_rx_queues_prio - Configure RX Queue priority ++ * @priv: driver private structure ++ * Description: It is used for configuring the RX Queue Priority ++ */ ++static void sunxi_uio_mac_config_rx_queues_prio(struct stmmac_priv *priv) ++{ ++ u32 rx_queues_count = priv->plat->rx_queues_to_use; ++ u32 queue, prio; ++ ++ for (queue = 0; queue < rx_queues_count; queue++) { ++ if (!priv->plat->rx_queues_cfg[queue].use_prio) ++ continue; ++ ++ prio = priv->plat->rx_queues_cfg[queue].prio; ++ stmmac_rx_queue_prio(priv, priv->hw, prio, queue); ++ } ++} ++ ++/** ++ * sunxi_uio_mac_config_tx_queues_prio - Configure TX Queue priority ++ * @priv: driver private structure ++ * Description: It is used for configuring the TX Queue Priority ++ */ ++static void sunxi_uio_mac_config_tx_queues_prio(struct stmmac_priv *priv) ++{ ++ u32 tx_queues_count = priv->plat->tx_queues_to_use; ++ u32 queue, prio; ++ ++ for (queue = 0; queue < tx_queues_count; queue++) { ++ if (!priv->plat->tx_queues_cfg[queue].use_prio) ++ continue; ++ ++ prio = priv->plat->tx_queues_cfg[queue].prio; ++ stmmac_tx_queue_prio(priv, priv->hw, prio, queue); ++ } ++} ++ ++/** ++ * sunxi_uio_mac_config_rx_queues_routing - Configure RX Queue Routing ++ * @priv: driver private structure ++ * Description: It is used for configuring the RX queue routing ++ */ ++static void sunxi_uio_mac_config_rx_queues_routing(struct stmmac_priv *priv) ++{ ++ u32 rx_queues_count = priv->plat->rx_queues_to_use; ++ u32 queue; ++ u8 packet; ++ ++ for (queue = 0; queue < rx_queues_count; queue++) { ++ /* no specific packet type routing specified for the queue */ ++ if (priv->plat->rx_queues_cfg[queue].pkt_route == 0x0) ++ continue; ++ ++ packet = priv->plat->rx_queues_cfg[queue].pkt_route; ++ stmmac_rx_queue_routing(priv, priv->hw, packet, queue); ++ } ++} ++ ++static void sunxi_uio_mac_config_rss(struct stmmac_priv *priv) ++{ ++ if (!priv->dma_cap.rssen || !priv->plat->rss_en) { ++ priv->rss.enable = false; ++ return; ++ } ++ ++ if (priv->dev->features & NETIF_F_RXHASH) ++ priv->rss.enable = true; ++ else ++ priv->rss.enable = false; ++ ++ stmmac_rss_configure(priv, priv->hw, &priv->rss, ++ priv->plat->rx_queues_to_use); ++} ++ ++/** ++ * sunxi_uio_mac_enable_rx_queues - Enable MAC rx queues ++ * @priv: driver private structure ++ * Description: It is used for enabling the rx queues in the MAC ++ */ ++static void sunxi_uio_mac_enable_rx_queues(struct stmmac_priv *priv) ++{ ++ u32 rx_queues_count = priv->plat->rx_queues_to_use; ++ int queue; ++ u8 mode; ++ ++ for (queue = 0; queue < rx_queues_count; queue++) { ++ mode = priv->plat->rx_queues_cfg[queue].mode_to_use; ++ stmmac_rx_queue_enable(priv, priv->hw, mode, queue); ++ } ++} ++ ++/** ++ * sunxi_uio_mtl_configuration - Configure MTL ++ * @priv: driver private structure ++ * Description: It is used for configuring MTL ++ */ ++static void sunxi_uio_mtl_configuration(struct stmmac_priv *priv) ++{ ++ u32 rx_queues_count = priv->plat->rx_queues_to_use; ++ u32 tx_queues_count = priv->plat->tx_queues_to_use; ++ ++ if (tx_queues_count > 1) ++ sunxi_uio_set_tx_queue_weight(priv); ++ ++ /* Configure MTL RX algorithms */ ++ if (rx_queues_count > 1) ++ stmmac_prog_mtl_rx_algorithms(priv, priv->hw, ++ priv->plat->rx_sched_algorithm); ++ ++ /* Configure MTL TX algorithms */ ++ if (tx_queues_count > 1) ++ stmmac_prog_mtl_tx_algorithms(priv, priv->hw, ++ priv->plat->tx_sched_algorithm); ++ ++ /* Configure CBS in AVB TX queues */ ++ if (tx_queues_count > 1) ++ sunxi_uio_configure_cbs(priv); ++ ++ /* Map RX MTL to DMA channels */ ++ sunxi_uio_rx_queue_dma_chan_map(priv); ++ ++ /* Enable MAC RX Queues */ ++ sunxi_uio_mac_enable_rx_queues(priv); ++ ++ /* Set RX priorities */ ++ if (rx_queues_count > 1) ++ sunxi_uio_mac_config_rx_queues_prio(priv); ++ ++ /* Set TX priorities */ ++ if (tx_queues_count > 1) ++ sunxi_uio_mac_config_tx_queues_prio(priv); ++ ++ /* Set RX routing */ ++ if (rx_queues_count > 1) ++ sunxi_uio_mac_config_rx_queues_routing(priv); ++ ++ /* Receive Side Scaling */ ++ if (rx_queues_count > 1) ++ sunxi_uio_mac_config_rss(priv); ++} ++ ++static void sunxi_uio_safety_feat_configuration(struct stmmac_priv *priv) ++{ ++ if (priv->dma_cap.asp) { ++ netdev_info(priv->dev, "Enabling Safety Features\n"); ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) ++ stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp); ++#else ++ stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp, ++ priv->plat->safety_feat_cfg); ++#endif ++ } else { ++ netdev_info(priv->dev, "No Safety Features support found\n"); ++ } ++} ++ ++/** ++ * sunxi_uio_dma_operation_mode - HW DMA operation mode ++ * @priv: driver private structure ++ * Description: it is used for configuring the DMA operation mode register in ++ * order to program the tx/rx DMA thresholds or Store-And-Forward mode. ++ */ ++static void sunxi_uio_dma_operation_mode(struct stmmac_priv *priv) ++{ ++ u32 rx_channels_count = priv->plat->rx_queues_to_use; ++ u32 tx_channels_count = priv->plat->tx_queues_to_use; ++ int rxfifosz = priv->plat->rx_fifo_size; ++ int txfifosz = priv->plat->tx_fifo_size; ++ u32 txmode = 0, rxmode = 0, chan = 0; ++ u8 qmode = 0; ++ ++ if (rxfifosz == 0) ++ rxfifosz = priv->dma_cap.rx_fifo_size; ++ if (txfifosz == 0) ++ txfifosz = priv->dma_cap.tx_fifo_size; ++ ++ /* Adjust for real per queue fifo size */ ++ rxfifosz /= rx_channels_count; ++ txfifosz /= tx_channels_count; ++ ++ if (priv->plat->force_thresh_dma_mode) { ++ txmode = tc; ++ rxmode = tc; ++ } else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { ++ /* In case of GMAC, SF mode can be enabled ++ * to perform the TX COE in HW. This depends on: ++ * 1) TX COE if actually supported ++ * 2) There is no bugged Jumbo frame support ++ * that needs to not insert csum in the TDES. ++ */ ++ txmode = SF_DMA_MODE; ++ rxmode = SF_DMA_MODE; ++ priv->xstats.threshold = SF_DMA_MODE; ++ } else { ++ txmode = tc; ++ rxmode = SF_DMA_MODE; ++ } ++ ++ /* configure all channels */ ++ for (chan = 0; chan < rx_channels_count; chan++) { ++ qmode = priv->plat->rx_queues_cfg[chan].mode_to_use; ++ ++ stmmac_dma_rx_mode(priv, priv->ioaddr, rxmode, chan, ++ rxfifosz, qmode); ++ stmmac_set_dma_bfsize(priv, priv->ioaddr, priv->dma_buf_sz, ++ chan); ++ } ++ ++ for (chan = 0; chan < tx_channels_count; chan++) { ++ qmode = priv->plat->tx_queues_cfg[chan].mode_to_use; ++ ++ stmmac_dma_tx_mode(priv, priv->ioaddr, txmode, chan, ++ txfifosz, qmode); ++ } ++} ++ ++/** ++ * sunxi_uio_hw_setup - setup mac in a usable state. ++ * @dev : pointer to the device structure. ++ * @init_ptp: initialize PTP if set ++ * Description: ++ * this is the main function to setup the HW in a usable state because the ++ * dma engine is reset, the core registers are configured (e.g. AXI, ++ * Checksum features, timers). The DMA is ready to start receiving and ++ * transmitting. ++ * Return value: ++ * 0 on success and an appropriate (-)ve integer as defined in errno.h ++ * file on failure. ++ */ ++static int sunxi_uio_hw_setup(struct net_device *dev, bool init_ptp) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ int ret; ++ ++ /* DMA initialization and SW reset */ ++ ret = sunxi_uio_init_dma_engine(priv); ++ if (ret < 0) { ++ netdev_err(priv->dev, "%s: DMA engine initialization failed\n", ++ __func__); ++ return ret; ++ } ++ ++ /* Copy the MAC addr into the HW */ ++ stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0); ++ ++ /* PS and related bits will be programmed according to the speed */ ++ if (priv->hw->pcs) { ++ int speed = priv->plat->mac_port_sel_speed; ++ ++ if (speed == SPEED_10 || speed == SPEED_100 || ++ speed == SPEED_1000) { ++ priv->hw->ps = speed; ++ } else { ++ dev_warn(priv->device, "invalid port speed\n"); ++ priv->hw->ps = 0; ++ } ++ } ++ ++ /* Initialize the MAC Core */ ++ stmmac_core_init(priv, priv->hw, dev); ++ ++ /* Initialize MTL*/ ++ sunxi_uio_mtl_configuration(priv); ++ ++ /* Initialize Safety Features */ ++ sunxi_uio_safety_feat_configuration(priv); ++ ++ ret = stmmac_rx_ipc(priv, priv->hw); ++ if (!ret) { ++ netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); ++ priv->plat->rx_coe = STMMAC_RX_COE_NONE; ++ priv->hw->rx_csum = 0; ++ } ++ ++ /* Enable the MAC Rx/Tx */ ++ stmmac_mac_set(priv, priv->ioaddr, true); ++ ++ /* Set the HW DMA mode and the COE */ ++ sunxi_uio_dma_operation_mode(priv); ++ ++ if (priv->hw->pcs) ++ stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0); ++ ++ /* set TX and RX rings length */ ++ sunxi_uio_set_rings_length(priv); ++ ++ return 0; ++} ++ ++static int sunxi_uio_set_bfsize(int mtu, int bufsize) ++{ ++ int ret = bufsize; ++ ++ if (mtu >= BUF_SIZE_8KiB) ++ ret = BUF_SIZE_16KiB; ++ else if (mtu >= BUF_SIZE_4KiB) ++ ret = BUF_SIZE_8KiB; ++ else if (mtu >= BUF_SIZE_2KiB) ++ ret = BUF_SIZE_4KiB; ++ else if (mtu > DEFAULT_BUFSIZE) ++ ret = BUF_SIZE_2KiB; ++ else ++ ret = DEFAULT_BUFSIZE; ++ ++ return ret; ++} ++ ++/** ++ * sunxi_uio_init - open entry point of the driver ++ * @dev : pointer to the device structure. ++ * Description: ++ * This function is the open entry point of the driver. ++ * Return value: ++ * 0 on success and an appropriate (-)ve integer as defined in errno.h ++ * file on failure. ++ */ ++static int sunxi_uio_init(struct net_device *dev) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ int ret, bfsize = 0; ++ ++ if (priv->hw->pcs != STMMAC_PCS_TBI && ++ priv->hw->pcs != STMMAC_PCS_RTBI && ++ !priv->hw->xpcs) { ++ ret = sunxi_uio_init_phy(dev); ++ if (ret) { ++ netdev_err(priv->dev, ++ "%s: Cannot attach to PHY (error: %d)\n", ++ __func__, ret); ++ return ret; ++ } ++ } ++ ++ /* Extra statistics */ ++ priv->xstats.threshold = tc; ++ ++ bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu); ++ if (bfsize < 0) ++ bfsize = 0; ++ ++ if (bfsize < BUF_SIZE_16KiB) ++ bfsize = sunxi_uio_set_bfsize(dev->mtu, priv->dma_buf_sz); ++ ++ priv->dma_buf_sz = bfsize; ++ buf_sz = bfsize; ++ ++ priv->rx_copybreak = STMMAC_RX_COPYBREAK; ++ ++ if (!priv->dma_tx_size) ++ priv->dma_tx_size = DMA_DEFAULT_TX_SIZE; ++ if (!priv->dma_rx_size) ++ priv->dma_rx_size = DMA_DEFAULT_RX_SIZE; ++ ++ ret = sunxi_uio_alloc_dma_desc_resources(priv); ++ if (ret < 0) { ++ netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n", ++ __func__); ++ goto dma_desc_error; ++ } ++ ++ ret = sunxi_uio_hw_setup(dev, true); ++ if (ret < 0) { ++ netdev_err(priv->dev, "%s: Hw setup failed\n", __func__); ++ goto init_error; ++ } ++ ++ phylink_start(priv->phylink); ++ /* We may have called phylink_speed_down before */ ++ phylink_speed_up(priv->phylink); ++ ++ return 0; ++ ++init_error: ++ sunxi_uio_free_dma_desc_resources(priv); ++dma_desc_error: ++ phylink_disconnect_phy(priv->phylink); ++ return ret; ++} ++ ++/** ++ * sunxi_uio_exit - close entry point of the driver ++ * @dev : device pointer. ++ * Description: ++ * This is the stop entry point of the driver. ++ */ ++static int sunxi_uio_exit(struct net_device *dev) ++{ ++ struct stmmac_priv *priv = netdev_priv(dev); ++ ++ /* Stop and disconnect the PHY */ ++ if (dev->phydev) { ++ phy_stop(dev->phydev); ++ phy_disconnect(dev->phydev); ++ } ++ ++ /* Release and free the Rx/Tx resources */ ++ sunxi_uio_free_dma_desc_resources(priv); ++ ++ /* Disable the MAC Rx/Tx */ ++ stmmac_mac_set(priv, priv->ioaddr, false); ++ ++ netif_carrier_off(dev); ++ ++ return 0; ++} ++ ++/** ++ * sunxi_uio_probe() platform driver probe routine ++ * - register uio devices filled with memory maps retrieved ++ * from device tree ++ */ ++static int sunxi_uio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node, *mac_node; ++ struct sunxi_uio *chip; ++ struct net_device *netdev; ++ struct stmmac_priv *priv; ++ struct uio_info *uio; ++ struct resource *res; ++ int err = 0; ++ ++ chip = devm_kzalloc(dev, sizeof(struct sunxi_uio), ++ GFP_KERNEL); ++ if (!chip) ++ return -ENOMEM; ++ ++ uio = &chip->uio; ++ chip->dev = dev; ++ mac_node = of_parse_phandle(np, "sunxi,ethernet", 0); ++ if (!mac_node) ++ return -ENODEV; ++ ++ if (of_device_is_available(mac_node)) { ++ netdev = of_find_net_device_by_node(mac_node); ++ of_node_put(mac_node); ++ if (!netdev) ++ return -ENODEV; ++ } else { ++ of_node_put(mac_node); ++ return -EINVAL; ++ } ++ ++ chip->ndev = netdev; ++ rtnl_lock(); ++ dev_close(netdev); ++ rtnl_unlock(); ++ ++ rtnl_lock(); ++ err = sunxi_uio_init(netdev); ++ if (err) { ++ rtnl_unlock(); ++ dev_err(dev, "Failed to open stmmac resource: %d\n", err); ++ return err; ++ } ++ rtnl_unlock(); ++ ++ priv = netdev_priv(netdev); ++ snprintf(chip->name, sizeof(chip->name), "uio_%s", ++ netdev->name); ++ uio->name = chip->name; ++ uio->version = DRIVER_VERSION; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) ++ return -ENODEV; ++ ++ uio->mem[0].name = "eth_regs"; ++ uio->mem[0].addr = res->start & PAGE_MASK; ++ uio->mem[0].size = PAGE_ALIGN(resource_size(res)); ++ uio->mem[0].memtype = UIO_MEM_PHYS; ++ ++ uio->mem[1].name = "eth_rx_bd"; ++ uio->mem[1].addr = priv->rx_queue[0].dma_rx_phy; ++ uio->mem[1].size = priv->dma_rx_size * sizeof(struct dma_desc); ++ uio->mem[1].memtype = UIO_MEM_PHYS; ++ ++ uio->mem[2].name = "eth_tx_bd"; ++ uio->mem[2].addr = priv->tx_queue[0].dma_tx_phy; ++ uio->mem[2].size = priv->dma_tx_size * sizeof(struct dma_desc); ++ uio->mem[2].memtype = UIO_MEM_PHYS; ++ ++ uio->open = sunxi_uio_open; ++ uio->release = sunxi_uio_release; ++ /* Custom mmap function. */ ++ uio->mmap = sunxi_uio_mmap; ++ uio->priv = chip; ++ ++ err = uio_register_device(dev, uio); ++ if (err) { ++ dev_err(dev, "Failed to register uio device: %d\n", err); ++ return err; ++ } ++ ++ chip->map_num = 3; ++ ++ dev_info(dev, "Registered %s uio devices, %d register maps attached\n", ++ chip->name, chip->map_num); ++ ++ platform_set_drvdata(pdev, chip); ++ ++ return 0; ++} ++ ++/** ++ * sunxi_uio_remove() - UIO platform driver release ++ * routine - unregister uio devices ++ */ ++static int sunxi_uio_remove(struct platform_device *pdev) ++{ ++ struct sunxi_uio *chip = platform_get_drvdata(pdev); ++ struct net_device *netdev; ++ ++ if (!chip) ++ return -EINVAL; ++ ++ netdev = chip->ndev; ++ ++ uio_unregister_device(&chip->uio); ++ ++ if (netdev) { ++ rtnl_lock(); ++ sunxi_uio_exit(netdev); ++ rtnl_unlock(); ++ } ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (netdev) { ++ rtnl_lock(); ++ dev_open(netdev, NULL); ++ rtnl_unlock(); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id sunxi_uio_of_match[] = { ++ { .compatible = "allwinner,sunxi-uio", }, ++ { } ++}; ++ ++static struct platform_driver sunxi_uio_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRIVER_NAME, ++ .of_match_table = sunxi_uio_of_match, ++ }, ++ .probe = sunxi_uio_probe, ++ .remove = sunxi_uio_remove, ++}; ++module_platform_driver(sunxi_uio_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("xuminghui "); ++MODULE_VERSION(DRIVER_VERSION); +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig +--- linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig 2025-01-17 13:41:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig 2025-01-23 10:53:24.284097476 +0100 +@@ -34,4 +34,6 @@ + To compile this driver as a module, choose M here. The module + will be called sun4i-emac. + ++source "drivers/net/ethernet/allwinner/gmac-200/Kconfig" ++ + endif # NET_VENDOR_ALLWINNER +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/Makefile linux-6.12.10/drivers/net/ethernet/allwinner/Makefile +--- linux-6.12.10/drivers/net/ethernet/allwinner/Makefile 2025-01-17 13:41:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/Makefile 2025-01-23 10:53:31.710764338 +0100 +@@ -4,3 +4,4 @@ + # + + obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o ++obj-$(CONFIG_NET_VENDOR_ALLWINNER) += gmac-200/ diff --git a/patch/kernel/archive/sunxi-dev-6.14/1140-net-ethernet-allwinner-add-gmac-support.patch b/patch/kernel/archive/sunxi-dev-6.14/1140-net-ethernet-allwinner-add-gmac-support.patch new file mode 100644 index 000000000..27e806e8e --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/1140-net-ethernet-allwinner-add-gmac-support.patch @@ -0,0 +1,4470 @@ + +Code is backport from BSP kernel + +Signed-off-by: Piotr Oniszczuk + +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Kconfig linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Kconfig +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Kconfig 2025-01-23 10:14:54.944035323 +0100 +@@ -0,0 +1,37 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++menu "Gmac Drivers" ++ ++config SUNXI55I_GMAC ++ tristate "Allwinner A523 GMAC support" ++ depends on OF ++ select SUNXI55I_GMAC_MDIO ++ select CRC32 ++ help ++ Support for Allwinner A523 GMAC ethernet driver. ++ ++ To compile this driver as a module, choose M here. The module ++ will be called sunxi-gmac.ko. ++ ++config SUNXI55I_GMAC_MDIO ++ tristate "Allwinner A523 GMAC MDIO support" ++ select MDIO_BUS ++ select MDIO_DEVICE ++ select PHYLIB ++ select MII ++ help ++ This driver supports the A523 GMAC MDIO interface in the network ++ ++config SUNXI55I_GMAC_METADATA ++ bool "Allwinner A523 GMAC metadata support" ++ depends on SUNXI55I_GMAC ++ help ++ Support Allwinner A523 GMAC to transmit and receive metadata ++ ++# todo (not backported from bsp yet) ++#config SUNXI55I_EPHY ++# tristate "Drivers for A523 Allwinner EPHY" ++# depends on SUNXI55I_GMAC ++# help ++# Support Allwinner A523 EPHY ++ ++endmenu +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Makefile linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Makefile +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac/Makefile 2025-01-23 10:14:29.307367960 +0100 +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++ccflags-y += -I $(srctree)/drivers/net/ethernet/allwinner/gmac ++ ++obj-$(CONFIG_SUNXI55I_GMAC) += sunxi-gmac.o ++obj-$(CONFIG_SUNXI55I_GMAC_MDIO) += sunxi-mdio.o ++obj-$(CONFIG_SUNXI55I_EPHY) += sunxi-ephy.o +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-ephy.c linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-ephy.c +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-ephy.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-ephy.c 2024-12-11 14:45:52.380098296 +0100 +@@ -0,0 +1,315 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* ++* Allwinner ephy driver. ++* ++* Copyright(c) 2022-2027 Allwinnertech Co., Ltd. ++* ++* This file is licensed under the terms of the GNU General Public ++* License version 2. This program is licensed "as is" without any ++* warranty of any kind, whether express or implied. ++*/ ++ ++/* #define DEBUG */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++ ++#define AC300_EPHY "ac300-ephy" ++#define AC300_DEV "ac300" ++ ++#define EPHY_CALI_BASE 0 ++#define EPHY_CALI_BIT BIT(29) ++#define EPHY_BGS_MASK 0x0f000000 ++#define EPHY_BGS_OFFSET 24 ++/* ++ * Ephy diagram test ++ * This macro will cause all cpu stuck ++ * Use it carefully ++ */ ++/* #define EPHY_100M_ED_TEST */ ++ ++struct ephy_res { ++ struct phy_device *ac300; ++ spinlock_t lock; ++ atomic_t ephy_en; ++}; ++ ++static struct ephy_res ac300_ephy; ++ ++static int sunxi_ephy_read_sid(u32 *buf) ++{ ++ int ret; ++ ++ if (!buf) ++ return -EINVAL; ++ ++ //todo ret = sunxi_efuse_readn(EFUSE_FTCP_NAME, buf, 4); ++ //if (ret) ++ // return ret; ++ ++ return 0; ++} ++ ++void sunxi_ephy_config_new_init(struct phy_device *phydev) ++{ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to Page 1 */ ++ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to Page 2 */ ++ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0600); /* switch to Page 6 */ ++ phy_write(phydev, 0x14, 0x7809); /* PHYAFE TX optimization */ ++ phy_write(phydev, 0x13, 0xf000); /* PHYAFE RX optimization */ ++ phy_write(phydev, 0x10, 0x5523); ++ phy_write(phydev, 0x15, 0x3533); ++ ++ phy_write(phydev, 0x1f, 0x0800); /* switch to Page 8 */ ++ phy_write(phydev, 0x1d, 0x0844); /* disable auto offset */ ++ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0000); /* switch to Page 0 */ ++} ++ ++void sunxi_ephy_config_old_init(struct phy_device *phydev) ++{ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to Page 1 */ ++ phy_write(phydev, 0x12, 0x4824); /* Disable APS */ ++ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to Page 2 */ ++ phy_write(phydev, 0x18, 0x0000); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0600); /* switch to Page 6 */ ++ phy_write(phydev, 0x14, 0x780b); /* PHYAFE TX optimization */ ++ phy_write(phydev, 0x13, 0xf000); /* PHYAFE RX optimization */ ++ phy_write(phydev, 0x15, 0x1530); ++ phy_write(phydev, 0x1f, 0x0800); /* switch to Page 8 */ ++ phy_write(phydev, 0x18, 0x00bc); /* PHYAFE TRX optimization */ ++ ++ phy_write(phydev, 0x1f, 0x0000); /* switch to Page 0 */ ++} ++ ++void sunxi_ephy_config_cali(struct phy_device *phydev, u32 ephy_cali) ++{ ++ int value, bgs_adjust; ++ ++ /* Adjust BGS value of 0x06 reg */ ++ value = phy_read(phydev, 0x06); ++ value &= ~(0x0F << 12); ++ bgs_adjust = (ephy_cali & EPHY_BGS_MASK) >> EPHY_BGS_OFFSET; ++ value |= (0xF & (EPHY_CALI_BASE + bgs_adjust)) << 12; ++ phy_write(phydev, 0x06, value); ++} ++ ++void sunxi_ephy_disable_intelligent_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, 0x1f, 0x0100); /* switch to page 1 */ ++ value = phy_read(phydev, 0x17); /* read address 0 0x17 register */ ++ value &= ~(1 << 3); /* reg 0x17 bit 3, set 0 to disable IEEE */ ++ phy_write(phydev, 0x17, value); ++ phy_write(phydev, 0x1f, 0x0000); /* switch to page 0 */ ++} ++ ++void sunxi_ephy_disable_802_3az_ieee(struct phy_device *phydev) ++{ ++ unsigned int value; ++ ++ phy_write(phydev, 0xd, 0x7); ++ phy_write(phydev, 0xe, 0x3c); ++ phy_write(phydev, 0xd, 0x1 << 14 | 0x7); ++ value = phy_read(phydev, 0xe); ++ value &= ~(0x1 << 1); ++ phy_write(phydev, 0xd, 0x7); ++ phy_write(phydev, 0xe, 0x3c); ++ phy_write(phydev, 0xd, 0x1 << 14 | 0x7); ++ phy_write(phydev, 0xe, value); ++ ++ phy_write(phydev, 0x1f, 0x0200); /* switch to page 2 */ ++ phy_write(phydev, 0x18, 0x0000); ++} ++ ++#ifdef EPHY_100M_ED_TEST ++static void ephy_debug_test(void *info) ++{ ++ while (1) ++ ; ++} ++#endif ++ ++static int ephy_config_init(struct phy_device *phydev) ++{ ++ int value; ++ int ret; ++ u32 ephy_cali = 0; ++ ++ ret = sunxi_ephy_read_sid(&ephy_cali); ++ if (ret) { ++ pr_err("ephy cali efuse read fail, use default 0\n"); ++ } ++ ++ sunxi_ephy_config_cali(ac300_ephy.ac300, ephy_cali); ++ ++ /* ++ * EPHY_CALI_BIT: the flag of calibration value ++ * 0: Normal ++ * 1: Low level of calibration value ++ */ ++ if (ephy_cali & EPHY_CALI_BIT) { ++ pr_debug("Low level ephy, use new init\n"); ++ sunxi_ephy_config_new_init(phydev); ++ } else { ++ pr_debug("Normal ephy, use old init\n"); ++ sunxi_ephy_config_old_init(phydev); ++ } ++ ++ sunxi_ephy_disable_intelligent_ieee(phydev); /* Disable Intelligent IEEE */ ++ sunxi_ephy_disable_802_3az_ieee(phydev); /* Disable 802.3az IEEE */ ++ phy_write(phydev, 0x1f, 0x0000); /* Switch to Page 0 */ ++ ++#ifdef EPHY_100M_ED_TEST ++ phy_write(phydev, 0x1f, 0x0000); /* Switch to Page 0 */ ++ phy_write(phydev, 0x00, 0x2100); /* Force 100M Mode */ ++ phy_write(phydev, 0x1f, 0x0000); /* Switch to Page 0 */ ++ phy_write(phydev, 0x13, 0x0100); /* Force TX output@TXP/TXN */ ++ on_each_cpu(ephy_debug_test, NULL, 1); /* Stuck all cpu for ephy eye diagram test */ ++#endif ++ ++ value = phy_read(ac300_ephy.ac300, 0x06); ++ if (phydev->interface == PHY_INTERFACE_MODE_RMII) ++ value |= (1 << 11); ++ else ++ value &= (~(1 << 11)); ++ ++ phy_write(ac300_ephy.ac300, 0x06, value); ++ ++ return 0; ++} ++ ++static int ephy_probe(struct phy_device *phydev) ++{ ++ return 0; ++} ++ ++static int ephy_suspend(struct phy_device *phydev) ++{ ++ return genphy_suspend(phydev); ++} ++ ++static int ephy_resume(struct phy_device *phydev) ++{ ++ return genphy_resume(phydev); ++} ++ ++static void ac300_enable(struct phy_device *phydev) ++{ ++ /* release reset */ ++ phy_write(phydev, 0x00, 0x1f40); /* reset ephy */ ++ phy_write(phydev, 0x00, 0x1f43); /* de-reset ephy */ ++ ++ /* clk gating */ ++ phy_write(phydev, 0x00, 0x1fb7); ++ ++ /* io enable */ ++ phy_write(phydev, 0x05, 0xa81f); ++ ++ mdelay(10); ++ phy_write(phydev, 0x06, 0x0811); ++ ++ mdelay(10); ++ phy_write(phydev, 0x06, 0x0810); ++} ++ ++static void ac300_disable(struct phy_device *phydev) ++{ ++ phy_write(phydev, 0x00, 0x1f40); ++ phy_write(phydev, 0x05, 0xa800); ++ ++ phy_write(phydev, 0x06, 0x01); ++} ++ ++static int ac300_suspend(struct phy_device *phydev) ++{ ++ ac300_disable(phydev); ++ return 0; ++} ++ ++static int ac300_resume(struct phy_device *phydev) ++{ ++ return 0; ++} ++ ++static int ac300_probe(struct phy_device *phydev) ++{ ++ ac300_enable(phydev); ++ ++ return 0; ++} ++ ++static int ac300_init(struct phy_device *phydev) ++{ ++ /* save ac300 message */ ++ ac300_ephy.ac300 = phydev; ++ ++ /* ac300 enable */ ++ ac300_enable(phydev); ++ ++ /* FIXME: delay may be required after AC300 reset*/ ++ msleep(50); ++ ++ return 0; ++} ++ ++static struct phy_driver ac300_driver[] = { ++{ ++ .phy_id = 0xc0000000, ++ .name = AC300_DEV, ++ .phy_id_mask = 0xffffffff, ++ .config_init = ac300_init, ++ .suspend = ac300_suspend, ++ .resume = ac300_resume, ++ .probe = ac300_probe, ++}, ++{ .phy_id = 0x00441400, ++ .name = AC300_EPHY, ++ .phy_id_mask = 0x0ffffff0, ++ .config_init = ephy_config_init, ++ .config_aneg = &genphy_config_aneg, ++ .read_status = &genphy_read_status, ++ .suspend = ephy_suspend, ++ .resume = ephy_resume, ++ .probe = ephy_probe, ++ ++} }; ++ ++module_phy_driver(ac300_driver); ++ ++static struct mdio_device_id __maybe_unused ac300_tbl[] = { ++ { 0xc0000000, 0x0fffffff }, ++ { 0x00441400, 0x0ffffff0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, ac300_tbl); ++MODULE_DESCRIPTION("Allwinner phy drivers"); ++MODULE_AUTHOR("xuminghui "); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.1.1"); +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-gmac.c linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-gmac.c +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-gmac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-gmac.c 2025-01-23 10:25:09.037385167 +0100 +@@ -0,0 +1,3634 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++* Allwinner GMAC driver. ++* ++* Copyright(c) 2022-2027 Allwinnertech Co., Ltd. ++* ++* This file is licensed under the terms of the GNU General Public ++* License version 2. This program is licensed "as is" without any ++* warranty of any kind, whether express or implied. ++*/ ++ ++/* #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 ++#include ++#include ++#include ++//todo #include ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++#include ++#endif /* CONFIG_SUNXI55I_EPHY */ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++#include ++#endif /* CONFIG_SUNXI55I_GMAC_METADATA */ ++#include ++ ++/* All sunxi-gmac tracepoints are defined by the include below, which ++ * must be included exactly once across the whole kernel with ++ * CREATE_TRACE_POINTS defined ++ */ ++//#define CREATE_TRACE_POINTS ++//#include "sunxi-gmac-trace.h" ++ ++#define SUNXI_GMAC_MODULE_VERSION "2.4.3" ++ ++#define SUNXI_GMAC_DMA_DESC_RX 256 ++#define SUNXI_GMAC_DMA_DESC_TX 256 ++#define SUNXI_GMAC_BUDGET (sunxi_gmac_dma_desc_rx / 4) ++#define SUNXI_GMAC_TX_THRESH (sunxi_gmac_dma_desc_tx / 4) ++ ++#define SUNXI_GMAC_HASH_TABLE_SIZE 64 ++#define SUNXI_GMAC_MAX_BUF_SZ (SZ_2K - 1) ++/* Under the premise that each descriptor currently transmits 2k data, jumbo frame max is 8100 */ ++#define SUNXI_GMAC_MAX_MTU_SZ 8100 ++ ++/* SUNXI_GMAC_FRAME_FILTER register value */ ++#define SUNXI_GMAC_FRAME_FILTER_PR 0x80000000 /* Promiscuous Mode */ ++#define SUNXI_GMAC_FRAME_FILTER_HUC 0x00000100 /* Hash Unicast */ ++#define SUNXI_GMAC_FRAME_FILTER_HMC 0x00000200 /* Hash Multicast */ ++#define SUNXI_GMAC_FRAME_FILTER_DAIF 0x00000010 /* DA Inverse Filtering */ ++#define SUNXI_GMAC_FRAME_FILTER_PM 0x00010000 /* Pass all multicast */ ++#define SUNXI_GMAC_FRAME_FILTER_DBF 0x00020000 /* Disable Broadcast frames */ ++#define SUNXI_GMAC_FRAME_FILTER_SAIF 0x00000020 /* Inverse Filtering */ ++#define SUNXI_GMAC_FRAME_FILTER_SAF 0x00000040 /* Source Address Filter */ ++#define SUNXI_GMAC_FRAME_FILTER_RA 0x00000001 /* Receive all mode */ ++ ++/* Default tx descriptor */ ++#define SUNXI_GMAC_TX_SINGLE_DESC0 0x80000000 ++#define SUNXI_GMAC_TX_SINGLE_DESC1 0x63000000 ++ ++/* Default rx descriptor */ ++#define SUNXI_GMAC_RX_SINGLE_DESC0 0x80000000 ++#define SUNXI_GMAC_RX_SINGLE_DESC1 0x83000000 ++ ++/****************************************************************************** ++ * sunxi gmac reg offset ++ *****************************************************************************/ ++#define SUNXI_GMAC_BASIC_CTL0 0x00 ++#define SUNXI_GMAC_BASIC_CTL1 0x04 ++#define SUNXI_GMAC_INT_STA 0x08 ++#define SUNXI_GMAC_INT_EN 0x0C ++#define SUNXI_GMAC_TX_CTL0 0x10 ++#define SUNXI_GMAC_TX_CTL1 0x14 ++#define SUNXI_GMAC_TX_FLOW_CTL 0x1C ++#define SUNXI_GMAC_TX_DESC_LIST 0x20 ++#define SUNXI_GMAC_RX_CTL0 0x24 ++#define SUNXI_GMAC_RX_CTL1 0x28 ++#define SUNXI_GMAC_RX_DESC_LIST 0x34 ++#define SUNXI_GMAC_RX_FRM_FLT 0x38 ++#define SUNXI_GMAC_RX_HASH0 0x40 ++#define SUNXI_GMAC_RX_HASH1 0x44 ++#define SUNXI_GMAC_MDIO_ADDR 0x48 ++#define SUNXI_GMAC_MDIO_DATA 0x4C ++#define SUNXI_GMAC_ADDR_HI(reg) (0x50 + ((reg) << 3)) ++#define SUNXI_GMAC_ADDR_LO(reg) (0x54 + ((reg) << 3)) ++#define SUNXI_GMAC_TX_DMA_STA 0xB0 ++#define SUNXI_GMAC_TX_CUR_DESC 0xB4 ++#define SUNXI_GMAC_TX_CUR_BUF 0xB8 ++#define SUNXI_GMAC_RX_DMA_STA 0xC0 ++#define SUNXI_GMAC_RX_CUR_DESC 0xC4 ++#define SUNXI_GMAC_RX_CUR_BUF 0xC8 ++#define SUNXI_GMAC_RGMII_STA 0xD0 ++ ++#define SUNXI_GMAC_RGMII_IRQ 0x00000001 ++ ++#define SUNXI_GMAC_CTL0_LM 0x02 ++#define SUNXI_GMAC_CTL0_DM 0x01 ++#define SUNXI_GMAC_CTL0_SPEED 0x04 ++ ++#define SUNXI_GMAC_BURST_LEN 0x3F000000 ++#define SUNXI_GMAC_RX_TX_PRI 0x02 ++#define SUNXI_GMAC_SOFT_RST 0x01 ++ ++#define SUNXI_GMAC_TX_FLUSH 0x01 ++#define SUNXI_GMAC_TX_MD 0x02 ++#define SUNXI_GMAC_TX_NEXT_FRM 0x04 ++#define SUNXI_GMAC_TX_TH 0x0700 ++#define SUNXI_GMAC_TX_FLOW_CTL_BIT 0x01 ++ ++#define SUNXI_GMAC_RX_FLUSH 0x01 ++#define SUNXI_GMAC_RX_MD 0x02 ++#define SUNXI_GMAC_RX_RUNT_FRM 0x04 ++#define SUNXI_GMAC_RX_ERR_FRM 0x08 ++#define SUNXI_GMAC_RX_TH 0x0030 ++#define SUNXI_GMAC_RX_FLOW_CTL 0x1000000 ++ ++#define SUNXI_GMAC_TX_INT 0x00001 ++#define SUNXI_GMAC_TX_STOP_INT 0x00002 ++#define SUNXI_GMAC_TX_UA_INT 0x00004 ++#define SUNXI_GMAC_TX_TOUT_INT 0x00008 ++#define SUNXI_GMAC_TX_UNF_INT 0x00010 ++#define SUNXI_GMAC_TX_EARLY_INT 0x00020 ++#define SUNXI_GMAC_RX_INT 0x00100 ++#define SUNXI_GMAC_RX_UA_INT 0x00200 ++#define SUNXI_GMAC_RX_STOP_INT 0x00400 ++#define SUNXI_GMAC_RX_TOUT_INT 0x00800 ++#define SUNXI_GMAC_RX_OVF_INT 0x01000 ++#define SUNXI_GMAC_RX_EARLY_INT 0x02000 ++#define SUNXI_GMAC_LINK_STA_INT 0x10000 ++ ++#define SUNXI_GMAC_CHAIN_MODE_OFFSET 24 ++#define SUNXI_GMAC_LOOPBACK_OFFSET 2 ++#define SUNXI_GMAC_LOOPBACK 0x00000002 ++#define SUNXI_GMAC_CLEAR_SPEED 0x03 ++#define SUNXI_GMAC_1000M_SPEED ~0x0c ++#define SUNXI_GMAC_100M_SPEED 0x0c ++#define SUNXI_GMAC_10M_SPEED 0x08 ++#define SUNXI_GMAC_RX_FLOW_EN 0x10000 ++#define SUNXI_GMAC_TX_FLOW_EN 0x00001 ++#define SUNXI_GMAC_PAUSE_OFFSET 4 ++#define SUNXI_GMAC_INT_OFFSET 0x3fff ++#define SUNXI_GMAC_RX_DMA_EN 0x40000000 ++#define SUNXI_GMAC_TX_DMA_EN 0x40000000 ++#define SUNXI_GMAC_BURST_VALUE 8 ++#define SUNXI_GMAC_BURST_OFFSET 24 ++#define SUNXI_GMAC_SF_DMA_MODE 1 ++#define SUNXI_GMAC_TX_FRM_LEN_OFFSET 30 ++#define SUNXI_GMAC_CRC_OFFSET 27 ++#define SUNXI_GMAC_STRIP_FCS_OFFSET 28 ++#define SUNXI_GMAC_JUMBO_EN_OFFSET 29 ++#define SUNXI_GMAC_MDC_DIV_RATIO_M 0x03 ++#define SUNXI_GMAC_MDC_DIV_OFFSET 20 ++#define SUNXI_GMAC_TX_DMA_TH64 64 ++#define SUNXI_GMAC_TX_DMA_TH128 128 ++#define SUNXI_GMAC_TX_DMA_TH192 192 ++#define SUNXI_GMAC_TX_DMA_TH256 256 ++#define SUNXI_GMAC_TX_DMA_TH64_VAL 0x00000000 ++#define SUNXI_GMAC_TX_DMA_TH128_VAL 0X00000100 ++#define SUNXI_GMAC_TX_DMA_TH192_VAL 0x00000200 ++#define SUNXI_GMAC_TX_DMA_TH256_VAL 0x00000300 ++#define SUNXI_GMAC_RX_DMA_TH32 32 ++#define SUNXI_GMAC_RX_DMA_TH64 64 ++#define SUNXI_GMAC_RX_DMA_TH96 96 ++#define SUNXI_GMAC_RX_DMA_TH128 128 ++#define SUNXI_GMAC_RX_DMA_TH32_VAL 0x10 ++#define SUNXI_GMAC_RX_DMA_TH64_VAL 0x00 ++#define SUNXI_GMAC_RX_DMA_TH96_VAL 0x20 ++#define SUNXI_GMAC_RX_DMA_TH128_VAL 0x30 ++#define SUNXI_GMAC_TX_DMA_START 31 ++#define SUNXI_GMAC_RX_DMA_START 31 ++#define SUNXI_GMAC_DMA_DESC_BUFSIZE 11 ++#define SUNXI_GMAC_LOOPBACK_OFF 0 ++#define SUNXI_GMAC_MAC_LOOPBACK_ON 1 ++#define SUNXI_GMAC_PHY_LOOPBACK_ON 2 ++#define SUNXI_GMAC_OWN_DMA 0x80000000 ++#define SUNXI_GMAC_GPHY_TEST_OFFSET 13 ++#define SUNXI_GMAC_GPHY_TEST_MASK 0x07 ++#define SUNXI_GMAC_PHY_RGMII_MASK 0x00000004 ++#define SUNXI_GMAC_ETCS_RMII_MASK 0x00002003 ++#define SUNXI_GMAC_RGMII_INTCLK_MASK 0x00000002 ++#define SUNXI_GMAC_RMII_MASK 0x00002000 ++#define SUNXI_GMAC_TX_DELAY_MASK 0x07 ++#define SUNXI_GMAC_TX_DELAY_OFFSET 10 ++#define SUNXI_GMAC_RX_DELAY_MASK 0x1F ++#define SUNXI_GMAC_RX_DELAY_OFFSET 5 ++/* Flow Control defines */ ++#define SUNXI_GMAC_FLOW_OFF 0 ++#define SUNXI_GMAC_FLOW_RX 1 ++#define SUNXI_GMAC_FLOW_TX 2 ++#define SUNXI_GMAC_FLOW_AUTO (SUNXI_GMAC_FLOW_TX | SUNXI_GMAC_FLOW_RX) ++ ++/* Ring buffer caculate method */ ++#define circ_cnt(head, tail, size) (((head) > (tail)) ? \ ++ ((head) - (tail)) : \ ++ ((head) - (tail)) & ((size) - 1)) ++ ++#define circ_space(head, tail, size) circ_cnt((tail), ((head) + 1), (size)) ++ ++#define circ_inc(n, s) (((n) + 1) % (s)) ++ ++#define MAC_ADDR_LEN 18 ++#define SUNXI_GMAC_MAC_ADDRESS "80:3f:5d:09:8b:26" ++ ++/* loopback test */ ++#define LOOPBACK_PKT_CNT 64 ++#define LOOPBACK_PKT_LEN 1514 ++#define LOOPBACK_DEFAULT_TIME 5 ++enum self_test_index { ++ INTERNAL_LOOPBACK_TEST = 0, ++ EXTERNAL_LOOPBACK_TEST = 1, ++ SELF_TEST_MAX = 2, ++}; ++ ++static char sunxi_gmac_test_strings[][ETH_GSTRING_LEN] = { ++ "Internal lb test (mac loopback)", ++ "External lb test (phy loopback)", ++}; ++ ++//todo #ifdef MODULE ++//extern int get_custom_mac_address(int fmt, char *name, char *addr); ++//#endif ++ ++static char mac_str[MAC_ADDR_LEN] = SUNXI_GMAC_MAC_ADDRESS; ++module_param_string(mac_str, mac_str, MAC_ADDR_LEN, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mac_str, "MAC Address String.(xx:xx:xx:xx:xx:xx)"); ++ ++static int rxmode = 1; ++module_param(rxmode, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(rxmode, "DMA threshold control value"); ++ ++static int txmode = 1; ++module_param(txmode, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(txmode, "DMA threshold control value"); ++ ++static int pause = 0x400; ++module_param(pause, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(pause, "Flow Control Pause Time"); ++ ++#define TX_TIMEO 5000 ++static int watchdog = TX_TIMEO; ++module_param(watchdog, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds"); ++ ++static int sunxi_gmac_dma_desc_rx = SUNXI_GMAC_DMA_DESC_RX; ++module_param(sunxi_gmac_dma_desc_rx, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(sunxi_gmac_dma_desc_rx, "The number of receive's descriptors"); ++ ++static int sunxi_gmac_dma_desc_tx = SUNXI_GMAC_DMA_DESC_TX; ++module_param(sunxi_gmac_dma_desc_tx, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(sunxi_gmac_dma_desc_tx, "The number of transmit's descriptors"); ++ ++static int user_tx_delay = -1; ++module_param(user_tx_delay, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(user_tx_delay, "RGMII tx-delay parameter"); ++ ++static int user_rx_delay = -1; ++module_param(user_rx_delay, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(user_rx_delay, "RGMII rx-delay parameter"); ++ ++/* - 0: Flow Off ++ * - 1: Rx Flow ++ * - 2: Tx Flow ++ * - 3: Rx & Tx Flow ++ */ ++static int flow_ctrl; ++module_param(flow_ctrl, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(flow_ctrl, "Flow control [0: off, 1: rx, 2: tx, 3: both]"); ++ ++typedef union { ++ struct { ++ /* TDES0 */ ++ unsigned int deferred:1; /* Deferred bit (only half-duplex) */ ++ unsigned int under_err:1; /* Underflow error */ ++ unsigned int ex_deferral:1; /* Excessive deferral */ ++ unsigned int coll_cnt:4; /* Collision count */ ++ unsigned int vlan_tag:1; /* VLAN Frame */ ++ unsigned int ex_coll:1; /* Excessive collision */ ++ unsigned int late_coll:1; /* Late collision */ ++ unsigned int no_carr:1; /* No carrier */ ++ unsigned int loss_carr:1; /* Loss of collision */ ++ unsigned int ipdat_err:1; /* IP payload error */ ++ unsigned int frm_flu:1; /* Frame flushed */ ++ unsigned int jab_timeout:1; /* Jabber timeout */ ++ unsigned int err_sum:1; /* Error summary */ ++ unsigned int iphead_err:1; /* IP header error */ ++ unsigned int ttss:1; /* Transmit time stamp status */ ++ unsigned int reserved0:13; ++ unsigned int own:1; /* Own bit. CPU:0, DMA:1 */ ++ } tx; ++ ++ /* bits 5 7 0 | Frame status ++ * ---------------------------------------------------------- ++ * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects) ++ * 1 0 0 | IPv4/6 No CSUM errorS. ++ * 1 0 1 | IPv4/6 CSUM PAYLOAD error ++ * 1 1 0 | IPv4/6 CSUM IP HR error ++ * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS ++ * 0 0 1 | IPv4/6 unsupported IP PAYLOAD ++ * 0 1 1 | COE bypassed.. no IPv4/6 frame ++ * 0 1 0 | Reserved. ++ */ ++ struct { ++ /* RDES0 */ ++ unsigned int chsum_err:1; /* Payload checksum error */ ++ unsigned int crc_err:1; /* CRC error */ ++ unsigned int dribbling:1; /* Dribble bit error */ ++ unsigned int mii_err:1; /* Received error (bit3) */ ++ unsigned int recv_wt:1; /* Received watchdog timeout */ ++ unsigned int frm_type:1; /* Frame type */ ++ unsigned int late_coll:1; /* Late Collision */ ++ unsigned int ipch_err:1; /* IPv header checksum error (bit7) */ ++ unsigned int last_desc:1; /* Laset descriptor */ ++ unsigned int first_desc:1; /* First descriptor */ ++ unsigned int vlan_tag:1; /* VLAN Tag */ ++ unsigned int over_err:1; /* Overflow error (bit11) */ ++ unsigned int len_err:1; /* Length error */ ++ unsigned int sou_filter:1; /* Source address filter fail */ ++ unsigned int desc_err:1; /* Descriptor error */ ++ unsigned int err_sum:1; /* Error summary (bit15) */ ++ unsigned int frm_len:14; /* Frame length */ ++ unsigned int des_filter:1; /* Destination address filter fail */ ++ unsigned int own:1; /* Own bit. CPU:0, DMA:1 */ ++ #define RX_PKT_OK 0x7FFFB77C ++ #define RX_LEN 0x3FFF0000 ++ } rx; ++ ++ unsigned int all; ++} sunxi_gmac_desc0_u; ++ ++typedef union { ++ struct { ++ /* TDES1 */ ++ unsigned int buf1_size:11; /* Transmit buffer1 size */ ++ unsigned int buf2_size:11; /* Transmit buffer2 size */ ++ unsigned int ttse:1; /* Transmit time stamp enable */ ++ unsigned int dis_pad:1; /* Disable pad (bit23) */ ++ unsigned int adr_chain:1; /* Second address chained */ ++ unsigned int end_ring:1; /* Transmit end of ring */ ++ unsigned int crc_dis:1; /* Disable CRC */ ++ unsigned int cic:2; /* Checksum insertion control (bit27:28) */ ++ unsigned int first_sg:1; /* First Segment */ ++ unsigned int last_seg:1; /* Last Segment */ ++ unsigned int interrupt:1; /* Interrupt on completion */ ++ } tx; ++ ++ struct { ++ /* RDES1 */ ++ unsigned int buf1_size:11; /* Received buffer1 size */ ++ unsigned int buf2_size:11; /* Received buffer2 size */ ++ unsigned int reserved1:2; ++ unsigned int adr_chain:1; /* Second address chained */ ++ unsigned int end_ring:1; /* Received end of ring */ ++ unsigned int reserved2:5; ++ unsigned int dis_ic:1; /* Disable interrupt on completion */ ++ } rx; ++ ++ unsigned int all; ++} sunxi_gmac_desc1_u; ++ ++typedef struct sunxi_gmac_dma_desc { ++ sunxi_gmac_desc0_u desc0; ++ sunxi_gmac_desc1_u desc1; ++ /* The address of buffers */ ++ unsigned int desc2; ++ /* Next desc's address */ ++ unsigned int desc3; ++} __attribute__((packed)) sunxi_gmac_dma_desc_t; ++ ++enum rx_frame_status { /* IPC status */ ++ good_frame = 0, ++ discard_frame = 1, ++ csum_none = 2, ++ incomplete_frame = 3, /* use for jumbo frame */ ++ llc_snap = 4, ++}; ++ ++enum tx_dma_irq_status { ++ tx_hard_error = 1, ++ tx_hard_error_bump_tc = 2, ++ handle_tx_rx = 3, ++}; ++ ++struct sunxi_gmac_extra_stats { ++ /* Transmit errors */ ++ unsigned long tx_underflow; ++ unsigned long tx_carrier; ++ unsigned long tx_losscarrier; ++ unsigned long vlan_tag; ++ unsigned long tx_deferred; ++ unsigned long tx_vlan; ++ unsigned long tx_jabber; ++ unsigned long tx_frame_flushed; ++ unsigned long tx_payload_error; ++ unsigned long tx_ip_header_error; ++ ++ /* Receive errors */ ++ unsigned long rx_desc; ++ unsigned long sa_filter_fail; ++ unsigned long overflow_error; ++ unsigned long ipc_csum_error; ++ unsigned long rx_collision; ++ unsigned long rx_crc; ++ unsigned long dribbling_bit; ++ unsigned long rx_length; ++ unsigned long rx_mii; ++ unsigned long rx_multicast; ++ unsigned long rx_gmac_overflow; ++ unsigned long rx_watchdog; ++ unsigned long da_rx_filter_fail; ++ unsigned long sa_rx_filter_fail; ++ unsigned long rx_missed_cntr; ++ unsigned long rx_overflow_cntr; ++ unsigned long rx_vlan; ++ ++ /* Tx/Rx IRQ errors */ ++ unsigned long tx_undeflow_irq; ++ unsigned long tx_process_stopped_irq; ++ unsigned long tx_jabber_irq; ++ unsigned long rx_overflow_irq; ++ unsigned long rx_buf_unav_irq; ++ unsigned long rx_process_stopped_irq; ++ unsigned long rx_watchdog_irq; ++ unsigned long tx_early_irq; ++ unsigned long fatal_bus_error_irq; ++ ++ /* Extra info */ ++ unsigned long threshold; ++ unsigned long tx_pkt_n; ++ unsigned long rx_pkt_n; ++ unsigned long poll_n; ++ unsigned long sched_timer_n; ++ unsigned long normal_irq_n; ++}; ++ ++struct sunxi_gmac; ++ ++struct sunxi_gmac_ephy_ops { ++ int (*resource_get)(struct platform_device *pdev); ++ void (*resource_put)(struct platform_device *pdev); ++ int (*hardware_init)(struct sunxi_gmac *chip); ++ void (*hardware_deinit)(struct sunxi_gmac *chip); ++}; ++ ++struct sunxi_gmac { ++ struct sunxi_gmac_dma_desc *dma_tx; /* Tx dma descriptor */ ++ struct sk_buff **tx_skb; /* Tx socket buffer array */ ++ unsigned int tx_clean; /* Tx ring buffer data consumer */ ++ unsigned int tx_dirty; /* Tx ring buffer data provider */ ++ dma_addr_t dma_tx_phy; /* Tx dma physical address */ ++ ++ unsigned long buf_sz; /* Size of buffer specified by current descriptor */ ++ ++ struct sunxi_gmac_dma_desc *dma_rx; /* Rx dma descriptor */ ++ struct sk_buff **rx_skb; /* Rx socket buffer array */ ++ unsigned int rx_clean; /* Rx ring buffer data consumer */ ++ unsigned int rx_dirty; /* Rx ring buffer data provider */ ++ dma_addr_t dma_rx_phy; /* Rx dma physical address */ ++ ++ struct net_device *ndev; ++ struct device *dev; ++ struct napi_struct napi; ++ ++ struct sunxi_gmac_extra_stats xstats; /* Additional network statistics */ ++ ++ bool link; /* Phy link status */ ++ int speed; /* NIC network speed */ ++ int duplex; /* NIC network duplex capability */ ++ ++ /* suspend error workaround */ ++ unsigned int gmac_uevent_suppress; /* control kobject_uevent_env */ ++ ++#define SUNXI_EXTERNAL_PHY 1 ++#define SUNXI_INTERNAL_PHY 0 ++ u32 phy_type; /* 1: External phy, 0: Internal phy */ ++ ++#define SUNXI_PHY_USE_CLK25M 0 /* External phy use phy25m clk provided by Soc */ ++#define SUNXI_PHY_USE_EXT_OSC 1 /* External phy use extern osc 25m */ ++ u32 phy_clk_type; ++ ++ phy_interface_t phy_interface; ++ void __iomem *base; ++ void __iomem *syscfg_base; ++ struct clk *gmac_clk; ++ struct clk *phy25m_clk; ++ struct reset_control *reset; ++ struct pinctrl *pinctrl; ++ struct regulator *gmac_supply; ++ ++ /* definition spinlock */ ++ spinlock_t universal_lock; /* universal spinlock */ ++ spinlock_t tx_lock; /* tx tramsmit spinlock */ ++ ++ /* adjust transmit clock delay, value: 0~7 */ ++ /* adjust receive clock delay, value: 0~31 */ ++ u32 tx_delay; ++ u32 rx_delay; ++ ++ struct device_node *phy_node; ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ struct device_node *ac300_np; ++ struct phy_device *ac300_dev; ++ struct pwm_device *ac300_pwm; ++ u32 pwm_channel; ++#define PWM_DUTY_NS 205 ++#define PWM_PERIOD_NS 410 ++ struct sunxi_gmac_ephy_ops *ephy_ops; ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++ /* loopback test */ ++ int loopback_pkt_len; ++ int loopback_test_rx_idx; ++ bool is_loopback_test; ++ u8 *loopback_test_rx_buf; ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++ u8 *metadata_buff; ++ struct miscdevice mdev; ++ struct completion metadata_done; ++ u32 metadata_len; ++#endif ++ ++ struct sk_buff *skb; /* for jumbo frame */ ++ ++ u32 irq_affinity; ++}; ++ ++/** ++ * sunxi_gmac_desc_init_chain - GMAC dma descriptor chain table initialization ++ * ++ * @desc: Dma descriptor ++ * @addr: Dma descriptor physical address ++ * @size: Dma descriptor numsa ++ * ++ * Called when the NIC is up. We init Tx/Rx dma descriptor table. ++ */ ++static void sunxi_gmac_desc_init_chain(struct sunxi_gmac_dma_desc *desc, unsigned long addr, unsigned int size) ++{ ++ /* In chained mode the desc3 points to the next element in the ring. ++ * The latest element has to point to the head. ++ */ ++ int i; ++ struct sunxi_gmac_dma_desc *p = desc; ++ unsigned long dma_phy = addr; ++ ++ for (i = 0; i < (size - 1); i++) { ++ dma_phy += sizeof(*p); ++ p->desc3 = (unsigned int)dma_phy; ++ /* Chain mode */ ++ p->desc1.all |= (1 << SUNXI_GMAC_CHAIN_MODE_OFFSET); ++ p++; ++ } ++ p->desc1.all |= (1 << SUNXI_GMAC_CHAIN_MODE_OFFSET); ++ p->desc3 = (unsigned int)addr; ++} ++ ++/** ++ * sunxi_gmac_set_link_mode - GMAC speed/duplex set func ++ * ++ * @iobase: Gmac membase ++ * @duplex: Duplex capability:half/full ++ * @speed: Speed:10M/100M/1000M ++ * ++ * Updates phy status and takes action for network queue if required ++ * based upon link status. ++ */ ++static void sunxi_gmac_set_link_mode(void *iobase, int duplex, int speed) ++{ ++ unsigned int ctrl = readl(iobase + SUNXI_GMAC_BASIC_CTL0); ++ ++ if (!duplex) ++ ctrl &= ~SUNXI_GMAC_CTL0_DM; ++ else ++ ctrl |= SUNXI_GMAC_CTL0_DM; ++ ++ /* clear ctrl speed */ ++ ctrl &= SUNXI_GMAC_CLEAR_SPEED; ++ ++ switch (speed) { ++ case 1000: ++ ctrl &= SUNXI_GMAC_1000M_SPEED; ++ break; ++ case 100: ++ ctrl |= SUNXI_GMAC_100M_SPEED; ++ break; ++ case 10: ++ ctrl |= SUNXI_GMAC_10M_SPEED; ++ break; ++ default: ++ break; ++ } ++ ++ writel(ctrl, iobase + SUNXI_GMAC_BASIC_CTL0); ++} ++ ++/** ++ * sunxi_gmac_loop - GMAC loopback mode set func ++ * ++ * @iobase: Gmac membase ++ * @loopback_enable: Loopback status ++ */ ++static void sunxi_gmac_loopback(void *iobase, int loopback_enable) ++{ ++ int reg; ++ ++ reg = readl(iobase + SUNXI_GMAC_BASIC_CTL0); ++ if (loopback_enable) ++ reg |= SUNXI_GMAC_LOOPBACK_OFFSET; ++ else ++ reg &= ~SUNXI_GMAC_LOOPBACK_OFFSET; ++ writel(reg, iobase + SUNXI_GMAC_BASIC_CTL0); ++} ++ ++static void sunxi_gmac_crc(void *iobase, bool enable) ++{ ++ int reg; ++ ++ reg = readl(iobase + SUNXI_GMAC_RX_CTL0); ++ if (enable) ++ reg |= (1 << SUNXI_GMAC_CRC_OFFSET); ++ else ++ reg &= ~(1 << SUNXI_GMAC_CRC_OFFSET); ++ ++ writel(reg, iobase + SUNXI_GMAC_RX_CTL0); ++} ++ ++/** ++ * sunxi_gmac_flow_ctrl - GMAC flow ctrl set func ++ * ++ * @iobase: Gmac membase ++ * @duolex: Duplex capability ++ * @fc: Flow control option ++ * @pause: Flow control pause time ++ */ ++static void sunxi_gmac_flow_ctrl(void *iobase, int duplex, int fc, int pause) ++{ ++ unsigned int flow; ++ ++ if (fc & SUNXI_GMAC_FLOW_RX) { ++ flow = readl(iobase + SUNXI_GMAC_RX_CTL0); ++ flow |= SUNXI_GMAC_RX_FLOW_EN; ++ writel(flow, iobase + SUNXI_GMAC_RX_CTL0); ++ } ++ ++ if (fc & SUNXI_GMAC_FLOW_TX) { ++ flow = readl(iobase + SUNXI_GMAC_TX_FLOW_CTL); ++ flow |= SUNXI_GMAC_TX_FLOW_EN; ++ writel(flow, iobase + SUNXI_GMAC_TX_FLOW_CTL); ++ } ++ ++ if (duplex) { ++ flow = readl(iobase + SUNXI_GMAC_TX_FLOW_CTL); ++ flow |= (pause << SUNXI_GMAC_PAUSE_OFFSET); ++ writel(flow, iobase + SUNXI_GMAC_TX_FLOW_CTL); ++ } ++} ++ ++/** ++ * sunxi_gmac_int_status - GMAC get int status func ++ * ++ * @iobase: Gmac membase ++ * @x: Extra statistics ++ */ ++static int sunxi_gmac_int_status(void *iobase, struct sunxi_gmac_extra_stats *x) ++{ ++ int ret; ++ /* read the status register (CSR5) */ ++ unsigned int intr_status; ++ ++ intr_status = readl(iobase + SUNXI_GMAC_RGMII_STA); ++ if (intr_status & SUNXI_GMAC_RGMII_IRQ) ++ readl(iobase + SUNXI_GMAC_RGMII_STA); ++ ++ intr_status = readl(iobase + SUNXI_GMAC_INT_STA); ++ ++ /* ABNORMAL interrupts */ ++ if (intr_status & SUNXI_GMAC_TX_UNF_INT) { ++ ret = tx_hard_error_bump_tc; ++ x->tx_undeflow_irq++; ++ } ++ if (intr_status & SUNXI_GMAC_TX_TOUT_INT) ++ x->tx_jabber_irq++; ++ ++ if (intr_status & SUNXI_GMAC_RX_OVF_INT) ++ x->rx_overflow_irq++; ++ ++ if (intr_status & SUNXI_GMAC_RX_UA_INT) ++ x->rx_buf_unav_irq++; ++ ++ if (intr_status & SUNXI_GMAC_RX_STOP_INT) ++ x->rx_process_stopped_irq++; ++ ++ if (intr_status & SUNXI_GMAC_RX_TOUT_INT) ++ x->rx_watchdog_irq++; ++ ++ if (intr_status & SUNXI_GMAC_TX_EARLY_INT) ++ x->tx_early_irq++; ++ ++ if (intr_status & SUNXI_GMAC_TX_STOP_INT) { ++ x->tx_process_stopped_irq++; ++ ret = tx_hard_error; ++ } ++ ++ /* TX/RX NORMAL interrupts */ ++ if (intr_status & (SUNXI_GMAC_TX_INT | SUNXI_GMAC_RX_INT | SUNXI_GMAC_RX_EARLY_INT | SUNXI_GMAC_TX_UA_INT)) { ++ x->normal_irq_n++; ++ if (intr_status & (SUNXI_GMAC_TX_INT | SUNXI_GMAC_RX_INT)) ++ ret = handle_tx_rx; ++ } ++ /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */ ++ writel(intr_status & SUNXI_GMAC_INT_OFFSET, iobase + SUNXI_GMAC_INT_STA); ++ ++ return ret; ++} ++ ++/** ++ * sunxi_gmac_enable_rx - enable gmac rx dma ++ * ++ * @iobase: Gmac membase ++ * @rxbase: Base address of Rx descriptor ++ */ ++static void sunxi_gmac_enable_rx(void *iobase, unsigned long rxbase) ++{ ++ unsigned int value; ++ ++ /* Write the base address of Rx descriptor lists into registers */ ++ writel(rxbase, iobase + SUNXI_GMAC_RX_DESC_LIST); ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL1); ++ value |= SUNXI_GMAC_RX_DMA_EN; ++ writel(value, iobase + SUNXI_GMAC_RX_CTL1); ++} ++ ++static int sunxi_gmac_read_rx_flowctl(void *iobase) ++{ ++ unsigned int value; ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL1); ++ ++ return value & SUNXI_GMAC_RX_FLOW_CTL; ++} ++ ++static int sunxi_gmac_read_tx_flowctl(void *iobase) ++{ ++ unsigned int value; ++ ++ value = readl(iobase + SUNXI_GMAC_TX_FLOW_CTL); ++ ++ return value & SUNXI_GMAC_TX_FLOW_CTL_BIT; ++} ++ ++static void sunxi_gmac_write_rx_flowctl(void *iobase, bool flag) ++{ ++ unsigned int value; ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL1); ++ ++ if (flag) ++ value |= SUNXI_GMAC_RX_FLOW_CTL; ++ else ++ value &= ~SUNXI_GMAC_RX_FLOW_CTL; ++ ++ writel(value, iobase + SUNXI_GMAC_RX_CTL1); ++} ++ ++static void sunxi_gmac_write_tx_flowctl(void *iobase, bool flag) ++{ ++ unsigned int value; ++ ++ value = readl(iobase + SUNXI_GMAC_TX_FLOW_CTL); ++ ++ if (flag) ++ value |= SUNXI_GMAC_TX_FLOW_CTL_BIT; ++ else ++ value &= ~SUNXI_GMAC_TX_FLOW_CTL_BIT; ++ ++ writel(value, iobase + SUNXI_GMAC_TX_FLOW_CTL); ++} ++ ++/** ++ * sunxi_gmac_enable_tx - enable gmac tx dma ++ * ++ * @iobase: Gmac membase ++ * @rxbase: Base address of Tx descriptor ++ */ ++static void sunxi_gmac_enable_tx(void *iobase, unsigned long txbase) ++{ ++ unsigned int value; ++ ++ /* Write the base address of Tx descriptor lists into registers */ ++ writel(txbase, iobase + SUNXI_GMAC_TX_DESC_LIST); ++ ++ value = readl(iobase + SUNXI_GMAC_TX_CTL1); ++ value |= SUNXI_GMAC_TX_DMA_EN; ++ writel(value, iobase + SUNXI_GMAC_TX_CTL1); ++} ++ ++/** ++ * sunxi_gmac_disable_tx - disable gmac tx dma ++ * ++ * @iobase: Gmac membase ++ * @rxbase: Base address of Tx descriptor ++ */ ++static void sunxi_gmac_disable_tx(void *iobase) ++{ ++ unsigned int value = readl(iobase + SUNXI_GMAC_TX_CTL1); ++ ++ value &= ~SUNXI_GMAC_TX_DMA_EN; ++ writel(value, iobase + SUNXI_GMAC_TX_CTL1); ++} ++ ++static int sunxi_gmac_dma_init(void *iobase) ++{ ++ unsigned int value; ++ ++ /* Burst should be 8 */ ++ value = (SUNXI_GMAC_BURST_VALUE << SUNXI_GMAC_BURST_OFFSET); ++ ++#ifdef CONFIG_SUNXI_GMAC_DA ++ value |= SUNXI_GMAC_RX_TX_PRI; /* Rx has priority over tx */ ++#endif ++ writel(value, iobase + SUNXI_GMAC_BASIC_CTL1); ++ ++ /* Mask interrupts by writing to CSR7 */ ++ writel(SUNXI_GMAC_RX_INT | SUNXI_GMAC_TX_UNF_INT, iobase + SUNXI_GMAC_INT_EN); ++ ++ return 0; ++} ++ ++/** ++ * sunxi_gmac_init - init gmac config ++ * ++ * @iobase: Gmac membase ++ * @txmode: tx flow control mode ++ * @rxmode: rx flow control mode ++ */ ++static int sunxi_gmac_init(void *iobase, int txmode, int rxmode) ++{ ++ unsigned int value; ++ ++ sunxi_gmac_dma_init(iobase); ++ ++ /* Initialize the core component */ ++ value = readl(iobase + SUNXI_GMAC_TX_CTL0); ++ value |= (1 << SUNXI_GMAC_TX_FRM_LEN_OFFSET); ++ writel(value, iobase + SUNXI_GMAC_TX_CTL0); ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL0); ++ value |= (1 << SUNXI_GMAC_CRC_OFFSET); /* Enable CRC & IPv4 Header Checksum */ ++ value |= (1 << SUNXI_GMAC_STRIP_FCS_OFFSET); /* Automatic Pad/CRC Stripping */ ++ value |= (1 << SUNXI_GMAC_JUMBO_EN_OFFSET); /* Jumbo Frame Enable */ ++ writel(value, iobase + SUNXI_GMAC_RX_CTL0); ++ ++ writel((SUNXI_GMAC_MDC_DIV_RATIO_M << SUNXI_GMAC_MDC_DIV_OFFSET), ++ iobase + SUNXI_GMAC_MDIO_ADDR); /* MDC_DIV_RATIO */ ++ ++ /* Set the Rx&Tx mode */ ++ value = readl(iobase + SUNXI_GMAC_TX_CTL1); ++ if (txmode == SUNXI_GMAC_SF_DMA_MODE) { ++ /* Transmit COE type 2 cannot be done in cut-through mode. */ ++ value |= SUNXI_GMAC_TX_MD; ++ /* Operating on second frame increase the performance ++ * especially when transmit store-and-forward is used. ++ */ ++ value |= SUNXI_GMAC_TX_NEXT_FRM; ++ } else { ++ value &= ~SUNXI_GMAC_TX_MD; ++ value &= ~SUNXI_GMAC_TX_TH; ++ /* Set the transmit threshold */ ++ if (txmode <= SUNXI_GMAC_TX_DMA_TH64) ++ value |= SUNXI_GMAC_TX_DMA_TH64_VAL; ++ else if (txmode <= SUNXI_GMAC_TX_DMA_TH128) ++ value |= SUNXI_GMAC_TX_DMA_TH128_VAL; ++ else if (txmode <= SUNXI_GMAC_TX_DMA_TH192) ++ value |= SUNXI_GMAC_TX_DMA_TH192_VAL; ++ else ++ value |= SUNXI_GMAC_TX_DMA_TH256_VAL; ++ } ++ writel(value, iobase + SUNXI_GMAC_TX_CTL1); ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL1); ++ if (rxmode == SUNXI_GMAC_SF_DMA_MODE) { ++ value |= SUNXI_GMAC_RX_MD; ++ } else { ++ value &= ~SUNXI_GMAC_RX_MD; ++ value &= ~SUNXI_GMAC_RX_TH; ++ if (rxmode <= SUNXI_GMAC_RX_DMA_TH32) ++ value |= SUNXI_GMAC_RX_DMA_TH32_VAL; ++ else if (rxmode <= SUNXI_GMAC_RX_DMA_TH64) ++ value |= SUNXI_GMAC_RX_DMA_TH64_VAL; ++ else if (rxmode <= SUNXI_GMAC_RX_DMA_TH96) ++ value |= SUNXI_GMAC_RX_DMA_TH96_VAL; ++ else ++ value |= SUNXI_GMAC_RX_DMA_TH128_VAL; ++ } ++ ++ /* Forward frames with error and undersized good frame. */ ++ value |= (SUNXI_GMAC_RX_ERR_FRM | SUNXI_GMAC_RX_RUNT_FRM); ++ ++ writel(value, iobase + SUNXI_GMAC_RX_CTL1); ++ ++ return 0; ++} ++ ++static void sunxi_gmac_hash_filter(void *iobase, unsigned long low, unsigned long high) ++{ ++ writel(high, iobase + SUNXI_GMAC_RX_HASH0); ++ writel(low, iobase + SUNXI_GMAC_RX_HASH1); ++} ++ ++/* write macaddr into MAC register */ ++static void sunxi_gmac_set_mac_addr_to_reg(void *iobase, unsigned char *addr, int index) ++{ ++ unsigned long data; ++ ++ /* one char is 8bit, so splice mac address in steps of 8 */ ++ data = (addr[5] << 8) | addr[4]; ++ writel(data, iobase + SUNXI_GMAC_ADDR_HI(index)); ++ data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; ++ writel(data, iobase + SUNXI_GMAC_ADDR_LO(index)); ++} ++ ++static void sunxi_gmac_dma_start(void *iobase) ++{ ++ unsigned long value; ++ ++ value = readl(iobase + SUNXI_GMAC_TX_CTL0); ++ value |= (1 << SUNXI_GMAC_TX_DMA_START); ++ writel(value, iobase + SUNXI_GMAC_TX_CTL0); ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL0); ++ value |= (1 << SUNXI_GMAC_RX_DMA_START); ++ writel(value, iobase + SUNXI_GMAC_RX_CTL0); ++} ++ ++static void sunxi_gmac_dma_stop(void *iobase) ++{ ++ unsigned long value; ++ ++ value = readl(iobase + SUNXI_GMAC_TX_CTL0); ++ value &= ~(1 << SUNXI_GMAC_TX_DMA_START); ++ writel(value, iobase + SUNXI_GMAC_TX_CTL0); ++ ++ value = readl(iobase + SUNXI_GMAC_RX_CTL0); ++ value &= ~(1 << SUNXI_GMAC_RX_DMA_START); ++ writel(value, iobase + SUNXI_GMAC_RX_CTL0); ++} ++ ++static void sunxi_gmac_tx_poll(void *iobase) ++{ ++ unsigned int value; ++ ++ value = readl(iobase + SUNXI_GMAC_TX_CTL1); ++ writel(value | (1 << SUNXI_GMAC_TX_DMA_START), iobase + SUNXI_GMAC_TX_CTL1); ++} ++ ++static void sunxi_gmac_irq_enable(void *iobase) ++{ ++ writel(SUNXI_GMAC_RX_INT | SUNXI_GMAC_TX_UNF_INT, iobase + SUNXI_GMAC_INT_EN); ++} ++ ++static void sunxi_gmac_irq_disable(void *iobase) ++{ ++ writel(0, iobase + SUNXI_GMAC_INT_EN); ++} ++ ++static void sunxi_gmac_desc_buf_set(struct sunxi_gmac_dma_desc *desc, unsigned long paddr, int size) ++{ ++ desc->desc1.all &= (~((1 << SUNXI_GMAC_DMA_DESC_BUFSIZE) - 1)); ++ desc->desc1.all |= (size & ((1 << SUNXI_GMAC_DMA_DESC_BUFSIZE) - 1)); ++ desc->desc2 = paddr; ++} ++ ++static void sunxi_gmac_desc_set_own(struct sunxi_gmac_dma_desc *desc) ++{ ++ desc->desc0.all |= SUNXI_GMAC_OWN_DMA; ++} ++ ++static void sunxi_gmac_desc_tx_close(struct sunxi_gmac_dma_desc *first, struct sunxi_gmac_dma_desc *end, int csum_insert) ++{ ++ struct sunxi_gmac_dma_desc *desc = first; ++ ++ first->desc1.tx.first_sg = 1; ++ end->desc1.tx.last_seg = 1; ++ end->desc1.tx.interrupt = 1; ++ ++ if (csum_insert) ++ do { ++ desc->desc1.tx.cic = 3; ++ desc++; ++ } while (desc <= end); ++} ++ ++static void sunxi_gmac_desc_init(struct sunxi_gmac_dma_desc *desc) ++{ ++ desc->desc1.all = 0; ++ desc->desc2 = 0; ++ desc->desc1.all |= (1 << SUNXI_GMAC_CHAIN_MODE_OFFSET); ++} ++ ++static int sunxi_gmac_desc_get_tx_status(struct sunxi_gmac_dma_desc *desc, struct sunxi_gmac_extra_stats *x) ++{ ++ int ret = 0; ++ ++ if (desc->desc0.tx.under_err) { ++ x->tx_underflow++; ++ ret = -EIO; ++ } ++ ++ if (desc->desc0.tx.no_carr) { ++ x->tx_carrier++; ++ ret = -EIO; ++ } ++ ++ if (desc->desc0.tx.loss_carr) { ++ x->tx_losscarrier++; ++ ret = -EIO; ++ } ++ ++ if (desc->desc0.tx.deferred) { ++ x->tx_deferred++; ++ ret = -EIO; ++ } ++ ++ return ret; ++} ++ ++static int sunxi_gmac_desc_buf_get_len(struct sunxi_gmac_dma_desc *desc) ++{ ++ return (desc->desc1.all & ((1 << SUNXI_GMAC_DMA_DESC_BUFSIZE) - 1)); ++} ++ ++static int sunxi_gmac_desc_buf_get_addr(struct sunxi_gmac_dma_desc *desc) ++{ ++ return desc->desc2; ++} ++ ++static int sunxi_gmac_desc_rx_frame_len(struct sunxi_gmac_dma_desc *desc) ++{ ++ return desc->desc0.rx.frm_len; ++} ++ ++static int sunxi_gmac_desc_llc_snap(struct sunxi_gmac_dma_desc *desc) ++{ ++ /* Splice flags as follow: ++ * bits 5 7 0 | Frame status ++ * ---------------------------------------------------------- ++ * 0 0 0 | IEEE 802.3 Type frame (length < 1536 octects) ++ * 1 0 0 | IPv4/6 No CSUM errorS. ++ * 1 0 1 | IPv4/6 CSUM PAYLOAD error ++ * 1 1 0 | IPv4/6 CSUM IP HR error ++ * 1 1 1 | IPv4/6 IP PAYLOAD AND HEADER errorS ++ * 0 0 1 | IPv4/6 unsupported IP PAYLOAD ++ * 0 1 1 | COE bypassed.. no IPv4/6 frame ++ * 0 1 0 | Reserved. ++ */ ++ return ((desc->desc0.rx.frm_type << 2 | ++ desc->desc0.rx.ipch_err << 1 | ++ desc->desc0.rx.chsum_err) & 0x7); ++} ++ ++static int sunxi_gmac_desc_get_rx_status(struct sunxi_gmac_dma_desc *desc, struct sunxi_gmac_extra_stats *x) ++{ ++ int ret = good_frame; ++ ++ if (desc->desc0.rx.last_desc == 0) ++ return incomplete_frame; ++ ++ if (desc->desc0.rx.err_sum) { ++ if (desc->desc0.rx.desc_err) ++ x->rx_desc++; ++ ++ if (desc->desc0.rx.sou_filter) ++ x->sa_filter_fail++; ++ ++ if (desc->desc0.rx.over_err) ++ x->overflow_error++; ++ ++ if (desc->desc0.rx.ipch_err) ++ x->ipc_csum_error++; ++ ++ if (desc->desc0.rx.late_coll) ++ x->rx_collision++; ++ ++ if (desc->desc0.rx.crc_err) ++ x->rx_crc++; ++ ++ ret = discard_frame; ++ } ++ ++ if (desc->desc0.rx.len_err) ++ ret = discard_frame; ++ ++ if (desc->desc0.rx.mii_err) ++ ret = discard_frame; ++ ++ if (ret == good_frame) { ++ if (sunxi_gmac_desc_llc_snap(desc) == 0) ++ ret = llc_snap; ++ } ++ ++ return ret; ++} ++ ++static int sunxi_gmac_desc_get_own(struct sunxi_gmac_dma_desc *desc) ++{ ++ return desc->desc0.all & SUNXI_GMAC_OWN_DMA; ++} ++ ++static int sunxi_gmac_desc_get_tx_last_seg(struct sunxi_gmac_dma_desc *desc) ++{ ++ return desc->desc1.tx.last_seg; ++} ++ ++static int sunxi_gmac_reset(void *iobase, int n) ++{ ++ unsigned int value; ++ ++ /* gmac software reset */ ++ value = readl(iobase + SUNXI_GMAC_BASIC_CTL1); ++ value |= SUNXI_GMAC_SOFT_RST; ++ writel(value, iobase + SUNXI_GMAC_BASIC_CTL1); ++ ++ udelay(n); ++ ++ return !!(readl(iobase + SUNXI_GMAC_BASIC_CTL1) & SUNXI_GMAC_SOFT_RST); ++} ++ ++static int sunxi_gmac_stop(struct net_device *ndev); ++ ++static void sunxi_gmac_dump_dma_desc(struct sunxi_gmac_dma_desc *desc, int size) ++{ ++#ifdef DEBUG ++ int i; ++ ++ for (i = 0; i < size; i++) { ++ u32 *x = (u32 *)(desc + i); ++ ++ pr_info("\t%d [0x%08lx]: %08x %08x %08x %08x\n", ++ i, (unsigned long)(&desc[i]), ++ x[0], x[1], x[2], x[3]); ++ } ++ pr_info("\n"); ++#endif ++} ++ ++static ssize_t sunxi_gmac_extra_tx_stats_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ return sprintf(buf, "tx_underflow: %lu\ntx_carrier: %lu\n" ++ "tx_losscarrier: %lu\nvlan_tag: %lu\n" ++ "tx_deferred: %lu\ntx_vlan: %lu\n" ++ "tx_jabber: %lu\ntx_frame_flushed: %lu\n" ++ "tx_payload_error: %lu\ntx_ip_header_error: %lu\n\n", ++ chip->xstats.tx_underflow, chip->xstats.tx_carrier, ++ chip->xstats.tx_losscarrier, chip->xstats.vlan_tag, ++ chip->xstats.tx_deferred, chip->xstats.tx_vlan, ++ chip->xstats.tx_jabber, chip->xstats.tx_frame_flushed, ++ chip->xstats.tx_payload_error, chip->xstats.tx_ip_header_error); ++} ++/* eg: cat extra_tx_stats */ ++static DEVICE_ATTR(extra_tx_stats, 0444, sunxi_gmac_extra_tx_stats_show, NULL); ++ ++static ssize_t sunxi_gmac_extra_rx_stats_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ return sprintf(buf, "rx_desc: %lu\nsa_filter_fail: %lu\n" ++ "overflow_error: %lu\nipc_csum_error: %lu\n" ++ "rx_collision: %lu\nrx_crc: %lu\n" ++ "dribbling_bit: %lu\nrx_length: %lu\n" ++ "rx_mii: %lu\nrx_multicast: %lu\n" ++ "rx_gmac_overflow: %lu\nrx_watchdog: %lu\n" ++ "da_rx_filter_fail: %lu\nsa_rx_filter_fail: %lu\n" ++ "rx_missed_cntr: %lu\nrx_overflow_cntr: %lu\n" ++ "rx_vlan: %lu\n\n", ++ chip->xstats.rx_desc, chip->xstats.sa_filter_fail, ++ chip->xstats.overflow_error, chip->xstats.ipc_csum_error, ++ chip->xstats.rx_collision, chip->xstats.rx_crc, ++ chip->xstats.dribbling_bit, chip->xstats.rx_length, ++ chip->xstats.rx_mii, chip->xstats.rx_multicast, ++ chip->xstats.rx_gmac_overflow, chip->xstats.rx_length, ++ chip->xstats.da_rx_filter_fail, chip->xstats.sa_rx_filter_fail, ++ chip->xstats.rx_missed_cntr, chip->xstats.rx_overflow_cntr, ++ chip->xstats.rx_vlan); ++} ++/* eg: cat extra_rx_stats */ ++static DEVICE_ATTR(extra_rx_stats, 0444, sunxi_gmac_extra_rx_stats_show, NULL); ++ ++static ssize_t sunxi_gmac_gphy_test_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "Usage:\necho [0/1/2/3/4] > gphy_test\n" ++ "0 - Normal Mode\n" ++ "1 - Transmit Jitter Test\n" ++ "2 - Transmit Jitter Test(MASTER mode)\n" ++ "3 - Transmit Jitter Test(SLAVE mode)\n" ++ "4 - Transmit Distortion Test\n\n"); ++} ++ ++static ssize_t sunxi_gmac_gphy_test_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ u16 value, phyreg_val; ++ int ret; ++ ++ phyreg_val = phy_read(ndev->phydev, MII_CTRL1000); ++ ++ ret = kstrtou16(buf, 0, &value); ++ if (ret) ++ return ret; ++ ++ if (value >= 0 && value <= 4) { ++ phyreg_val &= ~(SUNXI_GMAC_GPHY_TEST_MASK << ++ SUNXI_GMAC_GPHY_TEST_OFFSET); ++ phyreg_val |= value << SUNXI_GMAC_GPHY_TEST_OFFSET; ++ phy_write(ndev->phydev, MII_CTRL1000, phyreg_val); ++ netdev_info(ndev, "Set MII_CTRL1000(0x09) Reg: 0x%x\n", phyreg_val); ++ } else { ++ netdev_err(ndev, "Error: Unknown value (%d)\n", value); ++ } ++ ++ return count; ++} ++/* eg: echo 0 > gphy_test */ ++static DEVICE_ATTR(gphy_test, 0664, sunxi_gmac_gphy_test_show, sunxi_gmac_gphy_test_store); ++ ++static ssize_t sunxi_gmac_mii_read_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "Usage:\necho PHYREG > mii_read\n"); ++} ++ ++static ssize_t sunxi_gmac_mii_read_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ u16 phyreg, phyreg_val; ++ int ret; ++ ++ if (!netif_running(ndev)) { ++ netdev_err(ndev, "Error: Nic is down\n"); ++ return count; ++ } ++ ++ ret = kstrtou16(buf, 0, &phyreg); ++ if (ret) ++ return ret; ++ ++ phyreg_val = phy_read(ndev->phydev, phyreg); ++ netdev_info(ndev, "PHYREG[0x%02x] = 0x%04x\n", phyreg, phyreg_val); ++ return count; ++} ++/* eg: echo 0x00 > mii_read; cat mii_read */ ++static DEVICE_ATTR(mii_read, 0664, sunxi_gmac_mii_read_show, sunxi_gmac_mii_read_store); ++ ++static ssize_t sunxi_gmac_mii_write_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "Usage:\necho PHYREG PHYVAL > mii_write\n"); ++} ++ ++static ssize_t sunxi_gmac_mii_write_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ u16 phyreg_val_before, phyreg_val_after; ++ int i, ret; ++ /* userspace_cmd[0]: phyreg ++ * userspace_cmd[1]: phyval ++ */ ++ u16 userspace_cmd[2] = {0}; ++ char *ptr1 = (char *)buf; ++ char *ptr2; ++ ++ if (!netif_running(ndev)) { ++ netdev_err(ndev, "Error: Nic is down\n"); ++ return count; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(userspace_cmd); i++) { ++ ptr1 = skip_spaces(ptr1); ++ ptr2 = strchr(ptr1, ' '); ++ if (ptr2) ++ *ptr2 = '\0'; ++ ++ ret = kstrtou16(ptr1, 16, &userspace_cmd[i]); ++ if (!ptr2 || ret) ++ break; ++ ++ ptr1 = ptr2 + 1; ++ } ++ ++ phyreg_val_before = phy_read(ndev->phydev, userspace_cmd[0]); ++ phy_write(ndev->phydev, userspace_cmd[0], userspace_cmd[1]); ++ phyreg_val_after = phy_read(ndev->phydev, userspace_cmd[0]); ++ netdev_info(ndev, "before PHYREG[0x%02x] = 0x%04x, after PHYREG[0x%02x] = 0x%04x\n", ++ userspace_cmd[0], phyreg_val_before, userspace_cmd[0], phyreg_val_after); ++ ++ return count; ++} ++/* eg: echo 0x00 0x1234 > mii_write; cat mii_write */ ++static DEVICE_ATTR(mii_write, 0664, sunxi_gmac_mii_write_show, sunxi_gmac_mii_write_store); ++ ++static ssize_t sunxi_gmac_loopback_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int macreg_val; ++ u16 phyreg_val; ++ ++ phyreg_val = phy_read(ndev->phydev, MII_BMCR); ++ if (phyreg_val & BMCR_LOOPBACK) ++ netdev_dbg(ndev, "Phy loopback enabled\n"); ++ else ++ netdev_dbg(ndev, "Phy loopback disabled\n"); ++ ++ macreg_val = readl(chip->base); ++ if (macreg_val & SUNXI_GMAC_LOOPBACK) ++ netdev_dbg(ndev, "Mac loopback enabled\n"); ++ else ++ netdev_dbg(ndev, "Mac loopback disabled\n"); ++ ++ return sprintf(buf, "Usage:\necho [0/1/2] > loopback\n" ++ "0 - Loopback off\n" ++ "1 - Mac loopback mode\n" ++ "2 - Phy loopback mode\n"); ++} ++ ++static ssize_t sunxi_gmac_loopback_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int phyreg_val, ret; ++ u16 mode; ++ ++ if (!netif_running(ndev)) { ++ netdev_err(ndev, "Error: eth is down\n"); ++ return count; ++ } ++ ++ ret = kstrtou16(buf, 0, &mode); ++ if (ret) ++ return ret; ++ ++ switch (mode) { ++ case SUNXI_GMAC_LOOPBACK_OFF: ++ sunxi_gmac_loopback(chip->base, 0); ++ phyreg_val = phy_read(ndev->phydev, MII_BMCR); ++ phy_write(ndev->phydev, MII_BMCR, phyreg_val & ~BMCR_LOOPBACK); ++ break; ++ case SUNXI_GMAC_MAC_LOOPBACK_ON: ++ phyreg_val = phy_read(ndev->phydev, MII_BMCR); ++ phy_write(ndev->phydev, MII_BMCR, phyreg_val & ~BMCR_LOOPBACK); ++ sunxi_gmac_loopback(chip->base, 1); ++ break; ++ case SUNXI_GMAC_PHY_LOOPBACK_ON: ++ sunxi_gmac_loopback(chip->base, 0); ++ phyreg_val = phy_read(ndev->phydev, MII_BMCR); ++ phy_write(ndev->phydev, MII_BMCR, phyreg_val | BMCR_LOOPBACK); ++ break; ++ default: ++ netdev_err(ndev, "Error: Please echo right value\n"); ++ break; ++ } ++ ++ return count; ++} ++/* eg: echo 1 > loopback */ ++static DEVICE_ATTR(loopback, 0664, sunxi_gmac_loopback_show, sunxi_gmac_loopback_store); ++ ++static ssize_t sunxi_gmac_tx_delay_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ u32 reg_val; ++ u16 tx_delay; ++ ++ reg_val = readl(chip->syscfg_base); ++ tx_delay = (reg_val >> SUNXI_GMAC_TX_DELAY_OFFSET) & SUNXI_GMAC_TX_DELAY_MASK; ++ ++ return sprintf(buf, "Usage:\necho [0~7] > tx_delay\n" ++ "\nnow tx_delay: %d\n", tx_delay); ++} ++ ++static ssize_t sunxi_gmac_tx_delay_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int ret; ++ u32 reg_val; ++ u16 tx_delay; ++ ++ if (!netif_running(ndev)) { ++ netdev_err(ndev, "Error: eth is down\n"); ++ return count; ++ } ++ ++ ret = kstrtou16(buf, 0, &tx_delay); ++ if (ret) ++ return ret; ++ ++ if (tx_delay > 7) ++ return -EINVAL; ++ ++ reg_val = readl(chip->syscfg_base); ++ reg_val &= ~(SUNXI_GMAC_TX_DELAY_MASK << SUNXI_GMAC_TX_DELAY_OFFSET); ++ reg_val |= ((tx_delay & SUNXI_GMAC_TX_DELAY_MASK) << SUNXI_GMAC_TX_DELAY_OFFSET); ++ writel(reg_val, chip->syscfg_base); ++ ++ return count; ++} ++/* eg: echo 1 > tx_delay */ ++static DEVICE_ATTR(tx_delay, 0664, sunxi_gmac_tx_delay_show, sunxi_gmac_tx_delay_store); ++ ++static ssize_t sunxi_gmac_rx_delay_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ u32 reg_val; ++ u16 rx_delay; ++ ++ reg_val = readl(chip->syscfg_base); ++ rx_delay = (reg_val >> SUNXI_GMAC_RX_DELAY_OFFSET) & SUNXI_GMAC_RX_DELAY_MASK; ++ ++ return sprintf(buf, "Usage:\necho [0~31] > rx_delay\n" ++ "\nnow rx_delay: %d\n", rx_delay); ++} ++ ++static ssize_t sunxi_gmac_rx_delay_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int ret; ++ u32 reg_val; ++ u16 rx_delay; ++ ++ if (!netif_running(ndev)) { ++ netdev_err(ndev, "Error: eth is down\n"); ++ return count; ++ } ++ ++ ret = kstrtou16(buf, 0, &rx_delay); ++ if (ret) ++ return ret; ++ ++ if (rx_delay > 31) ++ return -EINVAL; ++ ++ reg_val = readl(chip->syscfg_base); ++ reg_val &= ~(SUNXI_GMAC_RX_DELAY_MASK << SUNXI_GMAC_RX_DELAY_OFFSET); ++ reg_val |= ((rx_delay & SUNXI_GMAC_RX_DELAY_MASK) << SUNXI_GMAC_RX_DELAY_OFFSET); ++ writel(reg_val, chip->syscfg_base); ++ ++ return count; ++} ++/* eg: echo 1 > rx_delay */ ++static DEVICE_ATTR(rx_delay, 0664, sunxi_gmac_rx_delay_show, sunxi_gmac_rx_delay_store); ++ ++/* In phy state machine, we use this func to change link status */ ++static void sunxi_gmac_adjust_link(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct phy_device *phydev = ndev->phydev; ++ unsigned long flags; ++ int new_state = 0; ++ ++ if (!phydev) ++ return; ++ ++ spin_lock_irqsave(&chip->universal_lock, flags); ++ if (phydev->link) { ++ /* Now we make sure that we can be in full duplex mode. ++ * If not, we operate in half-duplex mode. ++ */ ++ if (phydev->duplex != chip->duplex) { ++ new_state = 1; ++ chip->duplex = phydev->duplex; ++ } ++ /* Flow Control operation */ ++ if (phydev->pause) ++ sunxi_gmac_flow_ctrl(chip->base, phydev->duplex, ++ flow_ctrl, pause); ++ ++ if (phydev->speed != chip->speed) { ++ new_state = 1; ++ chip->speed = phydev->speed; ++ } ++ ++ if (chip->link == 0) { ++ new_state = 1; ++ chip->link = phydev->link; ++ } ++ ++ if (new_state) ++ sunxi_gmac_set_link_mode(chip->base, chip->duplex, chip->speed); ++ ++ } else if (chip->link != phydev->link) { ++ new_state = 1; ++ chip->link = 0; ++ chip->speed = 0; ++ chip->duplex = -1; ++ } ++ spin_unlock_irqrestore(&chip->universal_lock, flags); ++ ++ if (new_state) ++ phy_print_status(phydev); ++} ++ ++static int sunxi_gmac_phy_release(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct phy_device *phydev = ndev->phydev; ++ int value; ++ ++ /* Stop and disconnect the PHY */ ++ if (phydev) ++ phy_stop(phydev); ++ ++ chip->link = PHY_DOWN; ++ chip->speed = 0; ++ chip->duplex = -1; ++ ++ if (phydev) { ++ value = phy_read(phydev, MII_BMCR); ++ phy_write(phydev, MII_BMCR, (value | BMCR_PDOWN)); ++ } ++ ++ if (phydev) { ++ phy_disconnect(phydev); ++ ndev->phydev = NULL; ++ } ++ ++ return 0; ++} ++ ++/* Refill rx dma descriptor after using */ ++static void sunxi_gmac_rx_refill(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct sunxi_gmac_dma_desc *desc; ++ struct sk_buff *skb = NULL; ++ dma_addr_t dma_addr; ++ ++ while (circ_space(chip->rx_clean, chip->rx_dirty, sunxi_gmac_dma_desc_rx) > 0) { ++ int entry = chip->rx_clean; ++ ++ /* Find the dirty's desc and clean it */ ++ desc = chip->dma_rx + entry; ++ ++ if (chip->rx_skb[entry] == NULL) { ++ skb = netdev_alloc_skb_ip_align(ndev, chip->buf_sz); ++ ++ if (unlikely(skb == NULL)) ++ break; ++ ++ chip->rx_skb[entry] = skb; ++ dma_addr = dma_map_single(chip->dev, skb->data, ++ chip->buf_sz, DMA_FROM_DEVICE); ++ ++ sunxi_gmac_desc_buf_set(desc, dma_addr, chip->buf_sz); ++ } ++ ++ dma_wmb(); ++ sunxi_gmac_desc_set_own(desc); ++ chip->rx_clean = circ_inc(chip->rx_clean, sunxi_gmac_dma_desc_rx); ++ } ++} ++ ++/* ++ * sunxi_gmac_dma_desc_init - initialize the RX/TX descriptor list ++ * ++ * @ndev: net device structure ++ * Description: initialize the list for dma. ++ */ ++static int sunxi_gmac_dma_desc_init(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct device *dev = &ndev->dev; ++ ++ chip->rx_skb = devm_kzalloc(dev, sizeof(chip->rx_skb[0]) * sunxi_gmac_dma_desc_rx, ++ GFP_KERNEL); ++ if (!chip->rx_skb) { ++ netdev_err(ndev, "Error: Alloc rx_skb failed\n"); ++ goto rx_skb_err; ++ } ++ chip->tx_skb = devm_kzalloc(dev, sizeof(chip->tx_skb[0]) * sunxi_gmac_dma_desc_tx, ++ GFP_KERNEL); ++ if (!chip->tx_skb) { ++ netdev_err(ndev, "Error: Alloc tx_skb failed\n"); ++ goto tx_skb_err; ++ } ++ ++ chip->dma_tx = dma_alloc_coherent(chip->dev, ++ sunxi_gmac_dma_desc_tx * ++ sizeof(struct sunxi_gmac_dma_desc), ++ &chip->dma_tx_phy, ++ GFP_KERNEL); ++ if (!chip->dma_tx) { ++ netdev_err(ndev, "Error: Alloc dma_tx failed\n"); ++ goto dma_tx_err; ++ } ++ ++ chip->dma_rx = dma_alloc_coherent(chip->dev, ++ sunxi_gmac_dma_desc_rx * ++ sizeof(struct sunxi_gmac_dma_desc), ++ &chip->dma_rx_phy, ++ GFP_KERNEL); ++ if (!chip->dma_rx) { ++ netdev_err(ndev, "Error: Alloc dma_rx failed\n"); ++ goto dma_rx_err; ++ } ++ ++ /* Set the size of buffer depend on the MTU & max buf size */ ++ chip->buf_sz = SUNXI_GMAC_MAX_BUF_SZ; ++ return 0; ++ ++dma_rx_err: ++ dma_free_coherent(chip->dev, sunxi_gmac_dma_desc_rx * sizeof(struct sunxi_gmac_dma_desc), ++ chip->dma_tx, chip->dma_tx_phy); ++dma_tx_err: ++ kfree(chip->tx_skb); ++tx_skb_err: ++ kfree(chip->rx_skb); ++rx_skb_err: ++ return -ENOMEM; ++} ++ ++static void sunxi_gmac_free_rx_skb(struct sunxi_gmac *chip) ++{ ++ int i; ++ ++ for (i = 0; i < sunxi_gmac_dma_desc_rx; i++) { ++ if (chip->rx_skb[i] != NULL) { ++ struct sunxi_gmac_dma_desc *desc = chip->dma_rx + i; ++ ++ dma_unmap_single(chip->dev, (u32)sunxi_gmac_desc_buf_get_addr(desc), ++ sunxi_gmac_desc_buf_get_len(desc), ++ DMA_FROM_DEVICE); ++ dev_kfree_skb_any(chip->rx_skb[i]); ++ chip->rx_skb[i] = NULL; ++ } ++ } ++} ++ ++static void sunxi_gmac_free_tx_skb(struct sunxi_gmac *chip) ++{ ++ int i; ++ ++ for (i = 0; i < sunxi_gmac_dma_desc_tx; i++) { ++ if (chip->tx_skb[i] != NULL) { ++ struct sunxi_gmac_dma_desc *desc = chip->dma_tx + i; ++ ++ if (sunxi_gmac_desc_buf_get_addr(desc)) ++ dma_unmap_single(chip->dev, (u32)sunxi_gmac_desc_buf_get_addr(desc), ++ sunxi_gmac_desc_buf_get_len(desc), ++ DMA_TO_DEVICE); ++ dev_kfree_skb_any(chip->tx_skb[i]); ++ chip->tx_skb[i] = NULL; ++ } ++ } ++} ++ ++static void sunxi_gmac_dma_desc_deinit(struct sunxi_gmac *chip) ++{ ++ /* Free the region of consistent memory previously allocated for the DMA */ ++ dma_free_coherent(chip->dev, sunxi_gmac_dma_desc_tx * sizeof(struct sunxi_gmac_dma_desc), ++ chip->dma_tx, chip->dma_tx_phy); ++ dma_free_coherent(chip->dev, sunxi_gmac_dma_desc_rx * sizeof(struct sunxi_gmac_dma_desc), ++ chip->dma_rx, chip->dma_rx_phy); ++ ++ kfree(chip->rx_skb); ++ kfree(chip->tx_skb); ++} ++ ++static int sunxi_gmac_stop(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ netif_stop_queue(ndev); ++ napi_disable(&chip->napi); ++ ++ netif_carrier_off(ndev); ++ ++ sunxi_gmac_phy_release(ndev); ++ ++ sunxi_gmac_dma_stop(chip->base); ++ ++ netif_tx_lock_bh(ndev); ++ /* Release the DMA TX/RX socket buffers */ ++ sunxi_gmac_free_rx_skb(chip); ++ sunxi_gmac_free_tx_skb(chip); ++ netif_tx_unlock_bh(ndev); ++ ++ return 0; ++} ++ ++static int sunxi_gmac_power_on(struct sunxi_gmac *chip) ++{ ++ int ret; ++ ++ if (IS_ERR_OR_NULL(chip->gmac_supply)) ++ return 0; ++ ++ ret = regulator_set_voltage(chip->gmac_supply, 3300000, 3300000); ++ if (ret) { ++ dev_err(chip->dev, "gmac-power set voltage error\n"); ++ return -EINVAL; ++ } ++ ++ ret = regulator_enable(chip->gmac_supply); ++ if (ret) { ++ dev_err(chip->dev, "Error: enable gmac-power failed\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static void sunxi_gmac_power_off(struct sunxi_gmac *chip) ++{ ++ if (IS_ERR_OR_NULL(chip->gmac_supply)) ++ return; ++ ++ regulator_disable(chip->gmac_supply); ++} ++ ++/** ++ * sunxi_gmac_open - GMAC device open ++ * @ndev: The Allwinner GMAC network adapter ++ * ++ * Called when system wants to start the interface. We init TX/RX channels ++ * and enable the hardware for packet reception/transmission and start the ++ * network queue. ++ * ++ * Returns 0 for a successful open, or appropriate error code ++ */ ++static int sunxi_gmac_open(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int ret; ++ ++ /* ++ * When changing the configuration of GMAC and PHY, ++ * it is necessary to turn off the carrier on the link. ++ */ ++ netif_carrier_off(ndev); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ if (chip->ac300_np) { ++ chip->ac300_dev = of_phy_find_device(chip->ac300_np); ++ if (!chip->ac300_dev) { ++ netdev_err(ndev, "Error: Could not find ac300 %s\n", ++ chip->ac300_np->full_name); ++ return -ENODEV; ++ } ++ phy_init_hw(chip->ac300_dev); ++ } ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++ if (chip->phy_node) { ++ ndev->phydev = of_phy_connect(ndev, chip->phy_node, ++ &sunxi_gmac_adjust_link, 0, chip->phy_interface); ++ if (!ndev->phydev) { ++ netdev_err(ndev, "Error: Could not connect to phy %s\n", ++ chip->phy_node->full_name); ++ return -ENODEV; ++ } ++ netdev_info(ndev, "%s: Type(%d) PHY ID %08x at %d IRQ %s (%s)\n", ++ ndev->name, ndev->phydev->interface, ndev->phydev->phy_id, ++ ndev->phydev->mdio.addr, "poll", dev_name(&ndev->phydev->mdio.dev)); ++ } ++ ret = sunxi_gmac_reset((void *)chip->base, 1000); ++ if (ret) { ++ netdev_err(ndev, "Error: Mac reset failed, please check phy and mac clk\n"); ++ goto mac_reset_err; ++ } ++ ++ sunxi_gmac_init(chip->base, txmode, rxmode); ++ sunxi_gmac_set_mac_addr_to_reg(chip->base, (unsigned char *)ndev->dev_addr, 0); ++ ++ memset(chip->dma_tx, 0, sunxi_gmac_dma_desc_tx * sizeof(struct sunxi_gmac_dma_desc)); ++ memset(chip->dma_rx, 0, sunxi_gmac_dma_desc_rx * sizeof(struct sunxi_gmac_dma_desc)); ++ ++ sunxi_gmac_desc_init_chain(chip->dma_rx, (unsigned long)chip->dma_rx_phy, sunxi_gmac_dma_desc_rx); ++ sunxi_gmac_desc_init_chain(chip->dma_tx, (unsigned long)chip->dma_tx_phy, sunxi_gmac_dma_desc_tx); ++ ++ chip->rx_clean = 0; ++ chip->rx_dirty = 0; ++ chip->tx_clean = 0; ++ chip->tx_dirty = 0; ++ sunxi_gmac_rx_refill(ndev); ++ ++ /* Extra statistics */ ++ memset(&chip->xstats, 0, sizeof(struct sunxi_gmac_extra_stats)); ++ ++ if (ndev->phydev) ++ phy_start(ndev->phydev); ++ ++ sunxi_gmac_enable_rx(chip->base, (unsigned long)((struct sunxi_gmac_dma_desc *) ++ chip->dma_rx_phy + chip->rx_dirty)); ++ sunxi_gmac_enable_tx(chip->base, (unsigned long)((struct sunxi_gmac_dma_desc *) ++ chip->dma_tx_phy + chip->tx_clean)); ++ ++ napi_enable(&chip->napi); ++ netif_start_queue(ndev); ++ ++ /* Start the Rx/Tx */ ++ sunxi_gmac_dma_start(chip->base); ++ ++ /* Indicate that the MAC is responsible for managing PHY PM */ ++ ndev->phydev->mac_managed_pm = true; ++ ++ return 0; ++ ++mac_reset_err: ++ phy_disconnect(ndev->phydev); ++ return ret; ++} ++ ++static int sunxi_gmac_clk_enable(struct sunxi_gmac *chip); ++static void sunxi_gmac_clk_disable(struct sunxi_gmac *chip); ++ ++#if IS_ENABLED(CONFIG_PM) ++static int sunxi_gmac_select_gpio_state(struct pinctrl *pctrl, char *name) ++{ ++ int ret; ++ struct pinctrl_state *pctrl_state; ++ ++ pctrl_state = pinctrl_lookup_state(pctrl, name); ++ if (IS_ERR(pctrl_state)) { ++ pr_err("gmac pinctrl_lookup_state(%s) failed! return %p\n", ++ name, pctrl_state); ++ return -EINVAL; ++ } ++ ++ ret = pinctrl_select_state(pctrl, pctrl_state); ++ if (ret < 0) ++ pr_err("gmac pinctrl_select_state(%s) failed! return %d\n", ++ name, ret); ++ ++ return ret; ++} ++ ++static int sunxi_gmac_resume(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ if (!netif_running(ndev)) ++ return 0; ++ ++ sunxi_gmac_power_on(chip); ++ ++ sunxi_gmac_clk_enable(chip); ++ ++ sunxi_gmac_select_gpio_state(chip->pinctrl, PINCTRL_STATE_DEFAULT); ++ ++ netif_device_attach(ndev); ++ ++ sunxi_gmac_open(ndev); ++ ++ /* suspend error workaround */ ++ if (ndev->phydev) ++ dev_set_uevent_suppress(&ndev->phydev->mdio.dev, chip->gmac_uevent_suppress); ++ ++ return 0; ++} ++ ++static int sunxi_gmac_suspend(struct device *dev) ++{ ++ struct net_device *ndev = dev_get_drvdata(dev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ if (!ndev || !netif_running(ndev)) ++ return 0; ++ ++ /* suspend error workaround */ ++ if (ndev->phydev) { ++ chip->gmac_uevent_suppress = dev_get_uevent_suppress(&ndev->phydev->mdio.dev); ++ dev_set_uevent_suppress(&ndev->phydev->mdio.dev, true); ++ } ++ ++ netif_device_detach(ndev); ++ ++ sunxi_gmac_stop(ndev); ++ ++ sunxi_gmac_select_gpio_state(chip->pinctrl, PINCTRL_STATE_SLEEP); ++ ++ sunxi_gmac_power_off(chip); ++ ++ sunxi_gmac_clk_disable(chip); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops sunxi_gmac_pm_ops = { ++ .suspend = sunxi_gmac_suspend, ++ .resume = sunxi_gmac_resume, ++}; ++#else ++static const struct dev_pm_ops sunxi_gmac_pm_ops; ++#endif /* CONFIG_PM */ ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++static void sunxi_gmac_shutdown(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ if (chip->ac300_dev) ++ phy_detach(chip->ac300_dev); ++} ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++static void sunxi_gmac_check_addr(struct net_device *ndev, unsigned char *mac) ++{ ++ int i; ++ char *p = mac; ++ unsigned char tmp_addr[6]; ++ ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ for (i = 0; i < ETH_ALEN; i++, p++) { ++ tmp_addr[i] = simple_strtoul(p, &p, 16); ++ dev_addr_mod(ndev, i, &tmp_addr[i], sizeof(char)); ++ } ++ ++ if (!is_valid_ether_addr(ndev->dev_addr)) { ++ eth_random_addr((u8 *)ndev->dev_addr); ++ netdev_info(ndev, "Info: Use random mac address\n"); ++ } ++ } ++} ++ ++static int sunxi_gmac_clk_enable(struct sunxi_gmac *chip) ++{ ++ struct net_device *ndev = chip->ndev; ++ int ret; ++ u32 clk_value; ++ ++ ret = reset_control_deassert(chip->reset); ++ if (ret) { ++ netdev_err(ndev, "Error: Try to de-assert gmac rst failed\n"); ++ goto gmac_reset_err; ++ } ++ ++ ret = clk_prepare_enable(chip->gmac_clk); ++ if (ret) { ++ netdev_err(ndev, "Error: Try to enable gmac_clk failed\n"); ++ goto gmac_clk_err; ++ } ++ ++ if (chip->phy_clk_type == SUNXI_PHY_USE_CLK25M) { ++ ret = clk_prepare_enable(chip->phy25m_clk); ++ if (ret) { ++ netdev_err(ndev, "Error: Try to enable phy25m_clk failed\n"); ++ goto phy25m_clk_err; ++ } ++ } ++ ++ clk_value = readl(chip->syscfg_base); ++ /* Only support RGMII/RMII/MII */ ++ if (chip->phy_interface == PHY_INTERFACE_MODE_RGMII) ++ clk_value |= SUNXI_GMAC_PHY_RGMII_MASK; ++ else ++ clk_value &= (~SUNXI_GMAC_PHY_RGMII_MASK); ++ ++ clk_value &= (~SUNXI_GMAC_ETCS_RMII_MASK); ++ if (chip->phy_interface == PHY_INTERFACE_MODE_RGMII ++ || chip->phy_interface == PHY_INTERFACE_MODE_GMII) ++ clk_value |= SUNXI_GMAC_RGMII_INTCLK_MASK; ++ else if (chip->phy_interface == PHY_INTERFACE_MODE_RMII) ++ clk_value |= SUNXI_GMAC_RMII_MASK; ++ ++ /* ++ * Adjust Tx/Rx clock delay ++ * Tx clock delay: 0~7 ++ * Rx clock delay: 0~31 ++ */ ++ clk_value &= ~(SUNXI_GMAC_TX_DELAY_MASK << SUNXI_GMAC_TX_DELAY_OFFSET); ++ clk_value |= ((chip->tx_delay & SUNXI_GMAC_TX_DELAY_MASK) << SUNXI_GMAC_TX_DELAY_OFFSET); ++ clk_value &= ~(SUNXI_GMAC_RX_DELAY_MASK << SUNXI_GMAC_RX_DELAY_OFFSET); ++ clk_value |= ((chip->rx_delay & SUNXI_GMAC_RX_DELAY_MASK) << SUNXI_GMAC_RX_DELAY_OFFSET); ++ ++ if (chip->phy_type == SUNXI_EXTERNAL_PHY) ++ clk_value &= ~(1 << 15); ++ else ++ clk_value |= (1 << 15); ++ ++ writel(clk_value, chip->syscfg_base); ++ ++ return 0; ++ ++phy25m_clk_err: ++ clk_disable(chip->gmac_clk); ++gmac_clk_err: ++ reset_control_assert(chip->reset); ++gmac_reset_err: ++ return ret; ++} ++ ++static void sunxi_gmac_clk_disable(struct sunxi_gmac *chip) ++{ ++ writel(0, chip->syscfg_base); ++ ++ if (chip->phy25m_clk) ++ clk_disable_unprepare(chip->phy25m_clk); ++ ++ if (chip->gmac_clk) ++ clk_disable_unprepare(chip->gmac_clk); ++ ++ if (chip->reset) ++ reset_control_assert(chip->reset); ++} ++ ++static void sunxi_gmac_tx_err(struct sunxi_gmac *chip) ++{ ++ netif_stop_queue(chip->ndev); ++ ++ sunxi_gmac_disable_tx(chip->base); ++ ++ sunxi_gmac_free_tx_skb(chip); ++ memset(chip->dma_tx, 0, sunxi_gmac_dma_desc_tx * sizeof(struct sunxi_gmac_dma_desc)); ++ sunxi_gmac_desc_init_chain(chip->dma_tx, (unsigned long)chip->dma_tx_phy, sunxi_gmac_dma_desc_tx); ++ chip->tx_dirty = 0; ++ chip->tx_clean = 0; ++ sunxi_gmac_enable_tx(chip->base, chip->dma_tx_phy); ++ ++ chip->ndev->stats.tx_errors++; ++ netif_wake_queue(chip->ndev); ++} ++ ++static void sunxi_gmac_schedule(struct sunxi_gmac *chip) ++{ ++ if (likely(napi_schedule_prep(&chip->napi))) { ++ sunxi_gmac_irq_disable(chip->base); ++ __napi_schedule(&chip->napi); ++ } ++} ++ ++static irqreturn_t sunxi_gmac_interrupt(int irq, void *dev_id) ++{ ++ struct net_device *ndev = (struct net_device *)dev_id; ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int status; ++ ++ status = sunxi_gmac_int_status(chip->base, (void *)(&chip->xstats)); ++ ++ if (likely(status == handle_tx_rx)) ++ sunxi_gmac_schedule(chip); ++ else if (unlikely(status == tx_hard_error_bump_tc)) ++ netdev_info(ndev, "Do nothing for bump tc\n"); ++ else if (unlikely(status == tx_hard_error)) ++ sunxi_gmac_tx_err(chip); ++ else ++ netdev_info(ndev, "Do nothing.....\n"); ++ ++ return IRQ_HANDLED; ++} ++ ++static void sunxi_gmac_tx_complete(struct sunxi_gmac *chip) ++{ ++ unsigned int entry = 0; ++ struct sk_buff *skb = NULL; ++ struct sunxi_gmac_dma_desc *desc = NULL; ++ int tx_stat; ++ ++ spin_lock_bh(&chip->tx_lock); ++ while (circ_cnt(chip->tx_dirty, chip->tx_clean, sunxi_gmac_dma_desc_tx) > 0) { ++ entry = chip->tx_clean; ++ desc = chip->dma_tx + entry; ++ ++ /* Check if the descriptor is owned by the DMA. */ ++ if (sunxi_gmac_desc_get_own(desc)) ++ break; ++ ++ /* Verify tx error by looking at the last segment */ ++ if (sunxi_gmac_desc_get_tx_last_seg(desc)) { ++ tx_stat = sunxi_gmac_desc_get_tx_status(desc, (void *)(&chip->xstats)); ++ ++ /* ++ * These stats will be parsed by net framework layer ++ * use ifconfig -a in linux cmdline to view ++ */ ++ if (likely(!tx_stat)) ++ chip->ndev->stats.tx_packets++; ++ else ++ chip->ndev->stats.tx_errors++; ++ } ++ ++ dma_unmap_single(chip->dev, (u32)sunxi_gmac_desc_buf_get_addr(desc), ++ sunxi_gmac_desc_buf_get_len(desc), DMA_TO_DEVICE); ++ ++ skb = chip->tx_skb[entry]; ++ chip->tx_skb[entry] = NULL; ++ sunxi_gmac_desc_init(desc); ++ ++ /* Find next dirty desc */ ++ chip->tx_clean = circ_inc(entry, sunxi_gmac_dma_desc_tx); ++ ++ if (unlikely(skb == NULL)) ++ continue; ++ ++ dev_kfree_skb(skb); ++ } ++ ++ if (unlikely(netif_queue_stopped(chip->ndev)) && ++ circ_space(chip->tx_dirty, chip->tx_clean, sunxi_gmac_dma_desc_tx) > ++ SUNXI_GMAC_TX_THRESH) { ++ netif_wake_queue(chip->ndev); ++ } ++ spin_unlock_bh(&chip->tx_lock); ++} ++ ++static netdev_tx_t sunxi_gmac_xmit(struct sk_buff *skb, struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct sunxi_gmac_dma_desc *desc, *first; ++ unsigned int entry, len, tmp_len = 0; ++ unsigned char *data_addr = skb->data; ++ int i, csum_insert; ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ dma_addr_t dma_addr; ++ ++ spin_lock_bh(&chip->tx_lock); ++ if (unlikely(circ_space(chip->tx_dirty, chip->tx_clean, ++ sunxi_gmac_dma_desc_tx) < (nfrags + 1))) { ++ if (!netif_queue_stopped(ndev)) { ++ netdev_err(ndev, "Error: Tx Ring full when queue awake\n"); ++ netif_stop_queue(ndev); ++ } ++ spin_unlock_bh(&chip->tx_lock); ++ ++ return NETDEV_TX_BUSY; ++ } ++ ++ csum_insert = (skb->ip_summed == CHECKSUM_PARTIAL); ++ entry = chip->tx_dirty; ++ first = chip->dma_tx + entry; ++ desc = chip->dma_tx + entry; ++ ++ len = skb_headlen(skb); ++ chip->tx_skb[entry] = skb; ++ ++ /* Every desc max size is 2K */ ++ while (len != 0) { ++ desc = chip->dma_tx + entry; ++ tmp_len = ((len > SUNXI_GMAC_MAX_BUF_SZ) ? SUNXI_GMAC_MAX_BUF_SZ : len); ++ ++ dma_addr = dma_map_single(chip->dev, data_addr, tmp_len, DMA_TO_DEVICE); ++ if (dma_mapping_error(chip->dev, dma_addr)) { ++ ndev->stats.tx_dropped++; ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&chip->tx_lock); ++ return -ENOMEM; ++ } ++ ++ sunxi_gmac_desc_buf_set(desc, dma_addr, tmp_len); ++ /* Don't set the first's own bit, here */ ++ if (first != desc) { ++ chip->tx_skb[entry] = NULL; ++ sunxi_gmac_desc_set_own(desc); ++ } ++ ++ entry = circ_inc(entry, sunxi_gmac_dma_desc_tx); ++ data_addr += tmp_len; ++ len -= tmp_len; ++ } ++ ++ for (i = 0; i < nfrags; i++) { ++ const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ ++ len = skb_frag_size(frag); ++ desc = chip->dma_tx + entry; ++ dma_addr = skb_frag_dma_map(chip->dev, frag, 0, len, DMA_TO_DEVICE); ++ if (dma_mapping_error(chip->dev, dma_addr)) { ++ ndev->stats.tx_dropped++; ++ dev_kfree_skb(skb); ++ spin_unlock_bh(&chip->tx_lock); ++ return -ENOMEM; ++ } ++ ++ sunxi_gmac_desc_buf_set(desc, dma_addr, len); ++ sunxi_gmac_desc_set_own(desc); ++ chip->tx_skb[entry] = NULL; ++ entry = circ_inc(entry, sunxi_gmac_dma_desc_tx); ++ } ++ ++ ndev->stats.tx_bytes += skb->len; ++ chip->tx_dirty = entry; ++ sunxi_gmac_desc_tx_close(first, desc, csum_insert); ++ ++ /* ++ * When the own bit, for the first frame, has to be set, all ++ * descriptors for the same frame has to be set before, to ++ * avoid race condition. ++ */ ++ dma_wmb(); ++ ++ sunxi_gmac_desc_set_own(first); ++ spin_unlock_bh(&chip->tx_lock); ++ ++ if (circ_space(chip->tx_dirty, chip->tx_clean, sunxi_gmac_dma_desc_tx) <= ++ (MAX_SKB_FRAGS + 1)) { ++ netif_stop_queue(ndev); ++ if (circ_space(chip->tx_dirty, chip->tx_clean, sunxi_gmac_dma_desc_tx) > ++ SUNXI_GMAC_TX_THRESH) ++ netif_wake_queue(ndev); ++ } ++ ++ netdev_dbg(ndev, "TX descripotor DMA: 0x%08x, dirty: %d, clean: %d\n", ++ (unsigned int)chip->dma_tx_phy, chip->tx_dirty, chip->tx_clean); ++ sunxi_gmac_dump_dma_desc(chip->dma_tx, sunxi_gmac_dma_desc_tx); ++ ++ sunxi_gmac_tx_poll(chip->base); ++ sunxi_gmac_tx_complete(chip); ++ ++ return NETDEV_TX_OK; ++} ++ ++static void sunxi_gmac_copy_loopback_data(struct sunxi_gmac *chip, ++ struct sk_buff *skb) ++{ ++ struct net_device *ndev = chip->ndev; ++ int loopback_len = chip->loopback_pkt_len; ++ int pkt_offset, frag_len, i; ++ void *frag_data = NULL; ++ u8 *loopback_buf = chip->loopback_test_rx_buf; ++ ++ if (chip->loopback_test_rx_idx == LOOPBACK_PKT_CNT) { ++ chip->loopback_test_rx_idx = 0; ++ netdev_warn(ndev, "Warning: Loopback test receive too more test pkts\n"); ++ } ++ ++ if (skb->len != chip->loopback_pkt_len) { ++ netdev_warn(ndev, "Warning: Wrong pkt length\n"); ++ chip->loopback_test_rx_idx++; ++ return; ++ } ++ ++ pkt_offset = chip->loopback_test_rx_idx * loopback_len; ++ frag_len = (int)skb_headlen(skb); ++ memcpy(loopback_buf + pkt_offset, skb->data, frag_len); ++ pkt_offset += frag_len; ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ frag_data = skb_frag_address(&skb_shinfo(skb)->frags[i]); ++ frag_len = (int)skb_frag_size(&skb_shinfo(skb)->frags[i]); ++ memcpy((loopback_buf + pkt_offset), frag_data, frag_len); ++ pkt_offset += frag_len; ++ } ++ ++ chip->loopback_test_rx_idx++; ++} ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++static int sunxi_gmac_rx_metadata_cmp(struct sk_buff *skb) ++{ ++ const u8 tmp[4] = {0xAA, 0xAA, 0xAA, 0xAA}; ++ u8 *data = skb->data; ++ ++ data = data + (2 * ETH_ALEN + 2); ++ return memcmp(data, tmp, 4); ++} ++#endif ++ ++static int sunxi_gmac_rx(struct sunxi_gmac *chip, int limit) ++{ ++ unsigned int rxcount = 0, offset = 0; ++ unsigned int entry; ++ struct sunxi_gmac_dma_desc *desc = NULL; ++ int status; ++ u32 frame_len; ++ ++ while (rxcount < limit) { ++ entry = chip->rx_dirty; ++ desc = chip->dma_rx + entry; ++ ++ if (sunxi_gmac_desc_get_own(desc)) ++ break; ++ ++ rxcount++; ++ chip->rx_dirty = circ_inc(chip->rx_dirty, sunxi_gmac_dma_desc_rx); ++ ++ /* Get length & status from hardware */ ++ frame_len = sunxi_gmac_desc_rx_frame_len(desc); ++ status = sunxi_gmac_desc_get_rx_status(desc, (void *)(&chip->xstats)); ++ ++ netdev_dbg(chip->ndev, "Rx frame size %d, status: %d\n", ++ frame_len, status); ++ ++ if (unlikely(!chip->rx_skb[entry])) { ++ netdev_err(chip->ndev, "Skb is null\n"); ++ chip->ndev->stats.rx_dropped++; ++ break; ++ } ++ ++ if (status == discard_frame || frame_len > SUNXI_GMAC_MAX_MTU_SZ) { ++ netdev_err(chip->ndev, "Get error pkt\n"); ++ chip->ndev->stats.rx_errors++; ++ if (chip->rx_skb[entry]) { ++ dev_kfree_skb_any(chip->rx_skb[entry]); ++ chip->rx_skb[entry] = NULL; ++ } ++ ++ if (chip->skb) { ++ dev_kfree_skb_any(chip->skb); ++ chip->skb = NULL; ++ } ++ continue; ++ } ++ ++ dma_unmap_single(chip->dev, (u32)sunxi_gmac_desc_buf_get_addr(desc), ++ sunxi_gmac_desc_buf_get_len(desc), DMA_FROM_DEVICE); ++ ++ /* jumbo frame */ ++ if (status == incomplete_frame) { ++ if (!chip->skb) ++ chip->skb = netdev_alloc_skb_ip_align(chip->ndev, SUNXI_GMAC_MAX_MTU_SZ); ++ ++ if (!chip->skb) { ++ netdev_err(chip->ndev, "Failed to alloc skb\n"); ++ if (chip->rx_skb[entry]) { ++ dev_kfree_skb_any(chip->rx_skb[entry]); ++ chip->rx_skb[entry] = NULL; ++ } ++ continue; ++ } ++ ++ skb_copy_to_linear_data_offset(chip->skb, offset, chip->rx_skb[entry]->data, frame_len - offset); ++ /* after copy, release tmp skb */ ++ dev_kfree_skb_any(chip->rx_skb[entry]); ++ chip->rx_skb[entry] = NULL; ++ offset = frame_len; ++ continue; ++ } else { ++ if (!chip->skb) { ++ /* ++ * no need to copy skb, ++ * pass it to protocol stack, ++ * and protocol stack will release skb ++ */ ++ chip->skb = chip->rx_skb[entry]; ++ chip->rx_skb[entry] = NULL; ++ } else { ++ skb_copy_to_linear_data_offset(chip->skb, offset, chip->rx_skb[entry]->data, frame_len - offset); ++ /* after copy, release tmp skb */ ++ dev_kfree_skb_any(chip->rx_skb[entry]); ++ chip->rx_skb[entry] = NULL; ++ } ++ offset = 0; ++ } ++ ++ if (likely(status != llc_snap)) ++ frame_len -= ETH_FCS_LEN; ++ ++ skb_put(chip->skb, frame_len); ++ ++ if (unlikely(chip->is_loopback_test)) ++ sunxi_gmac_copy_loopback_data(chip, chip->skb); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++ if (unlikely(sunxi_gmac_rx_metadata_cmp(chip->skb) == 0)) { ++ frame_len = min(frame_len, chip->metadata_len); ++ memcpy(chip->metadata_buff, chip->skb->data + (2 * ETH_ALEN + 6), frame_len); ++ complete(&chip->metadata_done); ++ dev_kfree_skb_any(chip->skb); ++ continue; ++ } ++#endif ++ ++ chip->skb->protocol = eth_type_trans(chip->skb, chip->ndev); ++ chip->skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ napi_gro_receive(&chip->napi, chip->skb); ++ ++ chip->ndev->stats.rx_packets++; ++ chip->ndev->stats.rx_bytes += frame_len; ++ chip->skb = NULL; ++ } ++ ++ if (rxcount > 0) { ++ netdev_dbg(chip->ndev, "RX descriptor DMA: 0x%08x, dirty: %d, clean: %d\n", ++ (unsigned int)chip->dma_rx_phy, chip->rx_dirty, chip->rx_clean); ++ sunxi_gmac_dump_dma_desc(chip->dma_rx, sunxi_gmac_dma_desc_rx); ++ } ++ ++ sunxi_gmac_rx_refill(chip->ndev); ++ ++ return rxcount; ++} ++ ++static int sunxi_gmac_poll(struct napi_struct *napi, int budget) ++{ ++ struct sunxi_gmac *chip = container_of(napi, struct sunxi_gmac, napi); ++ int work_done = 0; ++ ++ sunxi_gmac_tx_complete(chip); ++ work_done = sunxi_gmac_rx(chip, budget); ++ ++ if (work_done < budget) { ++ napi_complete(napi); ++ sunxi_gmac_irq_enable(chip->base); ++ } ++ ++ return work_done; ++} ++ ++static int sunxi_gmac_change_mtu(struct net_device *ndev, int new_mtu) ++{ ++ if (netif_running(ndev)) { ++ netdev_err(ndev, "Error: Nic must be stopped to change its MTU\n"); ++ return -EBUSY; ++ } ++ ++ if (new_mtu < 46) { ++ netdev_err(ndev, "Error: Invalid MTU\n"); ++ return -EINVAL; ++ } ++ ++ ndev->mtu = new_mtu; ++ netdev_update_features(ndev); ++ ++ return 0; ++} ++ ++static netdev_features_t sunxi_gmac_fix_features(struct net_device *ndev, ++ netdev_features_t features) ++{ ++ return features; ++} ++ ++static void sunxi_gmac_set_rx_mode(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ unsigned int value = 0; ++ ++ netdev_dbg(ndev, "%s: # mcasts %d, # unicast %d\n", ++ __func__, netdev_mc_count(ndev), netdev_uc_count(ndev)); ++ ++ spin_lock_bh(&chip->universal_lock); ++ if (ndev->flags & IFF_PROMISC) { ++ value = SUNXI_GMAC_FRAME_FILTER_PR; ++ } else if ((netdev_mc_count(ndev) > SUNXI_GMAC_HASH_TABLE_SIZE) || ++ (ndev->flags & IFF_ALLMULTI)) { ++ value = SUNXI_GMAC_FRAME_FILTER_PM; /* pass all multi */ ++ sunxi_gmac_hash_filter(chip->base, ~0UL, ~0UL); ++ } else if (!netdev_mc_empty(ndev)) { ++ u32 mc_filter[2]; ++ struct netdev_hw_addr *ha; ++ ++ /* Hash filter for multicast */ ++ value = SUNXI_GMAC_FRAME_FILTER_HMC; ++ ++ memset(mc_filter, 0, sizeof(mc_filter)); ++ netdev_for_each_mc_addr(ha, ndev) { ++ /* The upper 6 bits of the calculated CRC are used to ++ * index the contens of the hash table ++ */ ++ int bit_nr = bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26; ++ /* The most significant bit determines the register to ++ * use (H/L) while the other 5 bits determine the bit ++ * within the register. ++ */ ++ mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); ++ } ++ sunxi_gmac_hash_filter(chip->base, mc_filter[0], mc_filter[1]); ++ } ++ ++ /* Handle multiple unicast addresses (perfect filtering)*/ ++ if (netdev_uc_count(ndev) > 16) { ++ /* Switch to promiscuous mode is more than 8 addrs are required */ ++ value |= SUNXI_GMAC_FRAME_FILTER_PR; ++ } else { ++ int reg = 1; ++ struct netdev_hw_addr *ha; ++ ++ netdev_for_each_uc_addr(ha, ndev) { ++ sunxi_gmac_set_mac_addr_to_reg(chip->base, ha->addr, reg); ++ reg++; ++ } ++ } ++ ++#ifdef FRAME_FILTER_DEBUG ++ /* Enable Receive all mode (to debug filtering_fail errors) */ ++ value |= SUNXI_GMAC_FRAME_FILTER_RA; ++#endif ++ writel(value, chip->base + SUNXI_GMAC_RX_FRM_FLT); ++ spin_unlock_bh(&chip->universal_lock); ++} ++ ++static void sunxi_gmac_tx_timeout(struct net_device *ndev, unsigned int txqueue) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ sunxi_gmac_tx_err(chip); ++} ++ ++static int sunxi_gmac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) ++{ ++ if (!netif_running(ndev)) ++ return -EINVAL; ++ ++ if (!ndev->phydev) ++ return -EINVAL; ++ ++ return phy_mii_ioctl(ndev->phydev, rq, cmd); ++} ++ ++/* Configuration changes (passed on by ifconfig) */ ++static int sunxi_gmac_config(struct net_device *ndev, struct ifmap *map) ++{ ++ if (ndev->flags & IFF_UP) /* can't act on a running interface */ ++ return -EBUSY; ++ ++ /* Don't allow changing the I/O address */ ++ if (map->base_addr != ndev->base_addr) { ++ netdev_err(ndev, "Error: Can't change I/O address\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Don't allow changing the IRQ */ ++ if (map->irq != ndev->irq) { ++ netdev_err(ndev, "Error: Can't change IRQ number %d\n", ndev->irq); ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int sunxi_gmac_set_mac_address(struct net_device *ndev, void *p) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct sockaddr *addr = p; ++ ++ if (!is_valid_ether_addr(addr->sa_data)) { ++ netdev_err(ndev, "Error: Set error mac address\n"); ++ return -EADDRNOTAVAIL; ++ } ++ ++ eth_hw_addr_set(ndev, addr->sa_data); ++ sunxi_gmac_set_mac_addr_to_reg(chip->base, (unsigned char *)ndev->dev_addr, 0); ++ ++ return 0; ++} ++ ++static int sunxi_gmac_set_features(struct net_device *ndev, netdev_features_t features) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ if (features & NETIF_F_LOOPBACK && netif_running(ndev)) ++ sunxi_gmac_loopback(chip->base, 1); ++ else ++ sunxi_gmac_loopback(chip->base, 0); ++ ++ return 0; ++} ++ ++#if IS_ENABLED(CONFIG_NET_POLL_CONTROLLER) ++/* Polling receive - used by NETCONSOLE and other diagnostic tools ++ * to allow network I/O with interrupts disabled. ++ */ ++static void sunxi_gmac_poll_controller(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ sunxi_gmac_interrupt(dev->irq, dev); ++ enable_irq(dev->irq); ++} ++#endif ++ ++static const struct net_device_ops sunxi_gmac_netdev_ops = { ++ .ndo_init = NULL, ++ .ndo_open = sunxi_gmac_open, ++ .ndo_start_xmit = sunxi_gmac_xmit, ++ .ndo_stop = sunxi_gmac_stop, ++ .ndo_change_mtu = sunxi_gmac_change_mtu, ++ .ndo_fix_features = sunxi_gmac_fix_features, ++ .ndo_set_rx_mode = sunxi_gmac_set_rx_mode, ++ .ndo_tx_timeout = sunxi_gmac_tx_timeout, ++ .ndo_do_ioctl = sunxi_gmac_ioctl, ++ .ndo_set_config = sunxi_gmac_config, ++#if IS_ENABLED(CONFIG_NET_POLL_CONTROLLER) ++ .ndo_poll_controller = sunxi_gmac_poll_controller, ++#endif ++ .ndo_set_mac_address = sunxi_gmac_set_mac_address, ++ .ndo_set_features = sunxi_gmac_set_features, ++}; ++ ++static int sunxi_gmac_check_if_running(struct net_device *ndev) ++{ ++ if (!netif_running(ndev)) ++ return -EBUSY; ++ return 0; ++} ++ ++static int sunxi_gmac_ethtool_get_sset_count(struct net_device *netdev, int sset) ++{ ++ int len; ++ ++ switch (sset) { ++ case ETH_SS_STATS: ++ len = 0; ++ return len; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++ ++/** ++ * sunxi_gmac_ethtool_getdrvinfo - Get various SUNXI GMAC driver information. ++ * @ndev: Pointer to net_device structure ++ * @ed: Pointer to ethtool_drvinfo structure ++ * ++ * This implements ethtool command for getting the driver information. ++ * Issue "ethtool -i ethX" under linux prompt to execute this function. ++ */ ++static void sunxi_gmac_ethtool_getdrvinfo(struct net_device *ndev, ++ struct ethtool_drvinfo *info) ++{ ++ strscpy(info->driver, "sunxi_gmac", sizeof(info->driver)); ++ ++ strcpy(info->version, SUNXI_GMAC_MODULE_VERSION); ++ info->fw_version[0] = '\0'; ++} ++ ++/** ++ * sunxi_gmac_ethool_get_pauseparam - Get the pause parameter setting for Tx/Rx. ++ * ++ * @ndev: Pointer to net_device structure ++ * @epause: Pointer to ethtool_pauseparam structure ++ * ++ * This implements ethtool command for getting sunxi_gmac ethernet pause frame ++ * setting. Issue "ethtool -a ethx" to execute this function. ++ */ ++static void sunxi_gmac_ethtool_get_pauseparam(struct net_device *ndev, ++ struct ethtool_pauseparam *epause) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ /* TODO: need to support autoneg */ ++ epause->tx_pause = sunxi_gmac_read_tx_flowctl(chip->base); ++ epause->rx_pause = sunxi_gmac_read_rx_flowctl(chip->base); ++} ++ ++/** ++ * sunxi_gmac_ethtool_set_pauseparam - Set device pause paramter(flow contrl) ++ * settings. ++ * @ndev: Pointer to net_device structure ++ * @epause: Pointer to ethtool_pauseparam structure ++ * ++ * This implements ethtool command for enabling flow control on Rx and Tx. ++ * Issue "ethtool -A ethx tx on|off" under linux prompt to execute this ++ * function. ++ * ++ */ ++static int sunxi_gmac_ethtool_set_pauseparam(struct net_device *ndev, ++ struct ethtool_pauseparam *epause) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ sunxi_gmac_write_tx_flowctl(chip->base, !!epause->tx_pause); ++ netdev_info(ndev, "Tx flowctrl %s\n", epause->tx_pause ? "ON" : "OFF"); ++ ++ sunxi_gmac_write_rx_flowctl(chip->base, !!epause->rx_pause); ++ netdev_info(ndev, "Rx flowctrl %s\n", epause->rx_pause ? "ON" : "OFF"); ++ ++ return 0; ++} ++ ++/** ++ * sunxi_gmac_ethtool_get_wol - Get device wake-on-lan settings. ++ * ++ * @ndev: Pointer to net_device structure ++ * @wol: Pointer to ethtool_wolinfo structure ++ * ++ * This implements ethtool command for get wake-on-lan settings. ++ * Issue "ethtool -s ethx wol p|u|m|b|a|g|s|d" under linux prompt to execute ++ * this function. ++ */ ++static void sunxi_gmac_ethtool_get_wol(struct net_device *ndev, ++ struct ethtool_wolinfo *wol) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ spin_lock_irq(&chip->universal_lock); ++ /* TODO: need to support wol */ ++ spin_unlock_irq(&chip->universal_lock); ++ ++ netdev_err(ndev, "Error: wakeup-on-lan func is not supported yet\n"); ++} ++ ++/** ++ * sunxi_gmac_ethtool_set_wol - set device wake-on-lan settings. ++ * ++ * @ndev: Pointer to net_device structure ++ * @wol: Pointer to ethtool_wolinfo structure ++ * ++ * This implements ethtool command for set wake-on-lan settings. ++ * Issue "ethtool -s ethx wol p|u|n|b|a|g|s|d" under linux prompt to execute ++ * this function. ++ */ ++static int sunxi_gmac_ethtool_set_wol(struct net_device *ndev, ++ struct ethtool_wolinfo *wol) ++{ ++ /* ++ * TODO: Wake-on-lane function need to be supported. ++ */ ++ ++ return 0; ++} ++ ++static int __sunxi_gmac_loopback_test(struct net_device *ndev) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct sk_buff *skb_tmp = NULL, *skb = NULL; ++ u8 *test_data = NULL; ++ u8 *loopback_test_rx_buf = chip->loopback_test_rx_buf; ++ u32 i, j; ++ ++ skb_tmp = alloc_skb(LOOPBACK_PKT_LEN, GFP_ATOMIC); ++ if (!skb_tmp) ++ return -ENOMEM; ++ ++ test_data = __skb_put(skb_tmp, LOOPBACK_PKT_LEN); ++ ++ memset(test_data, 0xFF, 2 * ETH_ALEN); ++ test_data[ETH_ALEN] = 0xFE; ++ test_data[2 * ETH_ALEN] = 0x08; ++ test_data[2 * ETH_ALEN + 1] = 0x0; ++ ++ for (i = ETH_HLEN; i < LOOPBACK_PKT_LEN; i++) ++ test_data[i] = i & 0xFF; ++ ++ skb_tmp->queue_mapping = 0; ++ skb_tmp->ip_summed = CHECKSUM_COMPLETE; ++ skb_tmp->dev = ndev; ++ ++ for (i = 0; i < LOOPBACK_DEFAULT_TIME; i++) { ++ chip->loopback_test_rx_idx = 0; ++ memset(loopback_test_rx_buf, 0, LOOPBACK_PKT_CNT * LOOPBACK_PKT_LEN); ++ ++ for (j = 0; j < LOOPBACK_PKT_CNT; j++) { ++ skb = pskb_copy(skb_tmp, GFP_ATOMIC); ++ if (!skb) { ++ dev_kfree_skb_any(skb_tmp); ++ netdev_err(ndev, "Error: Copy skb failed for loopback test\n"); ++ return -ENOMEM; ++ } ++ ++ /* mark index for every pkt */ ++ skb->data[LOOPBACK_PKT_LEN - 1] = j; ++ ++ /* xmit loopback skb */ ++ if (sunxi_gmac_xmit(skb, ndev)) { ++ dev_kfree_skb_any(skb); ++ dev_kfree_skb_any(skb_tmp); ++ netdev_err(ndev, "Error: Xmit pkt failed for loopback test\n"); ++ return -EBUSY; ++ } ++ } ++ ++ /* wait till all pkts received to RX buffer */ ++ msleep(200); ++ ++ for (j = 0; j < LOOPBACK_PKT_CNT; j++) { ++ /* compare loopback data */ ++ if (memcmp(loopback_test_rx_buf + j * LOOPBACK_PKT_LEN, ++ skb_tmp->data, LOOPBACK_PKT_LEN - 1) || ++ (*(loopback_test_rx_buf + j * LOOPBACK_PKT_LEN + ++ LOOPBACK_PKT_LEN - 1) != j)) { ++ dev_kfree_skb_any(skb_tmp); ++ netdev_err(ndev, "Error: Compare pkt failed in loopback test (index=0x%02x, data[%d]=0x%02x)\n", ++ j + i * LOOPBACK_PKT_CNT, ++ LOOPBACK_PKT_LEN - 1, ++ *(loopback_test_rx_buf + j * LOOPBACK_PKT_LEN + ++ LOOPBACK_PKT_LEN - 1)); ++ return -EIO; ++ } ++ } ++ } ++ ++ dev_kfree_skb_any(skb_tmp); ++ return 0; ++} ++ ++static int sunxi_gmac_loopback_test(struct net_device *ndev, u32 flags, ++ enum self_test_index *test_index) ++{ ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ u8 *loopback_test_rx_buf = NULL; ++ int err = 0; ++ ++ /* set loopback */ ++ if (!(flags & ETH_TEST_FL_EXTERNAL_LB)) { ++ *test_index = INTERNAL_LOOPBACK_TEST; ++ sunxi_gmac_loopback(chip->base, true); ++ } else { ++ *test_index = EXTERNAL_LOOPBACK_TEST; ++ err |= phy_loopback(ndev->phydev, true); ++ if (err) ++ goto out; ++ } ++ ++ /* only focus data part, so turn off the crc check */ ++ sunxi_gmac_crc(chip->base, false); ++ ++ loopback_test_rx_buf = vmalloc(LOOPBACK_PKT_CNT * LOOPBACK_PKT_LEN); ++ if (!loopback_test_rx_buf) { ++ err |= -ENOMEM; ++ } else { ++ chip->loopback_test_rx_buf = loopback_test_rx_buf; ++ chip->loopback_pkt_len = LOOPBACK_PKT_LEN; ++ chip->is_loopback_test = true; ++ err |= __sunxi_gmac_loopback_test(ndev); ++ chip->is_loopback_test = false; ++ msleep(100); ++ vfree(loopback_test_rx_buf); ++ chip->loopback_test_rx_buf = NULL; ++ } ++ ++ sunxi_gmac_crc(chip->base, true); ++out: ++ if (!(flags & ETH_TEST_FL_EXTERNAL_LB)) ++ sunxi_gmac_loopback(chip->base, false); ++ else ++ err |= phy_loopback(ndev->phydev, false); ++ ++ return err; ++} ++ ++static void sunxi_gmac_self_test(struct net_device *ndev, ++ struct ethtool_test *eth_test, u64 *data) ++{ ++ enum self_test_index test_index = 0; ++ int err; ++ ++ memset(data, 0, SELF_TEST_MAX * sizeof(u64)); ++ ++ if (!netif_running(ndev)) { ++ netdev_err(ndev, "Error: Do not support selftest when ndev is closed\n"); ++ eth_test->flags |= ETH_TEST_FL_FAILED; ++ return; ++ } ++ ++ netif_carrier_off(ndev); ++ netif_tx_disable(ndev); ++ ++ err = sunxi_gmac_loopback_test(ndev, eth_test->flags, &test_index); ++ if (err) { ++ eth_test->flags |= ETH_TEST_FL_FAILED; ++ data[test_index] = 1; /* 0:success, 1:fail */ ++ netdev_err(ndev, "Error: Loopback test failed\n"); ++ } ++ ++ netif_tx_wake_all_queues(ndev); ++ netif_carrier_on(ndev); ++} ++ ++static int sunxi_gmac_get_sset_count(struct net_device *ndev, int sset) ++{ ++ switch (sset) { ++ case ETH_SS_TEST: ++ return ARRAY_SIZE(sunxi_gmac_test_strings); ++ case ETH_SS_STATS: ++ return -EOPNOTSUPP; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static void sunxi_gmac_get_strings(struct net_device *netdev, ++ u32 stringset, u8 *data) ++{ ++ switch (stringset) { ++ case ETH_SS_TEST: ++ memcpy(data, *sunxi_gmac_test_strings, sizeof(sunxi_gmac_test_strings)); ++ return; ++ case ETH_SS_STATS: ++ return; ++ default: ++ return; ++ } ++} ++ ++static const struct ethtool_ops sunxi_gmac_ethtool_ops = { ++ .begin = sunxi_gmac_check_if_running, ++ .get_link = ethtool_op_get_link, ++ .get_pauseparam = sunxi_gmac_ethtool_get_pauseparam, ++ .set_pauseparam = sunxi_gmac_ethtool_set_pauseparam, ++ .get_wol = sunxi_gmac_ethtool_get_wol, ++ .set_wol = sunxi_gmac_ethtool_set_wol, ++ .get_sset_count = sunxi_gmac_ethtool_get_sset_count, ++ .get_drvinfo = sunxi_gmac_ethtool_getdrvinfo, ++ .get_link_ksettings = phy_ethtool_get_link_ksettings, ++ .set_link_ksettings = phy_ethtool_set_link_ksettings, ++ .get_sset_count = sunxi_gmac_get_sset_count, ++ .get_strings = sunxi_gmac_get_strings, ++ .self_test = sunxi_gmac_self_test, ++}; ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++static int sunxi_gmac_ephy_v1_hardware_init(struct sunxi_gmac *chip) ++{ ++ int ret; ++ ++ ret = pwm_config(chip->ac300_pwm, PWM_DUTY_NS, PWM_PERIOD_NS); ++ if (ret) { ++ netdev_err(chip->ndev, "Error: Config ac300 pwm failed\n"); ++ return ret; ++ } ++ ++ ret = pwm_enable(chip->ac300_pwm); ++ if (ret) { ++ netdev_err(chip->ndev, "Error: Enable ac300 pwm failed\n"); ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++static int sunxi_gmac_hardware_init(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ int ret; ++ ++ ret = sunxi_gmac_power_on(chip); ++ if (ret) { ++ netdev_err(ndev, "Error: Gmac power on failed\n"); ++ ret = -EINVAL; ++ goto power_on_err; ++ } ++ ++ ret = sunxi_gmac_clk_enable(chip); ++ if (ret) { ++ netdev_err(ndev, "Error: Clk enable is failed\n"); ++ ret = -EINVAL; ++ goto clk_enable_err; ++ } ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ ret = chip->ephy_ops->hardware_init(chip); ++ if (ret) { ++ netdev_err(ndev, "Error: ephy init failed\n"); ++ ret = -EINVAL; ++ goto ephy_init_err; ++ } ++ ++ return 0; ++ ++ephy_init_err: ++ sunxi_gmac_clk_disable(chip); ++#endif /* CONFIG_SUNXI55I_EPHY */ ++clk_enable_err: ++ sunxi_gmac_power_off(chip); ++power_on_err: ++ return ret; ++} ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++static void sunxi_gmac_ephy_v1_hardware_deinit(struct sunxi_gmac *chip) ++{ ++ pwm_disable(chip->ac300_pwm); ++} ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++static void sunxi_gmac_hardware_deinit(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ sunxi_gmac_power_off(chip); ++ ++ sunxi_gmac_clk_disable(chip); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ chip->ephy_ops->hardware_deinit(chip); ++#endif /* CONFIG_SUNXI55I_EPHY */ ++} ++ ++static void sunxi_gmac_parse_delay_maps(struct sunxi_gmac *chip) ++{ ++ struct platform_device *pdev = to_platform_device(chip->dev); ++ struct device_node *np = pdev->dev.of_node; ++ int ret, maps_cnt; ++ u32 *maps; ++ ++ maps_cnt = of_property_count_elems_of_size(np, "delay-maps", sizeof(u32)); ++ if (maps_cnt <= 0) { ++ dev_info(&pdev->dev, "Info: not found delay-maps in dts\n"); ++ return; ++ } ++ ++ maps = devm_kcalloc(&pdev->dev, maps_cnt, sizeof(u32), GFP_KERNEL); ++ if (!maps) ++ return; ++ ++ ret = of_property_read_u32_array(np, "delay-maps", maps, maps_cnt); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: failed to parse delay-maps\n"); ++ goto err_parse_maps; ++ } ++/* todo ++ const u8 array_size = 3; ++ u16 soc_ver; ++ int i; ++ ++ soc_ver = (u16)sunxi_get_soc_ver(); ++ for (i = 0; i < (maps_cnt / array_size); i++) { ++ if (soc_ver == maps[i * array_size]) { ++ chip->rx_delay = maps[i * array_size + 1]; ++ chip->tx_delay = maps[i * array_size + 2]; ++ dev_info(&pdev->dev, "Info: delay-maps overwrite delay parameters, rx-delay:%d, tx-delay:%d\n", ++ chip->rx_delay, chip->tx_delay); ++ } ++ } ++*/ ++err_parse_maps: ++ devm_kfree(&pdev->dev, maps); ++} ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++static int sunxi_gmac_ephy_v1_resource_get(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct device_node *np = pdev->dev.of_node; ++ int ret; ++ ++ ret = of_property_read_u32(np, "sunxi,pwm-channel", &chip->pwm_channel); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Get ac300 pwm failed\n"); ++ return -EINVAL; ++ } ++ ++ chip->ac300_pwm = pwm_request(chip->pwm_channel, NULL); ++ if (IS_ERR_OR_NULL(chip->ac300_pwm)) { ++ dev_err(&pdev->dev, "Error: Get ac300 pwm failed\n"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++static int sunxi_gmac_resource_get(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ struct device_node *np = pdev->dev.of_node; ++ struct resource *res; ++ struct cpumask mask; ++ int cpu; ++ phy_interface_t phy_mode; ++ ++ int ret; ++ ++ /* External phy is selected by default */ ++ chip->phy_type = SUNXI_EXTERNAL_PHY; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "Error: Get gmac memory failed\n"); ++ return -ENODEV; ++ } ++ ++ chip->base = devm_ioremap_resource(&pdev->dev, res); ++ if (!chip->base) { ++ dev_err(&pdev->dev, "Error: Gmac memory mapping failed\n"); ++ return -ENOMEM; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res) { ++ dev_err(&pdev->dev, "Error: Get phy memory failed\n"); ++ return -ENODEV; ++ } ++ ++ chip->syscfg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); ++ if (!chip->syscfg_base) { ++ dev_err(&pdev->dev, "Error: Phy memory mapping failed\n"); ++ return -ENOMEM; ++ } ++ ++ ndev->irq = platform_get_irq_byname(pdev, "gmacirq"); ++ if (ndev->irq < 0) { ++ dev_err(&pdev->dev, "Error: Gmac irq not found\n"); ++ return -ENXIO; ++ } ++ ++ ret = devm_request_irq(&pdev->dev, ndev->irq, sunxi_gmac_interrupt, IRQF_SHARED, dev_name(&pdev->dev), ndev); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Could not request irq %d\n", ndev->irq); ++ return -EINVAL; ++ } ++ ++ ret = of_property_read_u32(np, "irq-affinity", &chip->irq_affinity); ++ if (ret) { ++ dev_dbg(&pdev->dev, "Info: Get irq-affinity failed, use default\n"); ++ } else { ++ for_each_online_cpu(cpu) { ++ if (chip->irq_affinity & BIT(cpu)) ++ cpumask_set_cpu(cpu, &mask); ++ } ++ irq_set_affinity(ndev->irq, &mask); ++ dev_info(&pdev->dev, "Info: Set irq affinity to cpu%d\n", cpumask_first(&mask)); ++ } ++ ++ chip->reset = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(chip->reset)) { ++ dev_err(&pdev->dev, "Error: Get gmac rst failed\n"); ++ return -EINVAL; ++ } ++ ++ chip->pinctrl = devm_pinctrl_get(&pdev->dev); ++ if (IS_ERR(chip->pinctrl)) { ++ dev_err(&pdev->dev, "Error: Get Pin failed\n"); ++ return -EIO; ++ } ++ ++ chip->gmac_clk = devm_clk_get(&pdev->dev, "gmac"); ++ if (!chip->gmac_clk) { ++ dev_err(&pdev->dev, "Error: Get gmac clock failed\n"); ++ return -EINVAL; ++ } ++ ++ ret = of_get_phy_mode(np, &phy_mode); ++ if (!ret) { ++ chip->phy_interface = phy_mode; ++ if (chip->phy_interface != PHY_INTERFACE_MODE_RGMII && ++ chip->phy_interface != PHY_INTERFACE_MODE_RMII && ++ chip->phy_interface != PHY_INTERFACE_MODE_MII) { ++ dev_err(&pdev->dev, "Error: Get gmac phy interface failed\n"); ++ return -EINVAL; ++ } ++ } ++ ++ ret = of_property_read_u32(np, "tx-delay", &chip->tx_delay); ++ if (ret) { ++ dev_warn(&pdev->dev, "Warning: Get gmac tx-delay failed, use default 0\n"); ++ chip->tx_delay = 0; ++ } ++ ++ if (user_tx_delay >= 0 && user_tx_delay <= 7) { ++ chip->tx_delay = user_tx_delay; ++ dev_info(&pdev->dev, "Info: user tx-delay: %d\n", chip->tx_delay); ++ } else { ++ dev_info(&pdev->dev, "Info: dts tx-delay: %d\n", chip->tx_delay); ++ } ++ ++ ret = of_property_read_u32(np, "rx-delay", &chip->rx_delay); ++ if (ret) { ++ dev_warn(&pdev->dev, "Warning: Get gmac rx-delay failed, use default 0\n"); ++ chip->rx_delay = 0; ++ } ++ ++ if (user_rx_delay >= 0 && user_rx_delay <= 31) { ++ chip->rx_delay = user_rx_delay; ++ dev_info(&pdev->dev, "Info: user rx-delay: %d\n", chip->rx_delay); ++ } else { ++ dev_info(&pdev->dev, "Info: dts rx-delay: %d\n", chip->rx_delay); ++ } ++ ++ sunxi_gmac_parse_delay_maps(chip); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ chip->ac300_np = of_parse_phandle(np, "ac300-phy-handle", 0); ++ if (!chip->ac300_np) { ++ dev_err(&pdev->dev, "Error: Get gmac ac300-phy-handle failed\n"); ++ return -EINVAL; ++ } ++ ++ ret = chip->ephy_ops->resource_get(pdev); ++ if (ret) ++ return -EINVAL; ++ ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++ chip->phy_node = of_parse_phandle(np, "phy-handle", 0); ++ if (!chip->phy_node) { ++ dev_err(&pdev->dev, "Error: Get gmac phy-handle failed\n"); ++ return -EINVAL; ++ } ++ ++ ret = of_property_read_u32(np, "sunxi,phy-clk-type", &chip->phy_clk_type); ++ if (ret) { ++ dev_warn(&pdev->dev, "Warning: Get gmac phy-clk-type failed, use default OSC or pwm\n"); ++ chip->phy_clk_type = SUNXI_PHY_USE_EXT_OSC; ++ }; ++ ++ if (chip->phy_clk_type == SUNXI_PHY_USE_CLK25M) { ++ chip->phy25m_clk = devm_clk_get(&pdev->dev, "phy25m"); ++ if (IS_ERR_OR_NULL(chip->phy25m_clk)) { ++ dev_err(&pdev->dev, "Error: Get phy25m clk failed\n"); ++ return -EINVAL; ++ } ++ } ++ ++ chip->gmac_supply = devm_regulator_get_optional(&pdev->dev, "gmac3v3"); ++ if (IS_ERR(chip->gmac_supply)) ++ netdev_err(ndev, "Error: Not found gmac3v3-supply\n"); ++ ++ /* ++ * Read mac-address from dts, ++ * it doesn't matter if it's missing ++ */ ++ of_get_ethdev_address(np, ndev); ++ ++ return 0; ++} ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++static void sunxi_gmac_ephy_v1_resource_put(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ pwm_free(chip->ac300_pwm); ++} ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++static void sunxi_gmac_resource_put(struct platform_device *pdev) ++{ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++ chip->ephy_ops->resource_put(pdev); ++#endif /* CONFIG_SUNXI55I_EPHY */ ++} ++ ++static void sunxi_gmac_sysfs_create(struct device *dev) ++{ ++ device_create_file(dev, &dev_attr_gphy_test); ++ device_create_file(dev, &dev_attr_mii_read); ++ device_create_file(dev, &dev_attr_mii_write); ++ device_create_file(dev, &dev_attr_loopback); ++ device_create_file(dev, &dev_attr_tx_delay); ++ device_create_file(dev, &dev_attr_rx_delay); ++ device_create_file(dev, &dev_attr_extra_tx_stats); ++ device_create_file(dev, &dev_attr_extra_rx_stats); ++} ++ ++static void sunxi_gmac_sysfs_destroy(struct device *dev) ++{ ++ device_remove_file(dev, &dev_attr_gphy_test); ++ device_remove_file(dev, &dev_attr_mii_read); ++ device_remove_file(dev, &dev_attr_mii_write); ++ device_remove_file(dev, &dev_attr_loopback); ++ device_remove_file(dev, &dev_attr_tx_delay); ++ device_remove_file(dev, &dev_attr_rx_delay); ++ device_remove_file(dev, &dev_attr_extra_tx_stats); ++ device_remove_file(dev, &dev_attr_extra_rx_stats); ++} ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++ ++#define GMAC_WRITE _IOWR('X', 1, unsigned int) ++#define GMAC_READ _IOWR('X', 2, unsigned int) ++ ++static int sunxi_gmac_fops_open(struct inode *inode, struct file *file) ++{ ++ struct miscdevice *mdev = file->private_data; ++ struct sunxi_gmac *chip = container_of(mdev, struct sunxi_gmac, mdev); ++ ++ file->private_data = chip; ++ ++ return 0; ++} ++ ++static int sunxi_gmac_fops_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static struct sk_buff *sunxi_gmac_skb_compose(struct sunxi_gmac *chip) ++{ ++ struct sk_buff *skb; ++ u8 *skb_data, *data = chip->metadata_buff; ++ u32 len = chip->ndev->mtu; ++ const u8 markbits = 4; ++ ++ skb = alloc_skb(len, GFP_KERNEL); ++ if (!skb) ++ return NULL; ++ ++ skb_data = __skb_put(skb, len); ++ ++ /* ++ * compose broadcast skb ++ * dest mac : FF-FF-FF-FF-FF-FF ++ * src mac : FE-FF-FF-FF-FF-FF ++ * protocal : 08-00 ++ * metadata mark: AA-AA-AA-AA ++ * */ ++ memset(skb_data, 0, len); ++ memset(skb_data, 0xFF, 2 * ETH_ALEN); ++ skb_data[ETH_ALEN] = 0xFE; ++ skb_data[2 * ETH_ALEN] = 0x08; ++ skb_data[2 * ETH_ALEN + 1] = 0x0; ++ skb_data = skb_data + (2 * ETH_ALEN + 2); ++ memset(skb_data, 0xAA, markbits); ++ ++ skb_data = skb_data + markbits; ++ memcpy(skb_data, data, len); ++ ++ skb->queue_mapping = 0; ++ skb->ip_summed = CHECKSUM_NONE; ++ skb->dev = chip->ndev; ++ ++ return skb; ++} ++ ++static long sunxi_gmac_fops_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ struct sunxi_gmac *chip = file->private_data; ++ struct sk_buff *skb; ++ int ret; ++ ++ memset(chip->metadata_buff, 0, chip->metadata_len); ++ switch (cmd) { ++ case GMAC_WRITE: ++ ret = copy_from_user(chip->metadata_buff, (void __user *)arg, chip->metadata_len); ++ if (ret) { ++ dev_err(chip->dev, "metadata copy from user err\n"); ++ return -EFAULT; ++ } ++ ++ skb = sunxi_gmac_skb_compose(chip); ++ if (!skb) ++ return -ENOMEM; ++ ++ if (sunxi_gmac_xmit(skb, skb->dev)) ++ return -EBUSY; ++ ++ break; ++ case GMAC_READ: ++ wait_for_completion(&chip->metadata_done); ++ ++ ret = copy_to_user((void __user *)arg, chip->metadata_buff, chip->metadata_len); ++ if (ret) { ++ dev_err(chip->dev, "metadata copy to user err\n"); ++ return -EFAULT; ++ } ++ break; ++ default: ++ ret = -EFAULT; ++ dev_err(chip->dev, "Unspported cmd\n"); ++ break; ++ } ++ ++ return ret; ++} ++ ++struct file_operations sunxi_gmac_fops = { ++ .owner = THIS_MODULE, ++ .open = sunxi_gmac_fops_open, ++ .release = sunxi_gmac_fops_release, ++ .unlocked_ioctl = sunxi_gmac_fops_ioctl, ++}; ++ ++static int sunxi_gmac_fops_init(struct sunxi_gmac *chip) ++{ ++ chip->mdev.parent = chip->dev; ++ chip->mdev.minor = MISC_DYNAMIC_MINOR; ++ chip->mdev.name = "gmac"; ++ chip->mdev.fops = &sunxi_gmac_fops; ++ ++ /* MTU includes 4 bytes of mark, so the maximum metadata is MTU - 4 bytes in length */ ++ chip->metadata_len = chip->ndev->mtu - 4; ++ ++ chip->metadata_buff = devm_kzalloc(chip->dev, (sizeof(char) * chip->metadata_len), GFP_KERNEL); ++ if (!chip->metadata_buff) ++ return -ENOMEM; ++ ++ init_completion(&chip->metadata_done); ++ ++ return misc_register(&chip->mdev); ++} ++ ++static void sunxi_gmac_fops_exit(struct sunxi_gmac *chip) ++{ ++ kfree(chip->metadata_buff); ++ misc_deregister(&chip->mdev); ++} ++ ++#endif /* CONFIG_SUNXI55I_GMAC_METADATA */ ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++static struct sunxi_gmac_ephy_ops sunxi_gmac_ephy_ops_v1 = { ++ .resource_get = sunxi_gmac_ephy_v1_resource_get, ++ .resource_put = sunxi_gmac_ephy_v1_resource_put, ++ .hardware_init = sunxi_gmac_ephy_v1_hardware_init, ++ .hardware_deinit = sunxi_gmac_ephy_v1_hardware_deinit, ++}; ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ ++static const struct of_device_id sunxi_gmac_of_match[] = { ++ {.compatible = "allwinner,sunxi-gmac",}, ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ {.compatible = "allwinner,sunxi-gmac-ephy-v1", .data = &sunxi_gmac_ephy_ops_v1, }, ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, sunxi_gmac_of_match); ++ ++/** ++ * sunxi_gmac_probe - GMAC device probe ++ * @pdev: The SUNXI GMAC device that we are removing ++ * ++ * Called when probing for GMAC device. We get details of instances and ++ * resource information from platform init and register a network device ++ * and allocate resources necessary for driver to perform ++ * ++ */ ++static int sunxi_gmac_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct net_device *ndev; ++ struct sunxi_gmac *chip; ++ const struct of_device_id *match; ++ ++ dev_dbg(&pdev->dev, "%s() BEGIN\n", __func__); ++ ++ match = of_match_device(sunxi_gmac_of_match, &pdev->dev); ++ if (!match) { ++ dev_err(&pdev->dev, "gmac probe match device failed\n"); ++ return -EINVAL; ++ } ++ ++ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); ++ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; ++ ++ ndev = alloc_etherdev(sizeof(*chip)); ++ if (!ndev) { ++ dev_err(&pdev->dev, "Error: Allocate network device failed\n"); ++ ret = -ENOMEM; ++ goto alloc_etherdev_err; ++ } ++ SET_NETDEV_DEV(ndev, &pdev->dev); ++ ++ chip = netdev_priv(ndev); ++ platform_set_drvdata(pdev, ndev); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ chip->ephy_ops = (struct sunxi_gmac_ephy_ops *)match->data; ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ chip->ndev = ndev; ++ chip->dev = &pdev->dev; ++ ret = sunxi_gmac_resource_get(pdev); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Get gmac hardware resource failed\n"); ++ goto resource_get_err; ++ } ++ ++ ret = sunxi_gmac_hardware_init(pdev); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Init gmac hardware resource failed\n"); ++ goto hardware_init_err; ++ } ++ ++ /* ++ * setup the netdevice ++ * fillup netdevice base memory and ops ++ * fillup netdevice ethtool ops ++ */ ++ ether_setup(ndev); ++ ndev->netdev_ops = &sunxi_gmac_netdev_ops; ++ netdev_set_default_ethtool_ops(ndev, &sunxi_gmac_ethtool_ops); ++ ndev->base_addr = (unsigned long)chip->base; ++ ++ /* fillup netdevice features and flags */ ++ ndev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | ++ NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_GRO; ++ ndev->features |= ndev->hw_features; ++ ndev->hw_features |= NETIF_F_LOOPBACK; ++ ndev->priv_flags |= IFF_UNICAST_FLT; ++ ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ++ ndev->max_mtu = SUNXI_GMAC_MAX_MTU_SZ; ++ ++ /* add napi poll method */ ++ netif_napi_add(ndev, &chip->napi, sunxi_gmac_poll); ++ ++ spin_lock_init(&chip->universal_lock); ++ spin_lock_init(&chip->tx_lock); ++ ++ ret = register_netdev(ndev); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Register %s failed\n", ndev->name); ++ goto register_err; ++ } ++ ++//todo #ifdef MODULE ++// get_custom_mac_address(0, "eth", mac_str); ++//#endif ++ /* Before open the device, the mac address should be set */ ++ sunxi_gmac_check_addr(ndev, mac_str); ++ ++ memcpy(ndev->dev_addr_shadow, ndev->dev_addr, 18); ++ ++ ret = sunxi_gmac_dma_desc_init(ndev); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Init dma descriptor failed\n"); ++ goto init_dma_desc_err; ++ } ++ ++ sunxi_gmac_sysfs_create(&pdev->dev); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++ ret = sunxi_gmac_fops_init(chip); ++ if (ret) { ++ dev_err(&pdev->dev, "Error: Init gmac class failed\n"); ++ goto fops_init_err; ++ } ++#endif ++ ++ dev_dbg(&pdev->dev, "%s() SUCCESS\n", __func__); ++ ++ return 0; ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++fops_init_err: ++ sunxi_gmac_sysfs_destroy(&pdev->dev); ++#endif ++init_dma_desc_err: ++ unregister_netdev(ndev); ++register_err: ++ netif_napi_del(&chip->napi); ++ sunxi_gmac_hardware_deinit(pdev); ++hardware_init_err: ++ sunxi_gmac_resource_put(pdev); ++resource_get_err: ++ platform_set_drvdata(pdev, NULL); ++ free_netdev(ndev); ++alloc_etherdev_err: ++ return ret; ++} ++ ++static void sunxi_gmac_remove(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct sunxi_gmac *chip = netdev_priv(ndev); ++ ++#if IS_ENABLED(CONFIG_SUNXI55I_GMAC_METADATA) ++ sunxi_gmac_fops_exit(chip); ++#endif ++ sunxi_gmac_sysfs_destroy(&pdev->dev); ++ sunxi_gmac_dma_desc_deinit(chip); ++ unregister_netdev(ndev); ++ netif_napi_del(&chip->napi); ++ sunxi_gmac_hardware_deinit(pdev); ++ sunxi_gmac_resource_put(pdev); ++ platform_set_drvdata(pdev, NULL); ++ free_netdev(ndev); ++} ++ ++static struct platform_driver sunxi_gmac_driver = { ++ .probe = sunxi_gmac_probe, ++ .remove = sunxi_gmac_remove, ++#if IS_ENABLED(CONFIG_SUNXI55I_EPHY) ++ .shutdown = sunxi_gmac_shutdown, ++#endif /* CONFIG_SUNXI55I_EPHY */ ++ .driver = { ++ .name = "sunxi-gmac", ++ .owner = THIS_MODULE, ++ .pm = &sunxi_gmac_pm_ops, ++ .of_match_table = sunxi_gmac_of_match, ++ }, ++}; ++module_platform_driver(sunxi_gmac_driver); ++ ++#ifndef MODULE ++static int __init sunxi_gmac_set_mac_addr(char *str) ++{ ++ char *p = str; ++ ++ /** ++ * mac address: xx:xx:xx:xx:xx:xx ++ * The reason why memcpy 18 bytes is ++ * the `/0`. ++ */ ++ if (str && strlen(str)) ++ memcpy(mac_str, p, MAC_ADDR_LEN); ++ ++ return 0; ++} ++/* TODO: When used more than one mac, ++ * parsing the mac address becomes a problem. ++ * Maybe use this way: mac0_addr=, mac1_addr= ++ */ ++__setup("mac0_addr=", sunxi_gmac_set_mac_addr); ++#endif /* MODULE */ ++ ++MODULE_DESCRIPTION("Allwinner GMAC driver"); ++MODULE_AUTHOR("xuminghui "); ++MODULE_AUTHOR("Piotr Oniszczuk "); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_VERSION(SUNXI_GMAC_MODULE_VERSION); +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-mdio.c linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-mdio.c +--- linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-mdio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/gmac/sunxi-mdio.c 2024-12-11 14:37:13.080084379 +0100 +@@ -0,0 +1,434 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved. */ ++/* ++ * Allwinner GMAC MDIO interface driver ++ * ++ * Copyright 2022 Allwinnertech ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++/* #define DEBUG */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SUNXI_MDIO_CONFIG 0x0 ++#define SUNXI_MDIO_DATA 0x4 ++ ++#define SUNXI_MDIO_BUSY 0x00000001 ++#define SUNXI_MDIO_WRITE 0x00000002 ++#define SUNXI_MDIO_PHY_MASK 0x0000FFC0 ++#define SUNXI_MDIO_CR_MASK 0x0000001 ++#define SUNXI_MDIO_CLK 0x00000008 ++#define SUNXI_MDIO_MDC_DIV 0x3 ++ ++/* bits 4 3 2 | AHB1 Clock | MDC Clock ++ * ------------------------------------------------------- ++ * 0 0 0 | 60 ~ 100 MHz | div-42 ++ * 0 0 1 | 100 ~ 150 MHz | div-62 ++ * 0 1 0 | 20 ~ 35 MHz | div-16 ++ * 0 1 1 | 35 ~ 60 MHz | div-26 ++ * 1 0 0 | 150 ~ 250 MHz | div-102 ++ * 1 0 1 | 250 ~ 300 MHz | div-124 ++ * 1 1 x | Reserved | ++ */ ++#define SUNXI_MDIO_MDC_DIV_RATIO_M 0x07 ++#define SUNXI_MDIO_MDC_DIV_RATIO_M_BIT 20 ++#define SUNXI_MDIO_PHY_ADDR 0x0001F000 ++#define SUNXI_MDIO_PHY_ADDR_OFFSET 12 ++#define SUNXI_MDIO_PHY_REG 0x000007F0 ++#define SUNXI_MDIO_PHY_REG_OFFSET 4 ++#define SUNXI_MDIO_RESET 0x4 ++#define SUNXI_MDIO_RESET_OFFSET 2 ++ ++#define SUNXI_MDIO_WR_TIMEOUT 10 /* ms */ ++ ++struct mii_reg_dump { ++ u32 addr; ++ u16 reg; ++ u16 value; ++}; ++ ++struct sunxi_mdio { ++ struct device *dev; ++ void __iomem *base; ++}; ++ ++struct mii_reg_dump mii_reg; ++/** ++ * sunxi_parse_read_str - parse the input string for write attri. ++ * @str: string to be parsed, eg: "0x00 0x01". ++ * @addr: store the reg address. eg: 0x00. ++ * @reg: store the expect value. eg: 0x01. ++ * ++ * return 0 if success, otherwise failed. ++ */ ++static int sunxi_parse_read_str(char *str, u16 *addr, u16 *reg) ++{ ++ char *ptr = str; ++ char *tstr = NULL; ++ int ret; ++ ++ /* ++ * Skip the leading whitespace, find the true split symbol. ++ * And it must be 'address value'. ++ */ ++ tstr = strim(str); ++ ptr = strchr(tstr, ' '); ++ if (!ptr) ++ return -EINVAL; ++ ++ /* ++ * Replaced split symbol with a %NUL-terminator temporary. ++ * Will be fixed at end. ++ */ ++ *ptr = '\0'; ++ ret = kstrtos16(tstr, 16, addr); ++ if (ret) ++ goto out; ++ ++ ret = kstrtos16(skip_spaces(ptr + 1), 16, reg); ++ ++out: ++ return ret; ++} ++ ++/** ++ * sunxi_parse_write_str - parse the input string for compare attri. ++ * @str: string to be parsed, eg: "0x00 0x11 0x11". ++ * @addr: store the address. eg: 0x00. ++ * @reg: store the reg. eg: 0x11. ++ * @val: store the value. eg: 0x11. ++ * ++ * return 0 if success, otherwise failed. ++ */ ++static int sunxi_parse_write_str(char *str, u16 *addr, ++ u16 *reg, u16 *val) ++{ ++ u16 result_addr[3] = { 0 }; ++ char *ptr = str; ++ char *ptr2 = NULL; ++ int i, ret = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(result_addr); i++) { ++ ptr = skip_spaces(ptr); ++ ptr2 = strchr(ptr, ' '); ++ if (ptr2) ++ *ptr2 = '\0'; ++ ++ ret = kstrtou16(ptr, 16, &result_addr[i]); ++ ++ if (!ptr2 || ret) ++ break; ++ ++ ptr = ptr2 + 1; ++ } ++ ++ *addr = result_addr[0]; ++ *reg = result_addr[1]; ++ *val = result_addr[2]; ++ ++ return ret; ++} ++ ++/* ++ * Wait until any existing MII operation is complete ++ * Read 0 indicate finish in read or write operation ++ * Read 1 indicate busy ++ * */ ++static void sunxi_mdio_busy_wait(struct sunxi_mdio *chip) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(SUNXI_MDIO_WR_TIMEOUT); ++ u32 reg; ++ ++ do { ++ reg = readl(chip->base + SUNXI_MDIO_CONFIG); ++ ++ if ((reg & SUNXI_MDIO_BUSY) != 1) ++ break; ++ ++ } while (time_before(jiffies, timeout)); ++} ++ ++/** ++ * sunxi_mdio_read - GMAC MII bus read func ++ * @bus: mii bus struct ++ * @phyaddr: phy address ++ * @phyreg: phy register ++ * ++ * Called when phy_write is used. ++ * ++ * Returns reg value for specific phy register. ++ */ ++static int sunxi_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) ++{ ++ unsigned int value = 0; ++ struct sunxi_mdio *chip = bus->priv; ++ ++ /* Mask the MDC_DIV_RATIO */ ++ value |= ((SUNXI_MDIO_MDC_DIV & SUNXI_MDIO_MDC_DIV_RATIO_M) << SUNXI_MDIO_MDC_DIV_RATIO_M_BIT); ++ value |= (((phyaddr << SUNXI_MDIO_PHY_ADDR_OFFSET) & (SUNXI_MDIO_PHY_ADDR)) | ++ ((phyreg << SUNXI_MDIO_PHY_REG_OFFSET) & (SUNXI_MDIO_PHY_REG)) | ++ SUNXI_MDIO_BUSY); ++ ++ writel(value, chip->base + SUNXI_MDIO_CONFIG); ++ ++ sunxi_mdio_busy_wait(chip); ++ ++ return (int)readl(chip->base + SUNXI_MDIO_DATA); ++} ++ ++/** ++ * sunxi_mdio_write - GMAC MII bus write func ++ * @bus: mii bus struct ++ * @phyaddr: phy address ++ * @phyreg: phy register ++ * @data: the value to be written to the register ++ * ++ * Called when phy_wirte is used. ++ * ++ * Returns 0 for a successful open, or appropriate error code ++ */ ++static int sunxi_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, unsigned short data) ++{ ++ unsigned int value; ++ struct sunxi_mdio *chip = bus->priv; ++ ++ value = ((SUNXI_MDIO_MDC_DIV_RATIO_M << SUNXI_MDIO_MDC_DIV_RATIO_M_BIT) & readl(chip->base+ SUNXI_MDIO_CONFIG)) | ++ (SUNXI_MDIO_MDC_DIV << SUNXI_MDIO_MDC_DIV_RATIO_M_BIT); ++ value |= (((phyaddr << SUNXI_MDIO_PHY_ADDR_OFFSET) & (SUNXI_MDIO_PHY_ADDR)) | ++ ((phyreg << SUNXI_MDIO_PHY_REG_OFFSET) & (SUNXI_MDIO_PHY_REG))) | ++ SUNXI_MDIO_WRITE | SUNXI_MDIO_BUSY; ++ ++ sunxi_mdio_busy_wait(chip); ++ ++ /* Set the MII address register to write */ ++ writel(data, chip->base + SUNXI_MDIO_DATA); ++ writel(value, chip->base + SUNXI_MDIO_CONFIG); ++ ++ sunxi_mdio_busy_wait(chip); ++ ++ return 0; ++} ++ ++static int sunxi_mdio_reset(struct mii_bus *bus) ++{ ++ struct sunxi_mdio *chip = bus->priv; ++ ++ writel((SUNXI_MDIO_RESET << SUNXI_MDIO_RESET_OFFSET), chip->base + SUNXI_MDIO_CONFIG); ++ ++ sunxi_mdio_busy_wait(chip); ++ return 0; ++} ++ ++static ssize_t sunxi_mdio_read_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ ++ mii_reg.value = sunxi_mdio_read(bus, mii_reg.addr, mii_reg.reg); ++ return sprintf(buf, "ADDR[0x%02x]:REG[0x%02x] = 0x%04x\n", ++ mii_reg.addr, mii_reg.reg, mii_reg.value); ++} ++ ++static ssize_t sunxi_mdio_read_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ int ret = 0; ++ u16 reg, addr; ++ char *ptr; ++ ++ ptr = (char *)buf; ++ ++ if (!dev) { ++ pr_err("Argment is invalid\n"); ++ return count; ++ } ++ ++ ret = sunxi_parse_read_str(ptr, &addr, ®); ++ if (ret) ++ return ret; ++ ++ mii_reg.addr = addr; ++ mii_reg.reg = reg; ++ ++ return count; ++} ++ ++static ssize_t sunxi_mdio_write_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct platform_device *pdev = to_platform_device(dev); ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ u16 bef_val, aft_val; ++ ++ bef_val = sunxi_mdio_read(bus, mii_reg.addr, mii_reg.reg); ++ sunxi_mdio_write(bus, mii_reg.addr, mii_reg.reg, mii_reg.value); ++ aft_val = sunxi_mdio_read(bus, mii_reg.addr, mii_reg.reg); ++ return sprintf(buf, "before ADDR[0x%02x]:REG[0x%02x] = 0x%04x\n" ++ "after ADDR[0x%02x]:REG[0x%02x] = 0x%04x\n", ++ mii_reg.addr, mii_reg.reg, bef_val, ++ mii_reg.addr, mii_reg.reg, aft_val); ++} ++ ++static ssize_t sunxi_mdio_write_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ int ret = 0; ++ u16 reg, addr, val; ++ char *ptr; ++ ++ ptr = (char *)buf; ++ ++ ret = sunxi_parse_write_str(ptr, &addr, ®, &val); ++ if (ret) ++ return ret; ++ ++ mii_reg.reg = reg; ++ mii_reg.addr = addr; ++ mii_reg.value = val; ++ ++ return count; ++} ++ ++static DEVICE_ATTR(mii_read, 0664, sunxi_mdio_read_show, sunxi_mdio_read_store); ++static DEVICE_ATTR(mii_write, 0664, sunxi_mdio_write_show, sunxi_mdio_write_store); ++ ++static void sunxi_mdio_sysfs_create(struct device *dev) ++{ ++ device_create_file(dev, &dev_attr_mii_read); ++ device_create_file(dev, &dev_attr_mii_write); ++} ++ ++static void sunxi_mdio_sysfs_destroy(struct device *dev) ++{ ++ device_remove_file(dev, &dev_attr_mii_read); ++ device_remove_file(dev, &dev_attr_mii_write); ++} ++/** ++ * sunxi_mdio_probe - GMAC MII bus probe func ++ * ++ * sunxi mdio probe must run after sunxi emac probe, ++ * because mdio clk was enabled in emac driver. ++ */ ++static int sunxi_mdio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device *dev = &pdev->dev; ++ struct mii_bus *bus; ++ struct sunxi_mdio *chip; ++ int ret; ++#ifdef DEBUG ++ struct phy_device *phy; ++ int addr; ++#endif ++ ++ dev_dbg(dev, "%s() BEGIN\n", __func__); ++ ++ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); ++ if (!chip) ++ return -ENOMEM; ++ ++ bus = mdiobus_alloc_size(sizeof(*bus)); ++ if (!bus) { ++ dev_err(dev, "Error: alloc mii bus failed\n"); ++ return -ENOMEM; ++ } ++ ++ bus->name = dev_name(dev); ++ bus->read = sunxi_mdio_read; ++ bus->write = sunxi_mdio_write; ++ bus->reset = sunxi_mdio_reset; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(&pdev->dev)); ++ bus->parent = &pdev->dev; ++ bus->priv = chip; ++ ++ chip->dev = dev; ++ chip->base = of_iomap(np, 0); ++ if (IS_ERR(chip->base)) { ++ ret = PTR_ERR(chip->base); ++ goto iomap_err; ++ } ++ ++ ret = of_mdiobus_register(bus, np); ++ if (ret < 0) ++ goto mdio_register_err; ++ ++ platform_set_drvdata(pdev, bus); ++ ++ sunxi_mdio_sysfs_create(dev); ++ ++#ifdef DEBUG ++ /* scan and dump the bus */ ++ for (addr = 0; addr < PHY_MAX_ADDR; addr++) { ++ phy = mdiobus_get_phy(bus, addr); ++ if (phy) ++ dev_info(dev, "PHY ID: 0x%08x, ADDR: 0x%x, DEVICE: %s, DRIVER: %s\n", ++ phy->phy_id, addr, phydev_name(phy), ++ phy->drv ? phy->drv->name : "Generic PHY"); ++ } ++#endif ++ ++ dev_dbg(dev, "%s() SUCCESS\n", __func__); ++ return 0; ++ ++mdio_register_err: ++ iounmap(chip->base); ++iomap_err: ++ mdiobus_free(bus); ++ return ret; ++} ++ ++static void sunxi_mdio_remove(struct platform_device *pdev) ++{ ++ struct mii_bus *bus = platform_get_drvdata(pdev); ++ struct device *dev = &pdev->dev; ++ struct sunxi_mdio *chip = bus->priv; ++ ++ sunxi_mdio_sysfs_destroy(dev); ++ mdiobus_unregister(bus); ++ iounmap(chip->base); ++ mdiobus_free(bus); ++} ++ ++static const struct of_device_id sunxi_mdio_dt_ids[] = { ++ { .compatible = "allwinner,sunxi-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sunxi_mdio_dt_ids); ++ ++static struct platform_driver sunxi_mdio_driver = { ++ .probe = sunxi_mdio_probe, ++ .remove = sunxi_mdio_remove, ++ .driver = { ++ .name = "sunxi-mdio", ++ .of_match_table = sunxi_mdio_dt_ids, ++ }, ++}; ++ ++static int __init sunxi_mdio_init(void) ++{ ++ return platform_driver_register(&sunxi_mdio_driver); ++} ++late_initcall(sunxi_mdio_init); ++ ++static void __exit sunxi_mdio_exit(void) ++{ ++ platform_driver_unregister(&sunxi_mdio_driver); ++} ++module_exit(sunxi_mdio_exit); ++ ++MODULE_DESCRIPTION("Allwinner GMAC MDIO interface driver"); ++MODULE_AUTHOR("xuminghui "); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0.1"); +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig +--- linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig 2025-01-23 10:27:54.404056276 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/Kconfig 2025-01-23 09:26:21.877290265 +0100 +@@ -35,5 +35,6 @@ + will be called sun4i-emac. + + source "drivers/net/ethernet/allwinner/gmac-200/Kconfig" ++source "drivers/net/ethernet/allwinner/gmac/Kconfig" + + endif # NET_VENDOR_ALLWINNER +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/drivers/net/ethernet/allwinner/Makefile linux-6.12.10/drivers/net/ethernet/allwinner/Makefile +--- linux-6.12.10/drivers/net/ethernet/allwinner/Makefile 2025-01-23 10:27:54.404056276 +0100 ++++ linux-6.12.10/drivers/net/ethernet/allwinner/Makefile 2025-01-23 09:28:49.753960900 +0100 +@@ -5,3 +5,4 @@ + + obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o + obj-$(CONFIG_NET_VENDOR_ALLWINNER) += gmac-200/ ++obj-$(CONFIG_NET_VENDOR_ALLWINNER) += gmac/ diff --git a/patch/kernel/archive/sunxi-dev-6.14/1151-arm64-dtsi-allwinner-add-gmac1-in-A523-dtsi.patch b/patch/kernel/archive/sunxi-dev-6.14/1151-arm64-dtsi-allwinner-add-gmac1-in-A523-dtsi.patch new file mode 100644 index 000000000..72b2877d9 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/1151-arm64-dtsi-allwinner-add-gmac1-in-A523-dtsi.patch @@ -0,0 +1,99 @@ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.4/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi linux-6.12.4/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +--- linux-6.12.4/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi 2024-12-17 16:00:39.127051177 +0100 ++++ linux-6.12.4/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi 2024-12-18 12:33:17.756857967 +0100 +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -110,6 +112,28 @@ + allwinner,pinmux = <2>; + function = "uart0"; + }; ++ ++ /omit-if-no-ref/ ++ gmac1_pins_default: gmac1@0 { ++ pins = "PJ0", "PJ1", "PJ2", "PJ3", ++ "PJ4", "PJ5", "PJ6", "PJ7", ++ "PJ8", "PJ9", "PJ10", "PJ11", ++ "PJ12","PJ13", "PJ14", "PJ15"; ++ allwinner,pinmux = <5>; ++ function = "gmac1"; ++ drive-strength = <40>; ++ bias-pull-up; ++ }; ++ ++ /omit-if-no-ref/ ++ gmac1_pins_sleep: gmac1@1 { ++ pins = "PJ0", "PJ1", "PJ2", "PJ3", ++ "PJ4", "PJ5", "PJ6", "PJ7", ++ "PJ8", "PJ9", "PJ10", "PJ11", ++ "PJ12","PJ13", "PJ14", "PJ15"; ++ allwinner,pinmux = <0>; ++ function = "gpio_in"; ++ }; + }; + + ccu: clock@2001000 { +@@ -380,5 +404,58 @@ + clock-names = "bus", "hosc", "ahb"; + #clock-cells = <1>; + }; ++ ++ gmac1: ethernet@4510000 { ++ compatible = "allwinner,sunxi-gmac-200", "snps,dwmac-4.20a"; ++ reg = <0x04510000 0x10000>, ++ <0x03000034 0x4>; ++ interrupts = ; ++ interrupt-names = "macirq"; ++ clocks = <&ccu CLK_BUS_EMAC1>, <&ccu CLK_MBUS_EMAC1>, <&ccu CLK_EMAC1_25M>; ++ clock-names = "stmmaceth", "pclk", "phy25m"; ++ resets = <&ccu RST_BUS_EMAC1>; ++ reset-names = "stmmaceth"; ++ phy-handle = <&gmac1_phy0>; ++ //todo power-domains = <&pd1 A523_PCK_VO1>; ++ status = "disabled"; ++ ++ snps,fixed-burst; ++ ++ snps,axi-config = <&gmac1_stmmac_axi_setup>; ++ snps,mtl-rx-config = <&gmac1_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac1_mtl_tx_setup>; ++ ++ gmac1_stmmac_axi_setup: stmmac-axi-config { ++ snps,wr_osr_lmt = <0xf>; ++ snps,rd_osr_lmt = <0xf>; ++ snps,blen = <256 128 64 32 16 8 4>; ++ }; ++ ++ gmac1_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ ++ gmac1_mtl_tx_setup: tx_queues-config { ++ snps,tx-queues-to-use = <1>; ++ queue0 {}; ++ }; ++ ++ mdio1: mdio1@1 { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ gmac1_phy0: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0x1>; ++ max-speed = <1000>; /* Max speed capability */ ++ reset-gpios = <&pio 9 27 GPIO_ACTIVE_LOW>; /* PJ27; 9 is PJ */ ++ /* PHY datasheet rst time */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++ }; ++ }; + }; + }; diff --git a/patch/kernel/archive/sunxi-dev-6.14/1152-arm64-dtsi-allwinner-add-gmac0-in-A523-dtsi.patch b/patch/kernel/archive/sunxi-dev-6.14/1152-arm64-dtsi-allwinner-add-gmac0-in-A523-dtsi.patch new file mode 100644 index 000000000..48f5b366c --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/1152-arm64-dtsi-allwinner-add-gmac0-in-A523-dtsi.patch @@ -0,0 +1,69 @@ +diff --speed-large-files --no-dereference --minimal -Naur linux-6.12.10/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi linux-6.12.10/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +--- linux-6.12.10/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi 2025-01-22 15:45:11.961240491 +0100 ++++ linux-6.12.10/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi 2025-01-22 13:16:06.127667018 +0100 +@@ -159,6 +159,28 @@ + allwinner,pinmux = <2>; + function = "uart0"; + }; ++ ++ /omit-if-no-ref/ ++ gmac0_pins_default: gmac0@0 { ++ pins = "PH0", "PH1", "PH2", "PH3", ++ "PH4", "PH5", "PH6", "PH7", ++ "PH9", "PH10","PH13","PH14", ++ "PH15","PH16","PH17","PH18"; ++ allwinner,pinmux = <5>; ++ function = "gmac0"; ++ drive-strength = <40>; ++ bias-pull-up; ++ }; ++ ++ /omit-if-no-ref/ ++ gmac0_pins_sleep: gmac0@1 { ++ pins = "PH0", "PH1", "PH2", "PH3", ++ "PH4", "PH5", "PH6", "PH7", ++ "PH9", "PH10","PH13","PH14", ++ "PH15","PH16","PH17","PH18"; ++ allwinner,pinmux = <0>; ++ function = "gpio_in"; ++ }; + + /omit-if-no-ref/ + gmac1_pins_default: gmac1@0 { +@@ -610,6 +632,36 @@ + #clock-cells = <1>; + }; + ++ mdio0: mdio0@4500048 { ++ compatible = "allwinner,sunxi-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x04500048 0x8>; ++ status = "disabled"; ++ ++ gmac0_phy0: ethernet-phy@1 { ++ reg = <1>; ++ max-speed = <1000>; /* Max speed capability */ ++ reset-gpios = <&pio 7 19 GPIO_ACTIVE_LOW>; /* PH19 */ ++ /* PHY datasheet rst time */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++ }; ++ ++ gmac0: gmac0@4500000 { ++ compatible = "allwinner,sunxi-gmac"; ++ reg = <0x04500000 0x10000>, ++ <0x03000030 0x4>; ++ interrupts = ; ++ interrupt-names = "gmacirq"; ++ clocks = <&ccu CLK_BUS_EMAC0>, <&ccu CLK_EMAC0_25M>; ++ clock-names = "gmac", "phy25m"; ++ resets = <&ccu RST_BUS_EMAC0>; ++ phy-handle = <&gmac0_phy0>; ++ status = "disabled"; ++ }; ++ + gmac1: ethernet@4510000 { + compatible = "allwinner,sunxi-gmac-200", "snps,dwmac-4.20a"; + reg = <0x04510000 0x10000>, diff --git a/patch/kernel/archive/sunxi-dev-6.14/fix-leds-ethernets.patch b/patch/kernel/archive/sunxi-dev-6.14/fix-leds-ethernets.patch new file mode 100644 index 000000000..98712bb07 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/fix-leds-ethernets.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: John Doe +Date: Sat, 15 Mar 2025 20:51:03 -0300 +Subject: PATCH drivers: net: ethernet: stmmac: add yt8531c led fixup + +Signed-off-by: John Doe +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 71 ++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index c8cf84fa4091..737cbcb2088b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -60,10 +60,18 @@ + PTP_TCR_TSCTRLSSR) + + #define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16) + #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) + ++#define YT8531C_PHY_ID 0x4f51e91b ++#define YT8531C_PHY_ID_MASK 0x001fffff ++#define REG_DEBUG_ADDR_OFFSET 0x1e ++#define REG_DEBUG_DATA 0x1f ++ ++#define YT8531C_EXTREG_LED1 0xA00D ++#define YT8531C_EXTREG_LED2 0xA00E ++ + /* Module parameters */ + #define TX_TIMEO 5000 + static int watchdog = TX_TIMEO; + module_param(watchdog, int, 0644); + MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)"); +@@ -7395,10 +7403,67 @@ static int stmmac_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp) + + static const struct xdp_metadata_ops stmmac_xdp_metadata_ops = { + .xmo_rx_timestamp = stmmac_xdp_rx_timestamp, + }; + ++static int ytphy_read_ext(struct phy_device *phydev, u32 regnum) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = __phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); ++ if (ret < 0) ++ goto err_handle; ++ ++ ret = __phy_read(phydev, REG_DEBUG_DATA); ++ if (ret < 0) ++ goto err_handle; ++ ++err_handle: ++ phy_unlock_mdio_bus(phydev); ++ return ret; ++} ++ ++static int ytphy_write_ext(struct phy_device *phydev, u32 regnum, u16 val) ++{ ++ int ret; ++ ++ phy_lock_mdio_bus(phydev); ++ ret = __phy_write(phydev, REG_DEBUG_ADDR_OFFSET, regnum); ++ if (ret < 0) ++ goto err_handle; ++ ++ ret = __phy_write(phydev, REG_DEBUG_DATA, val); ++ if (ret < 0) ++ goto err_handle; ++ ++err_handle: ++ phy_unlock_mdio_bus(phydev); ++ return ret; ++} ++ ++static int phy_yt8531c_led_fixup(struct phy_device *phydev) ++{ ++ int ret; ++ int val; ++ ++ val = ytphy_read_ext(phydev, YT8531C_EXTREG_LED1); ++ if (val < 0) ++ return val; ++ val = 0x1e00; /* 10/100/1000Mbps blink*/ ++ ret = ytphy_write_ext(phydev, YT8531C_EXTREG_LED1, val); ++ if (ret < 0) ++ return ret; ++ ++ val = ytphy_read_ext(phydev, YT8531C_EXTREG_LED2); ++ if (val < 0) ++ return val; ++ val = 0x1800; /* 10/100/1000Mbps light*/ ++ ret = ytphy_write_ext(phydev, YT8531C_EXTREG_LED2, val); ++ return ret; ++} ++ + /** + * stmmac_dvr_probe + * @device: device pointer + * @plat_dat: platform data pointer + * @res: stmmac resource pointer +@@ -7704,10 +7769,16 @@ int stmmac_dvr_probe(struct device *device, + /* Let pm_runtime_put() disable the clocks. + * If CONFIG_PM is not enabled, the clocks will stay powered. + */ + pm_runtime_put(device); + ++ /* Register fixup for PHY YT8531C */ ++ ret = phy_register_fixup_for_uid(YT8531C_PHY_ID, YT8531C_PHY_ID_MASK, phy_yt8531c_led_fixup); ++ if (ret) { ++ dev_warn(priv->device, "Failed to register fixup for PHY YT8531C.\n"); ++ } ++ + return ret; + + error_netdev_register: + phylink_destroy(priv->phylink); + error_phy_setup: +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.14/update-cubie-a5e-dts.patch b/patch/kernel/archive/sunxi-dev-6.14/update-cubie-a5e-dts.patch new file mode 100644 index 000000000..ba4604bfc --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.14/update-cubie-a5e-dts.patch @@ -0,0 +1,161 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: John Doe +Date: Sat, 15 Mar 2025 17:18:05 -0300 +Subject: Patch sun55i-a527-radxa-a5e.dts Add gmac0/1 wifi + +Signed-off-by: John Doe +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts | 99 ++++++++++ + 1 file changed, 99 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts +index 912e1bda974c..8cf16035796e 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-radxa-a5e.dts +@@ -11,16 +11,38 @@ / { + model = "Radxa A5E"; + compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527"; + + aliases { + serial0 = &uart0; ++ mmc0 = &mmc0; ++ mmc1 = &mmc1; ++ mmc2 = &mmc2; ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ ethernet2 = &wlan; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "radxa:green:power"; ++ gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */ ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led-1 { ++ label = "radxa:blue:user"; ++ gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */ ++ linux,default-trigger = "default-on"; ++ }; ++ }; ++ + ext_osc32k: ext-osc32k-clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; +@@ -42,10 +64,20 @@ reg_usb_vbus: vbus { + regulator-max-microvolt = <5000000>; + vin-supply = <®_vcc5v>; + gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ + enable-active-high; + }; ++ ++ reg_3v3_wifi: 3v3-wifi { ++ compatible = "regulator-fixed"; ++ regulator-name = "3v3-wifi"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <®_vcc5v>; ++ gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */ ++ enable-active-high; ++ }; + }; + + &ehci0 { + status = "okay"; + }; +@@ -59,10 +91,27 @@ &mmc0 { + cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; /* PF6 */ + bus-width = <4>; + status = "okay"; + }; + ++&mmc1_pins { ++ drive-strength = <40>; ++}; ++ ++&mmc1 { ++ vmmc-supply = <®_3v3_wifi>; ++ bus-width = <4>; ++ non-removable; ++ // todo: investigate why clock above 40MHz makes data errors ++ max-frequency = <35000000>; ++ status = "okay"; ++ ++ wlan: wifi@1 { ++ reg = <1>; ++ }; ++}; ++ + &ohci0 { + status = "okay"; + }; + + &ohci1 { +@@ -295,5 +344,55 @@ &usb_otg { + &usbphy { + usb0_vbus-supply = <®_vcc5v>; + usb1_vbus-supply = <®_usb_vbus>; + status = "okay"; + }; ++ ++&gmac0 { ++ phy-mode = "rgmii"; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&gmac0_pins_default>; ++ pinctrl-1 = <&gmac0_pins_sleep>; ++ sunxi,phy-clk-type = <0>; ++ tx-delay = <2>; ++ rx-delay = <4>; ++ gmac3v3-supply = <®_cldo3>; ++ status = "okay"; ++}; ++ ++&mdio0 { ++ compatible = "allwinner,sunxi-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x04500048 0x8>; ++ status = "okay"; ++ ++ gmac0_phy0: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0x1>; ++ reset-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++}; ++ ++&gmac1 { ++ phy-mode = "rgmii"; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&gmac1_pins_default>; ++ pinctrl-1 = <&gmac1_pins_sleep>; ++ aw,soc-phy25m; ++ tx-delay = <3>; ++ rx-delay = <4>; ++ dwmac3v3-supply = <®_cldo3>; ++ status = "okay"; ++ ++ mdio1: mdio1@1 { ++ gmac1_phy0: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0x1>; ++ reset-gpios = <&pio 9 16 GPIO_ACTIVE_LOW>; /* PJ16 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++ }; ++}; +-- +Created with Armbian build tools https://github.com/armbian/build +