diff options
author | Michal Wilczynski <m.wilczynski@samsung.com> | 2024-10-04 11:15:49 +0200 |
---|---|---|
committer | Michal Wilczynski <m.wilczynski@samsung.com> | 2024-10-04 12:37:22 +0200 |
commit | 2b6d1108a78dd557e2c100e7494b091586094782 (patch) | |
tree | f061e5b0306539d838d9db3de1d6fba295f324ca | |
parent | c342a18d9bb780f7014f3a993c6d6c4680bd671d (diff) | |
download | linux-thead-2b6d1108a78dd557e2c100e7494b091586094782.tar.gz linux-thead-2b6d1108a78dd557e2c100e7494b091586094782.tar.bz2 linux-thead-2b6d1108a78dd557e2c100e7494b091586094782.zip |
wireless: aic8800: Enable LicheePi 4A wireless driver
Ported from the vendor kernel [1].
[1] https://gitee.com/thead-yocto/kernel.git
Change-Id: Ibd067b5ebf33e6206e57b9e45a2e8b1a1c88011f
Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
132 files changed, 81600 insertions, 0 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7555af5195ec..4e68380c22a7 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -42,4 +42,6 @@ source "drivers/net/wireless/legacy/Kconfig" source "drivers/net/wireless/virtual/Kconfig" +source "drivers/net/wireless/aic8800/Kconfig" + endif # WLAN diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 4d7374d567d1..5de2b694bc2d 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/ obj-$(CONFIG_WLAN) += legacy/ obj-$(CONFIG_WLAN) += virtual/ + +obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/ diff --git a/drivers/net/wireless/aic8800/Kconfig b/drivers/net/wireless/aic8800/Kconfig new file mode 100644 index 000000000000..90f674b9f61a --- /dev/null +++ b/drivers/net/wireless/aic8800/Kconfig @@ -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" + 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 --git a/drivers/net/wireless/aic8800/Makefile b/drivers/net/wireless/aic8800/Makefile new file mode 100644 index 000000000000..e410cafee48d --- /dev/null +++ b/drivers/net/wireless/aic8800/Makefile @@ -0,0 +1,81 @@ +obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) += aic8800_btlpm/ +obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/ +obj-$(CONFIG_AIC_WLAN_SUPPORT) += 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 + +ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) +#KDIR = /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel +#ARCH = arm +#CROSS_COMPILE = /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- +KDIR = /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel +ARCH = arm +CROSS_COMPILE = /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR = /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel +#ARCH = arm64 +#CROSS_COMPILE = /home/yaya/E/Rockchip/3399/rk3399-android-10/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) +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_ROCKCHIP2 +endif + + +ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) +KDIR = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9 +ARCH = arm64 +CROSS_COMPILE = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +ccflags-y += -DANDROID_PLATFORM +endif + +ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) +ccflags-y += -DANDROID_PLATFORM +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/ + +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 .tmp_versions/ + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/.gitignore b/drivers/net/wireless/aic8800/aic8800_bsp/.gitignore new file mode 100644 index 000000000000..c3c2d151e157 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/.gitignore @@ -0,0 +1,10 @@ +*.o +*.ko +*.order +*.symvers +*.o.d +*.o.cmd +*.ko.cmd +*.mod +*.mod.c +*.mod.cmd diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/Makefile b/drivers/net/wireless/aic8800/aic8800_bsp/Makefile new file mode 100644 index 000000000000..632435a6b566 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/Makefile @@ -0,0 +1,157 @@ +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_ONE_TXQ = n +CONFIG_DPD = y +CONFIG_FORCE_DPD_CALIB = y +CONFIG_RESV_MEM_SUPPORT = y +CONFIG_AMSDU_RX ?=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_ONE_TXQ) += -DCONFIG_ONE_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 + +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/3399/rk3399-android-10/kernel +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/ +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- +#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel +#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel +#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel +#ARCH ?= arm64 +#CROSS_COMPILE ?= ~/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- +#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/ +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +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/A133/a133-sdk/android/longan/out/kernel/build/ +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.c new file mode 100644 index 000000000000..edc85f2b62d5 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.c @@ -0,0 +1,207 @@ +#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 +}; + +u32 patch_tbl_8800d80[][2] = { + #ifdef USE_5G + {0x00b4, 0xf3010001}, + #else + {0x00b4, 0xf3010000}, + #endif +#if defined(CONFIG_AMSDU_RX) + {0x170, 0x0100000a} +#endif +#if AIC_IRQ_WAKE_FLAG + {0x00000170, 0x0000010a}, //irqf +#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; +} + +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; + 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; + + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM); + if (ret) { + printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num)); + return ret; + } + + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2); + if (ret) { + printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num_2)); + return ret; + } + + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_start), patch_addr); + if (ret) { + printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_start)); + return ret; + } + + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt); + if (ret) { + printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_count)); + return ret; + } + + for (cnt = 0; cnt < patch_cnt; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl_8800d80[cnt][0]+config_base); + if (ret) { + printk("%x write fail\n", start_addr+8*cnt); + return ret; + } + ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl_8800d80[cnt][1]); + if (ret) { + printk("%x write fail\n", start_addr+8*cnt+4); + return ret; + } + } + + if (adap_test){ + int tmp_cnt = patch_cnt + adap_patch_cnt; + for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) { + int tbl_idx = cnt - patch_cnt; + ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, adaptivity_patch_tbl_8800d80[tbl_idx][0]+config_base); + if(ret) { + printk("%x write fail\n", start_addr+8*cnt); + return ret; + } + ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, adaptivity_patch_tbl_8800d80[tbl_idx][1]); + if(ret) { + printk("%x write fail\n", start_addr+8*cnt+4); + return ret; + } + } + } + + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[0]), 0); + if (ret) { + printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret); + return ret; + } + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[1]), 0); + if (ret) { + printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret); + return ret; + } + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[2]), 0); + if (ret) { + printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret); + return ret; + } + ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[3]), 0); + if (ret) { + printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret); + return ret; + } + + return 0; +} + + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.h b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.h new file mode 100644 index 000000000000..20956582620f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.h @@ -0,0 +1,24 @@ +#ifndef _AIC8800D80_COMPAT_H_ +#define _AIC8800D80_COMPAT_H_ + +#include "aicsdio.h" +/*typedef u32 (*array2_tbl_t)[2]; + +typedef uint8_t u8_l; +typedef int8_t s8_l; +typedef bool bool_l; +typedef uint16_t u16_l; +typedef int16_t s16_l; +typedef uint32_t u32_l; +typedef int32_t s32_l; +typedef uint64_t u64_l;*/ + +int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev); +int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev); +int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev); + + +#endif + + + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.c new file mode 100644 index 000000000000..2bbb087ba3da --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.c @@ -0,0 +1,2210 @@ +#include <linux/version.h> +#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 + {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, + 0x00ffca7d, + 0x00ffca88, + 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, + 0x00ffca7d, + 0x00ffca88, + 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 + 0xffca6b, //11 + 0xffca79, //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 + 0xffca6b, //11 + 0xffca79, //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) + +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; + + 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); + + + 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) { + 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; + } + } + } + } + + 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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.h b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.h new file mode 100644 index 000000000000..67074cecfc5f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c new file mode 100644 index 000000000000..586787f8ecda --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c @@ -0,0 +1,2050 @@ +/** + ****************************************************************************** + * + * rwnx_cmds.c + * + * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to + * LMAC FW + * + * Copyright (C) RivieraWaves 2014-2019 + * + ****************************************************************************** + */ + +#include <linux/list.h> +#include <linux/version.h> +#include <linux/delay.h> +#include <linux/vmalloc.h> +#include <linux/firmware.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) +#include <linux/hardirq.h> +#endif +#include <linux/fs.h> +#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 LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +#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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h new file mode 100644 index 000000000000..810ed8e4dbef --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h @@ -0,0 +1,566 @@ +/** + ****************************************************************************** + * + * rwnx_cmds.h + * + * Copyright (C) RivieraWaves 2014-2019 + * + ****************************************************************************** + */ + +#ifndef _AIC_BSP_DRIVER_H +#define _AIC_BSP_DRIVER_H + +#include <linux/spinlock.h> +#include <linux/completion.h> +#include <linux/module.h> +#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" +#define RWNX_MAC_CALIB_NAME_8800DC_H_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_h_u02.bin" + +#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" +#define RWNX_MAC_PATCH_NAME2_8800DC_H_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_h_u02.bin" +#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" +#define RWNX_MAC_PATCH_TABLE_8800DC_H_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_h_u02.bin" + +#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 +#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART +#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 AIC_IRQ_WAKE_FLAG 0 // 0: rising edge, 1: falling edge +#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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h new file mode 100644 index 000000000000..249d6ec082ea --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c new file mode 100644 index 000000000000..5e144c8c1169 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c @@ -0,0 +1,381 @@ +#include <linux/module.h> +#include <linux/inetdevice.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/platform_device.h> +#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; */ +int aicwf_dbg_level_bsp = LOGERROR; +module_param(aicwf_dbg_level_bsp, int, 0660); + +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", + .wl_fw = "fmacfw.bin" + }, + [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" + #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", + .wl_fw = "fmacfw_8800d80_u02.bin" + }, + + [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, + .irqf = AIC_IRQ_WAKE_FLAG, +}; + +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); +#ifdef CONFIG_PLATFORM_ROCKCHIP + 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) +{ +#ifdef CONFIG_PLATFORM_ROCKCHIP + if(aicbsp_sdiodev){ + aicbsp_sdio_exit(); + } +#endif + sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group); + platform_device_del(aicbsp_pdev); + platform_driver_unregister(&aicbsp_driver); + mutex_destroy(&aicbsp_power_lock); + aicbsp_resv_mem_deinit(); +#ifdef CONFIG_PREALLOC_TXQ + aicwf_prealloc_txq_free(); +#endif + printk("%s\n", __func__); +} + +module_init(aicbsp_init); +module_exit(aicbsp_exit); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_VERSION(DRV_VERS_MOD); +MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c new file mode 100644 index 000000000000..e7b3670bc0f5 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c @@ -0,0 +1,2087 @@ +/** + * aicwf_sdmmc.c + * + * SDIO function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/mmc/sdio.h> +#include <linux/mmc/sdio_ids.h> +#include <linux/mmc/sdio_func.h> +#include <linux/mmc/card.h> +#include <linux/mmc/host.h> +#include <linux/semaphore.h> +#include <linux/debugfs.h> +#include <linux/kthread.h> +#include "aicsdio_txrxif.h" +#include "aicsdio.h" +#include "aic_bsp_driver.h" +#include <linux/version.h> +#include <linux/delay.h> +#ifdef CONFIG_PLATFORM_ROCKCHIP +#include <linux/rfkill-wlan.h> +#endif /* CONFIG_PLATFORM_ROCKCHIP */ +#ifdef CONFIG_PLATFORM_ROCKCHIP2 +#include <linux/rfkill-wlan.h> +#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 <linux/amlogic/aml_gpio_consumer.h> +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 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 + +#ifdef CONFIG_PLATFORM_ROCKCHIP +#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 + +#ifdef 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); + + 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; + +#ifdef CONFIG_PLATFORM_ROCKCHIP +#ifdef CONFIG_GPIO_WAKEUP + //BT_SLEEP:true,BT_WAKEUP:false + rfkill_rk_sleep_bt(false); +#endif +#endif + +#ifdef 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; + } + +#ifdef CONFIG_PLATFORM_ROCKCHIP +#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 + +#ifdef 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__); + + 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) { + printk("%s aicbsp_reg_sdio_notify fail(%d)\n", __func__, ret); + return ret; + } + +#ifdef CONFIG_PLATFORM_ALLWINNER + sunxi_wlan_set_power(0); + mdelay(50); + sunxi_wlan_set_power(1); + mdelay(50); + sunxi_mmc_rescan_card(aicbsp_bus_index); +#endif //CONFIG_PLATFORM_ALLWINNER + + if (down_timeout(&aic_chipup_sem, msecs_to_jiffies(2000)) == 0) { + aicbsp_unreg_sdio_notify(); + if (aicbsp_load_fw_in_fdrv) { + printk("%s load fw in fdrv\r\n", __func__); + return -1; + } + return 0; + } + + aicbsp_unreg_sdio_notify(); +#ifdef CONFIG_PLATFORM_ALLWINNER + sunxi_wlan_set_power(0); +#endif //CONFIG_PLATFORM_ALLWINNER + +#ifdef CONFIG_PLATFORM_AMLOGIC + extern_wifi_set_enable(0); +#endif + +#ifdef CONFIG_PLATFORM_ROCKCHIP2 + rockchip_wifi_power(0); +#endif /*CONFIG_PLATFORM_ROCKCHIP2*/ + + return -1; +} + +static void aicbsp_platform_power_off(void) +{ +//TODO wifi disable and sdio card detection +#ifdef CONFIG_PLATFORM_ALLWINNER + if (aicbsp_bus_index < 0) + aicbsp_bus_index = sunxi_wlan_get_bus_index(); + if (aicbsp_bus_index < 0) { + sdio_dbg("no aicbsp_bus_index\n"); + return; + } + sunxi_wlan_set_power(0); + mdelay(100); + sunxi_mmc_rescan_card(aicbsp_bus_index); +#endif //CONFIG_PLATFORM_ALLWINNER + +#ifdef CONFIG_PLATFORM_ROCKCHIP2 + rockchip_wifi_set_carddetect(0); + mdelay(200); + rockchip_wifi_power(0); + mdelay(200); +#endif /*CONFIG_PLATFORM_ROCKCHIP*/ +#ifdef CONFIG_PLATFORM_AMLOGIC + extern_wifi_set_enable(0); +#endif + + sdio_dbg("%s\n", __func__); +} + +int aicbsp_sdio_init(void) +{ + if (sdio_register_driver(&aicbsp_sdio_driver)) { + return -1; + } else { + //may add mmc_rescan here + } + 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 --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h new file mode 100644 index 000000000000..582ba94dfe87 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h @@ -0,0 +1,147 @@ +/** + * aicwf_sdio.h + * + * SDIO function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#ifndef _AICWF_SDMMC_H_ +#define _AICWF_SDMMC_H_ + +#ifdef AICWF_SDIO_SUPPORT +#include <linux/skbuff.h> +#include <linux/if_ether.h> +#include <linux/ieee80211.h> +#include <linux/semaphore.h> +#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; + struct aic_sdio_reg sdio_reg; + void (*sdio_hal_irqhandler) (struct sdio_func *func); +}; + +void *aicbsp_get_drvdata(void *args); +int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); +void aicwf_sdio_hal_irqhandler(struct sdio_func *func); +void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func); +#if defined(CONFIG_SDIO_PWRCTRL) +void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); +int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); +#endif +void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev); +int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); +int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev); +void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); +int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); +int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size, u8 msg); +int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); +void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); +void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); +void aicbsp_sdio_exit(void); +int aicbsp_sdio_init(void); +void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev); +int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); +int aicwf_sdio_bustx_thread(void *data); +int aicwf_sdio_busrx_thread(void *data); +int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); +int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv); +void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); +void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); +extern void aicwf_hostif_ready(void); +int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv); +uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); +#endif /* AICWF_SDIO_SUPPORT */ + +#endif /*_AICWF_SDMMC_H_*/ diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c new file mode 100644 index 000000000000..37297f1b8460 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c @@ -0,0 +1,463 @@ +/** + * aicwf_bus.c + * + * bus function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#include <linux/kthread.h> +#include <linux/netdevice.h> +#include <linux/printk.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/semaphore.h> +#include <linux/debugfs.h> +#include <linux/atomic.h> +#include <linux/vmalloc.h> +#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"); + 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; + struct aic_sdio_dev *sdiodev; + + if (!dev) { + txrx_err("device not found\n"); + return; + } + sdio_dbg("%s", __func__); + bus_if = aicbsp_get_drvdata(dev); + aicwf_bus_stop(bus_if); + + sdiodev = bus_if->bus_priv.sdio; + + if (bus_if->cmd_buf) { + kfree(bus_if->cmd_buf); + bus_if->cmd_buf = NULL; + } + + if (bus_if->bustx_thread) { + complete_all(&bus_if->bustx_trgg); + kthread_stop(bus_if->bustx_thread); + bus_if->bustx_thread = NULL; + } +} + +void aicwf_frame_tx(void *dev, struct sk_buff *skb) +{ + struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev; + aicwf_bus_txdata(sdiodev->bus_if, skb); +} + +struct aicwf_tx_priv *aicwf_tx_init(void *arg) +{ + struct aicwf_tx_priv *tx_priv; + + tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL); + if (!tx_priv) + return NULL; + + tx_priv->sdiodev = (struct aic_sdio_dev *)arg; + + atomic_set(&tx_priv->aggr_count, 0); + tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); + if (!tx_priv->aggr_buf) { + txrx_err("Alloc bus->txdata_buf failed!\n"); + kfree(tx_priv); + return NULL; + } + tx_priv->head = tx_priv->aggr_buf->data; + tx_priv->tail = tx_priv->aggr_buf->data; + + return tx_priv; +} + +void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) +{ + if (tx_priv && tx_priv->aggr_buf) + dev_kfree_skb(tx_priv->aggr_buf); + + kfree(tx_priv); + //tx_priv = NULL; +} + +static bool aicwf_another_ptk(struct sk_buff *skb) +{ + u8 *data; + u16 aggr_len = 0; + + if (skb->data == NULL || skb->len == 0) { + return false; + } + data = skb->data; + aggr_len = (*skb->data | (*(skb->data + 1) << 8)); + if (aggr_len == 0) { + return false; + } + + return true; +} + +int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) +{ + int ret = 0; + unsigned long flags = 0; + struct sk_buff *skb = NULL; + u16 pkt_len = 0; + struct sk_buff *skb_inblock = NULL; + u16 aggr_len = 0, adjust_len = 0; + u8 *data = NULL; + + while (1) { + spin_lock_irqsave(&rx_priv->rxqlock, flags); + if (aicwf_is_framequeue_empty(&rx_priv->rxq)) { + spin_unlock_irqrestore(&rx_priv->rxqlock, flags); + break; + } + skb = aicwf_frame_dequeue(&rx_priv->rxq); + spin_unlock_irqrestore(&rx_priv->rxqlock, flags); + if (skb == NULL) { + txrx_err("skb_error\r\n"); + break; + } + while (aicwf_another_ptk(skb)) { + data = skb->data; + pkt_len = (*skb->data | (*(skb->data + 1) << 8)); + + if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data + aggr_len = pkt_len + RX_HWHRD_LEN; + + if (aggr_len & (RX_ALIGNMENT - 1)) + adjust_len = roundup(aggr_len, RX_ALIGNMENT); + else + adjust_len = aggr_len; + + skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv + if (skb_inblock == NULL) { + txrx_err("no more space!\n"); + aicwf_dev_skb_free(skb); + return -EBADE; + } + + skb_put(skb_inblock, aggr_len); + memcpy(skb_inblock->data, data, aggr_len); + #if 0 + rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv); + #endif + skb_pull(skb, adjust_len); + } else { // type : config + aggr_len = pkt_len; + + if (aggr_len & (RX_ALIGNMENT - 1)) + adjust_len = roundup(aggr_len, RX_ALIGNMENT); + else + adjust_len = aggr_len; + + skb_inblock = __dev_alloc_skb(aggr_len+4, GFP_KERNEL); + if (skb_inblock == NULL) { + txrx_err("no more space!\n"); + aicwf_dev_skb_free(skb); + return -EBADE; + } + + skb_put(skb_inblock, aggr_len+4); + memcpy(skb_inblock->data, data, aggr_len+4); + if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP) + rwnx_rx_handle_msg(rx_priv->sdiodev, (struct ipc_e2a_msg *)(skb_inblock->data + 4)); + #if 0 + if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM) + aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(skb_inblock->data + 4)); + #endif + skb_pull(skb, adjust_len+4); + } + } + + /* skb_inblock no used currently, just free it! */ + dev_kfree_skb(skb_inblock); + dev_kfree_skb(skb); + atomic_dec(&rx_priv->rx_cnt); + } + +#if defined(CONFIG_SDIO_PWRCTRL) + aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST); +#endif + + return ret; +} + +static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize) +{ + int i; + struct recv_msdu *req, *reqs; + + reqs = vmalloc(qsize*sizeof(struct recv_msdu)); + if (reqs == NULL) + return NULL; + + req = reqs; + for (i = 0; i < qsize; i++) { + INIT_LIST_HEAD(&req->rxframe_list); + list_add(&req->rxframe_list, q); + req->len = 0; + req++; + } + + return reqs; +} + +struct aicwf_rx_priv *aicwf_rx_init(void *arg) +{ + struct aicwf_rx_priv *rx_priv; + rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL); + if (!rx_priv) + return NULL; + + rx_priv->sdiodev = (struct aic_sdio_dev *)arg; + aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN); + spin_lock_init(&rx_priv->rxqlock); + atomic_set(&rx_priv->rx_cnt, 0); + + INIT_LIST_HEAD(&rx_priv->rxframes_freequeue); + spin_lock_init(&rx_priv->freeq_lock); + rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME); + if (!rx_priv->recv_frames) { + txrx_err("no enough buffer for free recv frame queue!\n"); + kfree(rx_priv); + return NULL; + } + spin_lock_init(&rx_priv->stas_reord_lock); + INIT_LIST_HEAD(&rx_priv->stas_reord_list); + + return rx_priv; +} + + +static void aicwf_recvframe_queue_deinit(struct list_head *q) +{ + struct recv_msdu *req, *next; + + list_for_each_entry_safe(req, next, q, rxframe_list) { + list_del_init(&req->rxframe_list); + } +} + +void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) +{ + if (rx_priv->sdiodev->bus_if->busrx_thread) { + complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); + kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); + rx_priv->sdiodev->bus_if->busrx_thread = NULL; + } + + aicwf_frame_queue_flush(&rx_priv->rxq); + aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue); + if (rx_priv->recv_frames) + vfree(rx_priv->recv_frames); + + kfree(rx_priv); + //rx_priv = NULL; +} + +bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt) +{ + return aicwf_frame_enq(dev, q, pkt, 0); +} + + +void aicwf_dev_skb_free(struct sk_buff *skb) +{ + if (!skb) + return; + + dev_kfree_skb_any(skb); +} + +static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p) +{ + struct sk_buff_head *q; + + if (pq->queuelist[prio].qlen >= pq->qmax) + return NULL; + + q = &pq->queuelist[prio]; + __skb_queue_tail(q, p); + pq->qcnt++; + if (pq->hi_prio < prio) + pq->hi_prio = (u16)prio; + + return p; +} + +void aicwf_frame_queue_flush(struct frame_queue *pq) +{ + int prio; + struct sk_buff_head *q; + struct sk_buff *p, *next; + + for (prio = 0; prio < pq->num_prio; prio++) { + q = &pq->queuelist[prio]; + skb_queue_walk_safe(q, p, next) { + skb_unlink(p, q); + aicwf_dev_skb_free(p); + pq->qcnt--; + } + } +} + +void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len) +{ + int prio; + + memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio)); + pq->num_prio = (u16)num_prio; + pq->qmax = (u16)max_len; + + for (prio = 0; prio < num_prio; prio++) { + skb_queue_head_init(&pq->queuelist[prio]); + } +} + +struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out) +{ + int prio; + + if (pq->qcnt == 0) + return NULL; + + for (prio = 0; prio < pq->hi_prio; prio++) + if (!skb_queue_empty(&pq->queuelist[prio])) + break; + + if (prio_out) + *prio_out = prio; + + return skb_peek_tail(&pq->queuelist[prio]); +} + +bool aicwf_is_framequeue_empty(struct frame_queue *pq) +{ + int prio, len = 0; + + for (prio = 0; prio <= pq->hi_prio; prio++) + len += pq->queuelist[prio].qlen; + + if (len > 0) + return false; + else + return true; +} + +struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) +{ + struct sk_buff_head *q; + struct sk_buff *p; + int prio; + + if (pq->qcnt == 0) + return NULL; + + while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio])) + pq->hi_prio--; + + q = &pq->queuelist[prio]; + p = __skb_dequeue(q); + if (p == NULL) + return NULL; + + pq->qcnt--; + + return p; +} + +static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) +{ + struct sk_buff_head *q = &pq->queuelist[prio]; + struct sk_buff *p = skb_dequeue_tail(q); + + if (!p) + return NULL; + + pq->qcnt--; + return p; +} + +bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) +{ + struct sk_buff *p = NULL; + int prio_modified = -1; + + if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { + aicwf_frame_queue_penq(q, prio, pkt); + return true; + } + if (q->queuelist[prio].qlen >= q->qmax) { + prio_modified = prio; + } else if (q->qcnt >= q->qmax) { + p = aicwf_frame_queue_peek_tail(q, &prio_modified); + if (prio_modified > prio) + return false; + } + + if (prio_modified >= 0) { + if (prio_modified == prio) + return false; + + p = aicwf_skb_dequeue_tail(q, prio_modified); + aicwf_dev_skb_free(p); + + p = aicwf_frame_queue_penq(q, prio_modified, pkt); + if (p == NULL) + txrx_err("failed\n"); + } + + return p != NULL; +} + + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.h b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.h new file mode 100644 index 000000000000..801e0ea4965c --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.h @@ -0,0 +1,214 @@ +/** + * aicwf_txrxif.h + * + * bus function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#ifndef _AICWF_TXRXIF_H_ +#define _AICWF_TXRXIF_H_ + +#include <linux/skbuff.h> +#include <linux/sched.h> +#include "aicsdio.h" + +#define CMD_BUF_MAX 1536 +#define TXPKT_BLOCKSIZE 512 +#define MAX_AGGR_TXPKT_LEN (1536*4) +#define CMD_TX_TIMEOUT 5000 +#define TX_ALIGNMENT 4 + +#define RX_HWHRD_LEN 60 //58->60 word allined +#define CCMP_OR_WEP_INFO 8 +#define MAX_RXQLEN 2000 +#define RX_ALIGNMENT 4 + +#define DEBUG_ERROR_LEVEL 0 +#define DEBUG_DEBUG_LEVEL 1 +#define DEBUG_INFO_LEVEL 2 + +#define DBG_LEVEL DEBUG_DEBUG_LEVEL + +#define txrx_err(fmt, ...) pr_err("aicbsp: txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define sdio_err(fmt, ...) pr_err("aicbsp: sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#define usb_err(fmt, ...) pr_err("aicbsp: usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__) +#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL +#define sdio_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) +#define usb_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) +#else +#define sdio_dbg(fmt, ...) +#define usb_dbg(fmt, ...) +#endif +#if DBG_LEVEL >= DEBUG_INFO_LEVEL +#define sdio_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) +#define usb_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__) +#else +#define sdio_info(fmt, ...) +#define usb_info(fmt, ...) +#endif + +enum aicwf_bus_state { + BUS_DOWN_ST, + BUS_UP_ST +}; + +struct aicwf_bus_ops { + int (*start) (struct device *dev); + void (*stop) (struct device *dev); + int (*txdata) (struct device *dev, struct sk_buff *skb); + int (*txmsg) (struct device *dev, u8 *msg, uint len); +}; + +struct frame_queue { + u16 num_prio; + u16 hi_prio; + u16 qmax; /* max number of queued frames */ + u16 qcnt; + struct sk_buff_head queuelist[8]; +}; + +struct aicwf_bus { + union { + struct aic_sdio_dev *sdio; + struct aic_usb_dev *usb; + } bus_priv; + struct device *dev; + struct aicwf_bus_ops *ops; + enum aicwf_bus_state state; + u8 *cmd_buf; + struct completion bustx_trgg; + struct completion busrx_trgg; + struct task_struct *bustx_thread; + struct task_struct *busrx_thread; +}; + +struct aicwf_tx_priv { +#ifdef AICWF_SDIO_SUPPORT + struct aic_sdio_dev *sdiodev; + int fw_avail_bufcnt; + //for cmd tx + u8 *cmd_buf; + uint cmd_len; + bool cmd_txstate; + bool cmd_tx_succ; + struct semaphore cmd_txsema; + wait_queue_head_t cmd_txdone_wait; + //for data tx + atomic_t tx_pktcnt; + + struct frame_queue txq; + spinlock_t txqlock; + struct semaphore txctl_sema; +#endif +#ifdef AICWF_USB_SUPPORT + struct aic_usb_dev *usbdev; +#endif + struct sk_buff *aggr_buf; + atomic_t aggr_count; + u8 *head; + u8 *tail; +}; + + +#define MAX_REORD_RXFRAME 250 +#define REORDER_UPDATE_TIME 50 +#define AICWF_REORDER_WINSIZE 64 +#define SN_LESS(a, b) (((a-b)&0x800) != 0) +#define SN_EQUAL(a, b) (a == b) + +struct reord_ctrl { + struct aicwf_rx_priv *rx_priv; + u8 enable; + u16 ind_sn; + u8 wsize_b; + spinlock_t reord_list_lock; + struct list_head reord_list; + struct timer_list reord_timer; + struct work_struct reord_timer_work; +}; + +struct reord_ctrl_info { + u8 mac_addr[6]; + struct reord_ctrl preorder_ctrl[8]; + struct list_head list; +}; + +struct recv_msdu { + struct sk_buff *pkt; + u8 tid; + u16 seq_num; + uint len; + u8 *rx_data; + //for pending rx reorder list + struct list_head reord_pending_list; + //for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue + struct list_head rxframe_list; + struct reord_ctrl *preorder_ctrl; +}; + +struct aicwf_rx_priv { + struct aic_sdio_dev *sdiodev; + void *rwnx_vif; + atomic_t rx_cnt; + u32 data_len; + spinlock_t rxqlock; + struct frame_queue rxq; + + spinlock_t freeq_lock; + struct list_head rxframes_freequeue; + struct list_head stas_reord_list; + spinlock_t stas_reord_lock; + struct recv_msdu *recv_frames; +}; + +static inline int aicwf_bus_start(struct aicwf_bus *bus) +{ + return bus->ops->start(bus->dev); +} + +static inline void aicwf_bus_stop(struct aicwf_bus *bus) +{ + bus->ops->stop(bus->dev); +} + +static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb) +{ + return bus->ops->txdata(bus->dev, skb); +} + +static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len) +{ + return bus->ops->txmsg(bus->dev, msg, len); +} + +static inline void aicwf_sched_timeout(u32 millisec) +{ + ulong timeout = 0, expires = 0; + expires = jiffies + msecs_to_jiffies(millisec); + timeout = millisec; + + while (timeout) { + timeout = schedule_timeout(timeout); + if (time_after(jiffies, expires)) + break; + } +} + +int aicwf_bus_init(uint bus_hdrlen, struct device *dev); +void aicwf_bus_deinit(struct device *dev); +void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv); +void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv); +struct aicwf_tx_priv *aicwf_tx_init(void *arg); +struct aicwf_rx_priv *aicwf_rx_init(void *arg); +void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len); +void aicwf_frame_queue_flush(struct frame_queue *pq); +bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio); +bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt); +bool aicwf_is_framequeue_empty(struct frame_queue *pq); +void aicwf_frame_tx(void *dev, struct sk_buff *skb); +void aicwf_dev_skb_free(struct sk_buff *skb); +struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq); +struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out); + +#endif /* _AICWF_TXRXIF_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.c b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.c new file mode 100644 index 000000000000..77130f76bafa --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.c @@ -0,0 +1,16138 @@ +#include <linux/module.h> + +char fmacfw[259592] = { +0x00, 0x38, 0x18, 0x00, 0x89, 0x01, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA1, 0xCA, 0x12, 0x00, 0xA9, 0xCA, 0x12, 0x00, +0xB1, 0xCA, 0x12, 0x00, 0xB9, 0xCA, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xC6, 0x12, 0x00, +0xA5, 0xC6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0xBB, 0x12, 0x00, 0x19, 0x1E, 0x14, 0x00, 0x35, 0xEE, 0x12, 0x00, +0x49, 0xED, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x79, 0x5C, 0x13, 0x00, 0x49, 0x11, 0x12, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x65, 0x5A, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, +0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x45, 0xED, 0x12, 0x00, 0x7D, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, +0x99, 0x1A, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x99, 0x1A, 0x12, 0x00, +0x00, 0x00, 0x00, 0x00, 0x99, 0x1A, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x79, 0x51, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xCD, 0x5B, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x48, 0x00, 0x68, 0x10, 0xF0, 0x00, 0x4F, +0x0C, 0xBF, 0x04, 0x48, 0x20, 0xF0, 0x7F, 0x40, 0x80, 0xF3, 0x08, 0x88, 0x02, 0x48, 0x00, 0x47, 0x44, 0x01, 0x50, 0x40, +0x00, 0x38, 0x18, 0x00, 0x05, 0xC7, 0x12, 0x00, 0xF0, 0xB4, 0x86, 0x07, 0x46, 0xD0, 0x54, 0x1E, 0x00, 0x2A, 0x3C, 0xD0, +0xCA, 0xB2, 0x03, 0x46, 0x01, 0xE0, 0x01, 0x3C, 0x37, 0xD3, 0x03, 0xF8, 0x01, 0x2B, 0x9D, 0x07, 0xF9, 0xD1, 0x03, 0x2C, +0x2A, 0xD9, 0xCD, 0xB2, 0x45, 0xEA, 0x05, 0x25, 0x0F, 0x2C, 0x45, 0xEA, 0x05, 0x45, 0x34, 0xD9, 0xA4, 0xF1, 0x10, 0x02, +0x22, 0xF0, 0x0F, 0x0C, 0x03, 0xF1, 0x20, 0x07, 0x16, 0x09, 0x67, 0x44, 0x03, 0xF1, 0x10, 0x02, 0x42, 0xE9, 0x04, 0x55, +0x42, 0xE9, 0x02, 0x55, 0x10, 0x32, 0xBA, 0x42, 0xF8, 0xD1, 0x72, 0x1C, 0x14, 0xF0, 0x0C, 0x0F, 0x03, 0xEB, 0x02, 0x12, +0x04, 0xF0, 0x0F, 0x06, 0x13, 0xD0, 0x33, 0x1F, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x42, 0xF8, 0x04, 0x5B, +0x93, 0x42, 0xFB, 0xD1, 0x06, 0xF0, 0x03, 0x04, 0x2C, 0xB1, 0xCA, 0xB2, 0x1C, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x9C, 0x42, +0xFB, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x34, 0x46, 0x13, 0x46, 0x00, 0x2C, 0xF3, 0xD1, 0xF8, 0xE7, 0x14, 0x46, 0x03, 0x46, +0xC1, 0xE7, 0x1A, 0x46, 0x26, 0x46, 0xE0, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x68, 0x91, 0x4F, 0x4F, 0xD9, 0xF8, +0x00, 0x60, 0xDF, 0xF8, 0x64, 0xC1, 0x33, 0x89, 0xD6, 0xF8, 0x34, 0xE0, 0xC7, 0xF8, 0x10, 0xE0, 0xD6, 0xE9, 0x09, 0x10, +0xD6, 0xE9, 0x0B, 0x45, 0x39, 0x60, 0xC9, 0x08, 0x03, 0x29, 0x78, 0x60, 0x4F, 0xEA, 0xD0, 0x00, 0x38, 0xBF, 0x03, 0x21, +0xBC, 0x60, 0x03, 0x28, 0x4F, 0xEA, 0xD4, 0x04, 0x38, 0xBF, 0x03, 0x20, 0xFD, 0x60, 0x03, 0x2C, 0x4F, 0xEA, 0xD5, 0x05, +0x4F, 0xF0, 0x54, 0x02, 0x4F, 0xEA, 0xDE, 0x07, 0x2C, 0xF0, 0x03, 0x0C, 0x38, 0xBF, 0x03, 0x24, 0xDF, 0xF8, 0x1C, 0xE1, +0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0xA1, 0xC8, 0xF8, 0x00, 0x10, 0x03, 0x2D, 0x03, 0xFB, 0x02, 0x22, 0x38, 0xBF, +0x03, 0x25, 0x62, 0x44, 0x03, 0x2F, 0x38, 0xBF, 0x03, 0x27, 0x72, 0x45, 0xC8, 0xE9, 0x01, 0x04, 0xC8, 0xE9, 0x03, 0x57, +0xCA, 0xF8, 0x00, 0xC0, 0x4F, 0xD8, 0x01, 0x33, 0xDF, 0xF8, 0xF4, 0xE0, 0x2E, 0x4A, 0xDF, 0xF8, 0xF4, 0x80, 0xDF, 0xF8, +0xF4, 0x90, 0x4F, 0xF0, 0x58, 0x0C, 0x0C, 0xFB, 0x03, 0xE3, 0xD2, 0xF8, 0x00, 0xC0, 0x2A, 0x4A, 0x13, 0x60, 0x4F, 0xF4, +0xAC, 0x72, 0x02, 0xFB, 0x01, 0x33, 0x02, 0xFB, 0x00, 0x30, 0x02, 0xFB, 0x04, 0x04, 0x02, 0xFB, 0x05, 0x45, 0xDC, 0xF8, +0x00, 0x10, 0xC8, 0xF8, 0x00, 0x50, 0x02, 0xFB, 0x07, 0x52, 0xC9, 0xF8, 0x00, 0x40, 0x21, 0x4F, 0x21, 0x4D, 0x22, 0x4C, +0x38, 0x60, 0x2B, 0x60, 0xC4, 0xF8, 0x00, 0xE0, 0x41, 0xB9, 0xDC, 0xF8, 0x04, 0x30, 0x04, 0x33, 0x11, 0x1D, 0x23, 0xF0, +0x03, 0x03, 0xCC, 0xF8, 0x00, 0x10, 0x1A, 0x44, 0xDC, 0xF8, 0x08, 0x30, 0x13, 0xB9, 0x04, 0x32, 0xCC, 0xF8, 0x08, 0x20, +0x18, 0x4B, 0xF2, 0x68, 0x1A, 0x60, 0x33, 0x78, 0x02, 0x2B, 0x0E, 0xD0, 0x01, 0x2B, 0x01, 0xD0, 0xBD, 0xE8, 0xF0, 0x87, +0x72, 0x69, 0x00, 0x2A, 0xFA, 0xD0, 0x13, 0x49, 0x91, 0x42, 0xF7, 0xD9, 0xBD, 0xE8, 0xF0, 0x47, 0x11, 0x48, 0x05, 0xF0, +0xC1, 0xBF, 0x32, 0x69, 0xF3, 0xE7, 0x71, 0x46, 0x0F, 0x48, 0x05, 0xF0, 0xBB, 0xFF, 0xD9, 0xF8, 0x00, 0x60, 0xD8, 0xF8, +0x00, 0x10, 0x33, 0x89, 0xD8, 0xE9, 0x01, 0x04, 0xD8, 0xE9, 0x03, 0x57, 0x01, 0x33, 0xA1, 0xE7, 0x7C, 0x28, 0x17, 0x00, +0x30, 0x36, 0x17, 0x00, 0xEC, 0x57, 0x18, 0x00, 0xF4, 0x57, 0x18, 0x00, 0xF0, 0x57, 0x18, 0x00, 0x14, 0x63, 0x18, 0x00, +0x00, 0x38, 0x18, 0x00, 0x00, 0x38, 0x18, 0x00, 0x44, 0x76, 0x15, 0x00, 0x18, 0x76, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, +0x2B, 0x07, 0x18, 0x00, 0x00, 0x24, 0x18, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0xE0, 0x9F, 0x18, 0x00, +0xFC, 0x57, 0x18, 0x00, 0xF8, 0x57, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x49, 0x4C, 0x4A, 0x49, 0x4A, 0x4E, 0x4B, 0x4A, +0x4B, 0x4D, 0x4C, 0x48, 0x0C, 0x60, 0x04, 0xF1, 0x44, 0x07, 0x21, 0x1D, 0xD4, 0xF8, 0xD0, 0x30, 0x37, 0x60, 0x04, 0xF1, +0x80, 0x07, 0x11, 0x60, 0x2F, 0x60, 0x47, 0x49, 0x47, 0x4A, 0x04, 0xF1, 0x90, 0x05, 0x23, 0xF0, 0x7F, 0x43, 0x05, 0x60, +0x04, 0xF1, 0xA8, 0x00, 0x08, 0x60, 0x23, 0xF0, 0xFF, 0x03, 0x04, 0xF1, 0xAA, 0x01, 0x11, 0x60, 0x83, 0xB1, 0x94, 0xF8, +0xD1, 0x30, 0x23, 0xB1, 0x3F, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x01, 0x03, 0x53, 0x65, 0x94, 0xF8, 0xD2, 0x30, 0x00, 0x2B, +0x5B, 0xD1, 0x3B, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x10, 0x21, 0x39, 0x4D, 0x3A, 0x4F, 0xD5, 0xF8, 0x30, 0x32, +0xDF, 0xF8, 0xF8, 0x80, 0x98, 0x47, 0x01, 0x21, 0x00, 0x20, 0x05, 0xF0, 0x5F, 0xFF, 0x00, 0x20, 0x05, 0xF0, 0x9A, 0xFF, +0x01, 0x21, 0x02, 0x20, 0x05, 0xF0, 0x58, 0xFF, 0x02, 0x20, 0x05, 0xF0, 0x93, 0xFF, 0x01, 0x21, 0x03, 0x20, 0x05, 0xF0, +0x51, 0xFF, 0x03, 0x20, 0x05, 0xF0, 0x8C, 0xFF, 0x3B, 0x68, 0x03, 0xF0, 0x0F, 0x03, 0xA3, 0xF1, 0x0A, 0x03, 0xB3, 0xFA, +0x83, 0xF3, 0x5B, 0x09, 0x88, 0xF8, 0x02, 0x30, 0x25, 0xF0, 0x0E, 0xFA, 0x05, 0xF0, 0x90, 0xFA, 0x06, 0xF0, 0x54, 0xF8, +0xD5, 0xF8, 0x74, 0x32, 0x98, 0x47, 0x94, 0xF8, 0x44, 0x10, 0x23, 0x48, 0x24, 0xF0, 0xEE, 0xF8, 0x07, 0xF0, 0x8C, 0xF8, +0x06, 0xF0, 0xA8, 0xF9, 0x98, 0xF8, 0x02, 0x30, 0x0B, 0xB3, 0xD5, 0xF8, 0x6C, 0x34, 0x98, 0x47, 0x1D, 0x4A, 0x1E, 0x49, +0x13, 0x68, 0x23, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x0F, 0x03, 0x3B, 0x60, 0x02, 0x20, 0x24, 0xF0, +0x27, 0xF9, 0x33, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x02, 0xD1, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD5, 0xF8, 0x80, 0x32, +0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4A, 0x53, 0x6D, 0x23, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x9D, 0xE7, 0x11, 0x49, +0x02, 0x20, 0x24, 0xF0, 0x11, 0xF9, 0xE8, 0xE7, 0x2C, 0x19, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, +0xC8, 0x35, 0x17, 0x00, 0x30, 0x36, 0x17, 0x00, 0xAC, 0x35, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x40, 0x70, 0x76, 0x15, 0x00, 0x10, 0x00, 0x58, 0x40, +0x80, 0x76, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, 0x8C, 0x76, 0x15, 0x00, 0x3C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x20, 0x4B, +0x04, 0x46, 0x1E, 0x68, 0x1D, 0x68, 0x00, 0xF0, 0xAB, 0xFE, 0x07, 0x46, 0x00, 0xF0, 0xAA, 0xFE, 0x01, 0x2C, 0xC6, 0xF3, +0x03, 0x26, 0xC5, 0xF3, 0xC0, 0x65, 0x14, 0xD0, 0x02, 0x2C, 0x0E, 0xD0, 0x3C, 0xB1, 0x18, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x1C, 0xDB, 0x00, 0x20, 0xF8, 0xBD, 0x90, 0xB9, 0x05, 0xBB, 0x70, 0x1E, 0x18, 0xBF, 0x01, 0x20, +0xF8, 0xBD, 0x01, 0x2E, 0x0D, 0xD0, 0x68, 0x1D, 0xF8, 0xBD, 0x30, 0xB9, 0x01, 0x2E, 0x17, 0xD0, 0x00, 0x2F, 0x0C, 0xBF, +0x03, 0x20, 0x09, 0x20, 0xF8, 0xBD, 0x0B, 0x20, 0xF8, 0xBD, 0x0A, 0x20, 0xF8, 0xBD, 0x00, 0x2D, 0x14, 0xBF, 0x07, 0x20, +0x04, 0x20, 0xF8, 0xBD, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xB5, 0x12, 0x24, 0xF0, 0xDC, 0xFA, 0x00, 0x20, 0xF8, 0xBD, +0x08, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x00, 0x00, 0x33, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x09, 0x49, 0x0B, 0x69, 0x83, 0xB0, 0x18, 0x44, 0x20, 0x24, 0x01, 0x94, 0x01, 0x9B, +0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0B, 0x69, 0x1B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x08, 0xB5, 0xFF, 0xF7, 0x9D, 0xFF, 0x03, 0x4B, 0x1A, 0x78, 0x82, 0x42, +0x18, 0xBF, 0x18, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, 0x10, 0x4C, 0x18, 0x68, +0xC0, 0xF3, 0x01, 0x60, 0xFF, 0xF7, 0x8C, 0xFF, 0x08, 0x22, 0x05, 0x46, 0x00, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0xB6, 0xFD, +0x0B, 0x48, 0x0C, 0x4A, 0x00, 0xEB, 0x05, 0x10, 0xFF, 0x21, 0xC3, 0x88, 0x80, 0x88, 0x10, 0x60, 0xC3, 0xF3, 0x85, 0x12, +0x03, 0xF0, 0x3F, 0x03, 0x1A, 0x44, 0x21, 0x70, 0x4F, 0xF4, 0x96, 0x63, 0xB3, 0xFB, 0xF2, 0xF3, 0x63, 0x70, 0x38, 0xBD, +0x00, 0x00, 0x33, 0x40, 0x60, 0x25, 0x17, 0x00, 0x98, 0x76, 0x15, 0x00, 0x6C, 0x00, 0x34, 0x40, 0x01, 0x4B, 0x58, 0x78, +0x70, 0x47, 0x00, 0xBF, 0x60, 0x25, 0x17, 0x00, 0x10, 0xB4, 0x13, 0x4B, 0x13, 0x49, 0x11, 0x22, 0x1A, 0x60, 0x08, 0x69, +0x83, 0xB0, 0x0A, 0x30, 0x20, 0x24, 0x00, 0x94, 0x00, 0x9B, 0x5A, 0x1E, 0x00, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x0A, 0x69, +0x12, 0x1A, 0x00, 0x2A, 0xF5, 0xDB, 0x0A, 0x4A, 0x0A, 0x4C, 0x13, 0x60, 0x09, 0x69, 0x20, 0x20, 0x0A, 0x31, 0x01, 0x90, +0x01, 0x9B, 0x5A, 0x1E, 0x01, 0x92, 0x00, 0x2B, 0xFA, 0xD1, 0x23, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xF5, 0xDB, 0x03, 0xB0, +0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x00, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x16, 0x4A, 0x13, 0x68, +0x43, 0xF4, 0x80, 0x53, 0x10, 0xB4, 0x13, 0x60, 0x00, 0xBF, 0x02, 0xF5, 0x99, 0x42, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x53, +0x13, 0x60, 0x00, 0xBF, 0x10, 0x4B, 0x11, 0x48, 0x03, 0xF5, 0x00, 0x64, 0xC0, 0x1A, 0x1A, 0x18, 0x53, 0xF8, 0x04, 0x1B, +0x11, 0x60, 0xA3, 0x42, 0xF9, 0xD1, 0x00, 0xBF, 0x09, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x00, 0xBF, +0x1A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x00, 0xBF, 0x07, 0x4A, 0x5D, 0xF8, 0x04, 0x4B, 0x13, 0x68, 0x23, 0xF0, +0x00, 0x53, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x90, 0xB3, 0x33, 0x40, 0xB0, 0x05, 0x17, 0x00, 0x00, 0xA0, 0x33, 0x40, +0x10, 0x00, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x15, 0x46, 0x1C, 0x46, 0x9D, 0xF8, 0x18, 0x80, 0x0E, 0x46, +0xFF, 0xF7, 0x94, 0xFF, 0x6C, 0x4A, 0x13, 0x68, 0x01, 0x2F, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x00, 0xF0, 0x98, 0x80, +0x69, 0x4A, 0x6A, 0x49, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x40, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, +0xD9, 0x32, 0x02, 0xF5, 0xA2, 0x72, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, +0x61, 0x4A, 0x10, 0x68, 0x20, 0xF4, 0xFF, 0x40, 0x20, 0xF0, 0x7F, 0x00, 0x4F, 0xF0, 0x80, 0x63, 0xB3, 0xFB, 0xF5, 0xF3, +0xC3, 0xF3, 0x0E, 0x03, 0x03, 0x43, 0x01, 0x2C, 0x13, 0x60, 0x60, 0xD0, 0x02, 0x2C, 0x48, 0xD0, 0x00, 0x25, 0x59, 0x4B, +0x1E, 0x68, 0x26, 0xF0, 0x03, 0x06, 0x35, 0x43, 0x1D, 0x60, 0x00, 0x23, 0x56, 0x4A, 0x57, 0x49, 0x13, 0x60, 0x0B, 0x68, +0x56, 0x4D, 0x57, 0x48, 0x57, 0x4E, 0x22, 0x06, 0x02, 0xF0, 0x40, 0x72, 0x23, 0xF0, 0x40, 0x73, 0x13, 0x43, 0x0B, 0x60, +0x29, 0x68, 0x23, 0x04, 0x21, 0xF4, 0x40, 0x31, 0x03, 0xF4, 0x40, 0x33, 0x0B, 0x43, 0x2B, 0x60, 0x03, 0x68, 0x23, 0xF0, +0x80, 0x43, 0x03, 0x60, 0x31, 0x68, 0x05, 0xF5, 0x82, 0x35, 0x04, 0xF0, 0x0F, 0x03, 0x21, 0xF0, 0x0F, 0x01, 0x05, 0xF5, +0x88, 0x75, 0x0B, 0x43, 0x33, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0x40, 0x73, 0x1A, 0x43, 0x2A, 0x60, 0xEC, 0xB9, 0x50, 0xF8, +0x08, 0x3C, 0x45, 0x49, 0x45, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC8, 0x53, 0x40, 0xF8, 0x08, 0x3C, 0x0B, 0x68, +0x23, 0xF0, 0x30, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x1C, 0x43, 0x13, 0x60, 0xBD, 0xE8, +0xF0, 0x81, 0xAD, 0x1B, 0x00, 0x2D, 0x42, 0xDD, 0x0A, 0x2D, 0xCC, 0xBF, 0x00, 0x25, 0x01, 0x25, 0xAF, 0xE7, 0x01, 0x2C, +0x41, 0xD0, 0x38, 0x4A, 0x38, 0x49, 0x13, 0x68, 0x38, 0x48, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0x60, 0x63, 0x13, 0x60, +0x08, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0xF5, 0x28, 0x42, 0xB5, 0x42, 0x53, 0x6B, 0x88, 0xBF, 0x01, 0x21, 0x23, 0xF0, +0x03, 0x03, 0x98, 0xBF, 0x02, 0x21, 0x43, 0xEA, 0x01, 0x03, 0x02, 0xF1, 0x34, 0x02, 0x13, 0x60, 0x94, 0xBF, 0x01, 0x23, +0x00, 0x23, 0x95, 0xE7, 0x1D, 0x49, 0x1E, 0x48, 0x0B, 0x68, 0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0xC0, 0x33, 0x0B, 0x60, +0x03, 0x68, 0x01, 0xF5, 0xD9, 0x31, 0x01, 0xF5, 0xA2, 0x71, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x18, 0xF0, +0x04, 0x0F, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x3F, 0xF4, 0x64, 0xAF, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, +0x5E, 0xE7, 0x15, 0xF1, 0x0A, 0x0F, 0xB4, 0xBF, 0x03, 0x25, 0x02, 0x25, 0x6B, 0xE7, 0x1A, 0x48, 0x14, 0x49, 0x03, 0x68, +0x14, 0x4A, 0x23, 0xF0, 0x7F, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, +0x10, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0xD8, 0x43, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, +0x24, 0x03, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x08, 0x33, 0x40, 0x4C, 0x08, 0x33, 0x40, 0x80, 0xB0, 0x33, 0x40, +0x50, 0x08, 0x33, 0x40, 0x24, 0x08, 0x33, 0x40, 0x10, 0x03, 0x32, 0x40, 0x0C, 0x08, 0x33, 0x40, 0x00, 0x08, 0x33, 0x40, +0x08, 0x00, 0x34, 0x40, 0x8C, 0x08, 0x33, 0x40, 0x34, 0x08, 0x33, 0x40, 0x18, 0x08, 0x33, 0x40, 0x06, 0x0C, 0x8E, 0x01, +0x04, 0x08, 0x33, 0x40, 0x44, 0x49, 0x45, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x70, 0xB4, 0x0B, 0x60, 0x13, 0x68, +0x42, 0x4C, 0x43, 0x4D, 0x43, 0x4E, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, +0xE0, 0x03, 0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x23, 0x68, 0xA1, 0xF5, 0x0F, 0x41, 0x23, 0xF4, 0x00, 0x03, 0x23, 0x60, +0x04, 0x39, 0x0C, 0x23, 0x2B, 0x60, 0x0B, 0x68, 0x32, 0x6A, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x13, 0x43, +0x40, 0xF6, 0xB4, 0x12, 0x90, 0x42, 0x0B, 0x60, 0x34, 0x4B, 0x26, 0xD0, 0x72, 0x6A, 0x1A, 0x60, 0xA0, 0xF6, 0x6C, 0x13, +0x3C, 0x2B, 0x22, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, +0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, 0x21, 0x21, 0x21, 0x40, 0x21, +0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x21, +0x21, 0x21, 0x21, 0x47, 0x21, 0x21, 0x21, 0x21, 0x47, 0x00, 0x21, 0x4A, 0x1A, 0x60, 0x21, 0x4A, 0x21, 0x49, 0x13, 0x68, +0x91, 0xF8, 0xB4, 0x10, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x99, 0xB1, 0x1E, 0x49, 0x1F, 0x4B, 0x0A, 0x68, 0x22, 0xF4, +0xFE, 0x62, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, +0x0F, 0x02, 0x9A, 0x60, 0xDA, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0xDA, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x15, 0x49, 0x16, 0x4B, +0xB0, 0x6A, 0x72, 0x6B, 0x08, 0x60, 0x1A, 0x60, 0xD9, 0xE7, 0x12, 0x4B, 0xF4, 0x6A, 0xB1, 0x6B, 0x11, 0x4A, 0x1C, 0x60, +0x40, 0xF6, 0xA8, 0x13, 0x98, 0x42, 0x11, 0x60, 0xCF, 0xD1, 0x0F, 0x4B, 0x11, 0x22, 0x1A, 0x60, 0xCB, 0xE7, 0x00, 0xBF, +0x04, 0x40, 0x34, 0x40, 0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, +0x20, 0x03, 0x33, 0x40, 0x1B, 0x88, 0xB3, 0x01, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x78, 0x40, 0x34, 0x40, +0x00, 0x30, 0x50, 0x40, 0x30, 0x40, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x24, 0x01, 0x58, 0x40, 0x70, 0x47, 0x00, 0xBF, +0x3A, 0x49, 0x3B, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0xFC, 0x63, 0x43, 0xF4, 0xA8, 0x63, 0x30, 0xB4, 0x0B, 0x60, 0x13, 0x68, +0x37, 0x4C, 0x38, 0x4D, 0x23, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x13, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xE0, 0x03, +0x13, 0x60, 0x23, 0x68, 0x33, 0x4A, 0xA1, 0xF5, 0x0F, 0x41, 0x43, 0xF4, 0x00, 0x03, 0x23, 0x60, 0x04, 0x39, 0x0C, 0x23, +0x2B, 0x60, 0x0B, 0x68, 0xD4, 0x6C, 0x23, 0xF4, 0xFE, 0x43, 0x23, 0xF0, 0x7F, 0x03, 0x23, 0x43, 0x41, 0xF2, 0xC8, 0x44, +0xA0, 0x42, 0x0B, 0x60, 0x40, 0xD8, 0x2A, 0x4B, 0x12, 0x6C, 0x1A, 0x60, 0x29, 0x4A, 0x2A, 0x4C, 0x13, 0x68, 0x2A, 0x4D, +0x2A, 0x48, 0x2B, 0x49, 0x23, 0xF0, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x94, 0xF8, 0xB4, 0x40, 0x23, 0xF0, 0x0F, 0x03, +0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, +0x43, 0xF4, 0x70, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0xDC, 0xB1, 0x01, 0xF5, 0x01, 0x51, +0x1D, 0x4B, 0x8A, 0x68, 0x22, 0xF4, 0xFE, 0x62, 0x42, 0xF4, 0x88, 0x62, 0x8A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x0F, 0x02, +0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x9A, 0x68, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x9A, 0x60, 0xDA, 0x68, +0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x03, 0x02, 0x08, 0x31, 0xDA, 0x60, 0x30, 0xBC, 0x70, 0x47, 0x41, 0xF2, 0x44, 0x63, +0x98, 0x42, 0x08, 0x4B, 0x94, 0xBF, 0x52, 0x6C, 0x92, 0x6C, 0x1A, 0x60, 0xB8, 0xE7, 0x00, 0xBF, 0x04, 0x40, 0x34, 0x40, +0x34, 0x21, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x00, 0xB3, 0x33, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x30, 0x40, 0x34, 0x40, +0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x3C, 0x40, 0x34, 0x40, 0x08, 0x01, 0x58, 0x40, 0x30, 0x20, 0x34, 0x40, +0x00, 0x30, 0x50, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0x0F, 0x46, 0x9D, 0xF8, 0x3C, 0x10, +0x02, 0x91, 0xCD, 0xE9, 0x00, 0x23, 0x05, 0x46, 0x14, 0x46, 0x1E, 0x46, 0x02, 0x46, 0x3B, 0x46, 0xAE, 0x49, 0xAF, 0x48, +0x9D, 0xF8, 0x38, 0xA0, 0xDF, 0xF8, 0x08, 0x83, 0xDF, 0xF8, 0x08, 0x93, 0x23, 0xF0, 0x4C, 0xFD, 0xAB, 0x49, 0x22, 0x46, +0x04, 0x20, 0x23, 0xF0, 0x97, 0xFD, 0x30, 0x46, 0xFF, 0xF7, 0x06, 0xFD, 0x39, 0x46, 0x33, 0x46, 0xD8, 0xF8, 0x40, 0x71, +0xCD, 0xF8, 0x00, 0xA0, 0x22, 0x46, 0x28, 0x46, 0xB8, 0x47, 0x99, 0xF8, 0x2A, 0x30, 0xAB, 0x42, 0x0A, 0xD0, 0xD8, 0xF8, +0x80, 0x34, 0x28, 0x46, 0x98, 0x47, 0x99, 0xF8, 0x2A, 0x20, 0x9F, 0x49, 0x2B, 0x46, 0x04, 0x20, 0x23, 0xF0, 0x7C, 0xFD, +0x9D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA8, 0x80, 0x00, 0x2D, 0x00, 0xF0, 0xB7, 0x80, +0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x00, 0xF2, 0xAE, 0x80, 0x41, 0xF2, 0x7B, 0x53, 0x9C, 0x42, 0x8B, 0xBF, 0x4F, 0xF0, +0xEC, 0x09, 0x4F, 0xF0, 0xFC, 0x09, 0x3B, 0x27, 0x3F, 0x27, 0x20, 0x46, 0x35, 0xF0, 0x0E, 0xFD, 0x02, 0x46, 0x0B, 0x46, +0x82, 0x46, 0x8B, 0x46, 0x35, 0xF0, 0xBC, 0xFB, 0x8D, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0x98, 0xFE, 0x8C, 0x4B, 0x00, 0x22, +0x35, 0xF0, 0x6A, 0xFD, 0x35, 0xF0, 0x62, 0xFB, 0x36, 0xF0, 0x00, 0xF8, 0x52, 0x46, 0x5B, 0x46, 0x88, 0x49, 0x05, 0x46, +0x00, 0x20, 0x35, 0xF0, 0x89, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0x5A, 0xFD, 0x35, 0xF0, 0x52, 0xFB, +0x35, 0xF0, 0xF0, 0xFF, 0x03, 0x46, 0x38, 0x46, 0x1F, 0x46, 0x35, 0xF0, 0xE7, 0xFC, 0x80, 0x4B, 0x00, 0x22, 0x35, 0xF0, +0x4D, 0xFD, 0x02, 0x46, 0x0B, 0x46, 0x50, 0x46, 0x59, 0x46, 0x35, 0xF0, 0x71, 0xFE, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, +0x35, 0xF0, 0x42, 0xFD, 0x35, 0xF0, 0x3A, 0xFB, 0x35, 0xF0, 0xD8, 0xFF, 0x77, 0x4B, 0x78, 0x4A, 0xD3, 0xF8, 0x00, 0xE0, +0x2E, 0xF4, 0x00, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF4, 0x80, 0x0E, 0xC3, 0xF8, 0x00, 0xE0, +0xD3, 0xF8, 0x00, 0xE0, 0x2E, 0xF4, 0x00, 0x1E, 0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x4E, 0xF0, 0x08, 0x0E, +0xC3, 0xF8, 0x00, 0xE0, 0xD3, 0xF8, 0x00, 0xE0, 0x01, 0x46, 0x2E, 0xF0, 0x04, 0x0E, 0x6A, 0x48, 0xC3, 0xF8, 0x00, 0xE0, +0x03, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x03, 0x60, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x53, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF4, +0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x13, 0x60, 0x20, 0x46, 0xD8, 0xF8, 0xA8, 0x34, 0x89, 0x46, +0x98, 0x47, 0x20, 0x46, 0xD8, 0xF8, 0xAC, 0x34, 0x64, 0x08, 0x98, 0x47, 0x5C, 0x4B, 0x5D, 0x4A, 0x1D, 0x60, 0x17, 0x60, +0xC3, 0xF8, 0x48, 0x90, 0x00, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x01, 0x2E, 0x04, 0xD1, 0x59, 0x4A, 0x13, 0x68, 0x23, 0xF4, +0x00, 0x63, 0x13, 0x60, 0x57, 0x49, 0x58, 0x4B, 0x08, 0x68, 0x58, 0x4A, 0x03, 0x40, 0x43, 0xEA, 0x04, 0x33, 0x01, 0x20, +0x0B, 0x60, 0x10, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x2D, 0x7F, 0xF6, 0x55, 0xAF, 0x52, 0x49, 0x53, 0x48, +0x40, 0xF6, 0x4A, 0x22, 0x23, 0xF0, 0xEE, 0xFE, 0x41, 0xF2, 0x43, 0x63, 0x9C, 0x42, 0x7F, 0xF6, 0x52, 0xAF, 0x4F, 0xF0, +0xF0, 0x09, 0x3C, 0x27, 0x57, 0xE7, 0x20, 0x46, 0x35, 0xF0, 0x66, 0xFC, 0x4B, 0x4B, 0x00, 0x22, 0x82, 0x46, 0x8B, 0x46, +0x35, 0xF0, 0xCA, 0xFC, 0x39, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xF0, 0xFD, 0x38, 0x4B, 0x00, 0x22, 0x35, 0xF0, 0xC2, 0xFC, +0x35, 0xF0, 0xBA, 0xFA, 0x35, 0xF0, 0x58, 0xFF, 0x52, 0x46, 0x5B, 0x46, 0x05, 0x46, 0x42, 0x49, 0x00, 0x20, 0x35, 0xF0, +0xE1, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x35, 0xF0, 0xB2, 0xFC, 0x35, 0xF0, 0xAA, 0xFA, 0x35, 0xF0, 0x48, 0xFF, +0x24, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x07, 0x46, 0x59, 0x46, 0x50, 0x46, 0x35, 0xF0, 0xD0, 0xFD, 0x00, 0x22, 0x4F, 0xF0, +0x83, 0x43, 0x35, 0xF0, 0xA1, 0xFC, 0x35, 0xF0, 0x99, 0xFA, 0x35, 0xF0, 0x37, 0xFF, 0x27, 0x4B, 0x28, 0x4A, 0x19, 0x68, +0x21, 0xF4, 0x00, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x80, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF4, 0x00, 0x11, +0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x41, 0xF0, 0x04, 0x01, 0x19, 0x60, 0x13, 0x68, +0x23, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x81, 0x46, 0x23, 0xF0, 0x00, 0x53, 0x19, 0x48, 0x13, 0x60, 0x03, 0x68, +0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, 0x04, 0x03, 0x43, 0xF0, 0xEC, 0x03, 0x03, 0x60, 0xD8, 0xF8, 0xA0, 0x34, 0x20, 0x46, +0x98, 0x47, 0xD8, 0xF8, 0xA4, 0x34, 0x20, 0x46, 0x98, 0x47, 0x69, 0xE7, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, +0x13, 0x60, 0x73, 0xE7, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x78, 0x78, 0x15, 0x00, +0x58, 0x77, 0x15, 0x00, 0x8C, 0x77, 0x15, 0x00, 0x9C, 0x77, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, +0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x00, 0x54, 0x40, 0x14, 0x40, 0x34, 0x40, 0x3C, 0x40, 0x34, 0x40, +0x30, 0x40, 0x34, 0x40, 0x10, 0x20, 0x34, 0x40, 0x54, 0x20, 0x34, 0x40, 0x20, 0x40, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, +0xFF, 0x0F, 0x00, 0xE0, 0x84, 0x21, 0x34, 0x40, 0x70, 0x79, 0x15, 0x00, 0xB4, 0x77, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, +0x00, 0x00, 0xA4, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x43, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x6B, 0xDB, 0xFF, 0xF7, 0xBD, 0xFB, 0x40, 0x49, 0x40, 0x4A, 0x0B, 0x68, 0x40, 0x48, 0x43, 0xF0, +0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x13, 0x60, 0x03, 0x68, 0xC3, 0xF3, 0x03, 0x23, 0x02, 0x2B, +0x06, 0xD1, 0xA2, 0xF5, 0x99, 0x42, 0x04, 0x3A, 0x13, 0x68, 0x43, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x36, 0x4B, 0x1B, 0x68, +0xC3, 0xF3, 0x03, 0x13, 0x02, 0x2B, 0x02, 0xD1, 0x34, 0x4B, 0x35, 0x4A, 0x1A, 0x60, 0x35, 0x4A, 0x35, 0x49, 0x13, 0x68, +0xDF, 0xF8, 0x04, 0xC1, 0x34, 0x4D, 0x35, 0x4F, 0x35, 0x4C, 0x36, 0x48, 0x36, 0x4E, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, +0x07, 0x03, 0x43, 0xF4, 0xE0, 0x63, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x04, 0x23, 0xCC, 0xF8, 0x00, 0x30, +0x01, 0x22, 0xC4, 0x23, 0x3A, 0x60, 0x2B, 0x60, 0x00, 0x23, 0x23, 0x60, 0x6F, 0x24, 0x04, 0x60, 0x2C, 0x4C, 0xB0, 0x27, +0x37, 0x60, 0x23, 0x60, 0xC3, 0x60, 0xAB, 0x61, 0x6B, 0x25, 0xE5, 0x60, 0x29, 0x4D, 0x83, 0x61, 0x2A, 0x60, 0xA3, 0x61, +0x07, 0x24, 0x44, 0x62, 0xEC, 0x26, 0x27, 0x4C, 0xEE, 0x60, 0x03, 0x25, 0xC5, 0x62, 0x23, 0x60, 0xD0, 0xF8, 0xEC, 0x31, +0x93, 0x42, 0x00, 0xF5, 0xF6, 0x70, 0x0F, 0xD9, 0x22, 0x4B, 0xA0, 0xF5, 0x56, 0x70, 0x1A, 0x60, 0x03, 0x68, 0x23, 0xF0, +0x7F, 0x43, 0x43, 0xF0, 0x20, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x80, 0x73, 0x0B, 0x60, +0xF8, 0xBD, 0x1B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x0E, 0x02, 0x33, 0x03, 0xEB, 0x83, 0x03, 0xC2, 0xF3, 0x07, 0x42, +0x02, 0xEB, 0x43, 0x03, 0x1E, 0x2B, 0x86, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF6, 0x2C, 0x32, 0x23, 0xF0, 0xBC, 0xFD, +0x7F, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x10, 0x00, 0x34, 0x40, 0x14, 0x00, 0x34, 0x40, 0x00, 0x00, 0x33, 0x40, +0x04, 0xB1, 0x33, 0x40, 0x34, 0x34, 0x34, 0x00, 0xB4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x34, 0x40, 0x08, 0x12, 0x34, 0x40, +0x04, 0x12, 0x34, 0x40, 0x0C, 0x12, 0x34, 0x40, 0x10, 0x12, 0x34, 0x40, 0x14, 0x12, 0x34, 0x40, 0x18, 0x12, 0x34, 0x40, +0x2C, 0x12, 0x34, 0x40, 0x40, 0x12, 0x34, 0x40, 0x0C, 0x10, 0x34, 0x40, 0x3C, 0x00, 0x33, 0x40, 0x70, 0x79, 0x15, 0x00, +0xC8, 0x77, 0x15, 0x00, 0x00, 0x12, 0x34, 0x40, 0x10, 0xB5, 0x1A, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0x3C, 0x31, 0x98, 0x47, +0x18, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, +0x15, 0x4A, 0x1A, 0x60, 0x19, 0x68, 0x12, 0x4A, 0x41, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, +0x11, 0x4B, 0x13, 0x60, 0x13, 0x68, 0x0D, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0xDB, 0x0F, 0xFC, 0xD1, +0xCD, 0xE9, 0x00, 0x33, 0x40, 0xF6, 0x85, 0x12, 0x11, 0x46, 0x18, 0x46, 0xD4, 0xF8, 0x28, 0x42, 0xA0, 0x47, 0x09, 0x49, +0x09, 0x4B, 0x0A, 0x4A, 0x0C, 0x20, 0x08, 0x60, 0x1A, 0x60, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, +0x20, 0x00, 0x58, 0x40, 0xBF, 0x3F, 0x42, 0x01, 0xA2, 0x30, 0x43, 0x01, 0xDD, 0x1D, 0x44, 0x01, 0x00, 0xB3, 0x33, 0x40, +0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x70, 0xB5, 0x13, 0x4B, 0x13, 0x4D, 0x04, 0x46, 0xED, 0x1A, 0x03, 0xF2, +0x3C, 0x50, 0x5A, 0x19, 0x53, 0xF8, 0x04, 0x1B, 0x11, 0x60, 0x83, 0x42, 0xF9, 0xD1, 0xFF, 0xF7, 0xEB, 0xFA, 0x0E, 0x4B, +0x0E, 0x4E, 0xD3, 0xF8, 0x24, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, 0x86, 0xF8, 0x2A, 0x30, 0x0F, 0xCC, 0x35, 0x46, +0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x23, 0x68, 0x2B, 0x60, 0x05, 0x21, 0x4F, 0xF0, 0xFF, 0x12, 0xFF, 0x23, 0x86, 0xF8, +0x2B, 0x10, 0x72, 0x62, 0x33, 0x85, 0x70, 0xBD, 0xB0, 0x0D, 0x17, 0x00, 0x00, 0x90, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, +0xBC, 0x34, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD4, 0x08, 0xBD, 0x14, 0xF0, 0xF4, 0xFD, +0x02, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0xA8, 0x10, 0x34, 0x40, 0xAC, 0x10, 0x34, 0x40, 0x03, 0x4A, 0x04, 0x4B, +0x12, 0x68, 0x02, 0x60, 0x1B, 0x68, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x3C, 0x00, 0x33, 0x40, +0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x9D, 0xF8, 0x38, 0x40, 0xBD, 0xF8, 0x30, 0xA0, 0x9D, 0xF8, 0x34, 0x90, 0x00, 0x2C, +0x43, 0xD1, 0x98, 0x46, 0x25, 0x4B, 0x1B, 0x78, 0x05, 0x46, 0x0E, 0x46, 0x17, 0x46, 0xD3, 0xB1, 0x23, 0x4C, 0x24, 0x4A, +0xCD, 0xF8, 0x00, 0x90, 0x00, 0x23, 0xD2, 0xF8, 0x28, 0xB2, 0x01, 0x93, 0x42, 0x46, 0x33, 0x46, 0x39, 0x46, 0x28, 0x46, +0xD8, 0x47, 0x84, 0xF8, 0x2A, 0x50, 0x84, 0xF8, 0x2B, 0x60, 0x84, 0xF8, 0x2C, 0x90, 0xA7, 0x84, 0xA4, 0xF8, 0x26, 0x80, +0xA4, 0xF8, 0x28, 0xA0, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x4A, 0x15, 0x4C, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, +0x13, 0x60, 0x94, 0xF8, 0x2A, 0x30, 0x83, 0x42, 0xDB, 0xD1, 0x94, 0xF8, 0x2B, 0x30, 0x8B, 0x42, 0xD7, 0xD1, 0x94, 0xF8, +0x2C, 0x30, 0x4B, 0x45, 0xD3, 0xD1, 0xA3, 0x8C, 0xBB, 0x42, 0xD0, 0xD1, 0xE3, 0x8C, 0x43, 0x45, 0xCD, 0xD1, 0x23, 0x8D, +0x53, 0x45, 0xCA, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x35, 0xBA, 0x08, 0x49, +0x09, 0x48, 0x22, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x23, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x3C, 0x36, 0x17, 0x00, +0xBC, 0x34, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x78, 0x15, 0x00, 0x38, 0x78, 0x15, 0x00, +0x18, 0x78, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x71, 0xB9, 0x0A, 0x4A, 0x93, 0x8C, 0x92, 0xF8, 0x2B, 0x00, 0x92, 0xF8, +0x2A, 0x10, 0xD2, 0xF8, 0x26, 0x20, 0x62, 0x60, 0x1B, 0x04, 0x43, 0xEA, 0x00, 0x23, 0x0B, 0x43, 0x23, 0x60, 0x10, 0xBD, +0x0A, 0x46, 0x03, 0x48, 0x03, 0x49, 0x23, 0xF0, 0x07, 0xFA, 0xEA, 0xE7, 0xBC, 0x34, 0x17, 0x00, 0x18, 0x78, 0x15, 0x00, +0x9C, 0x78, 0x15, 0x00, 0x04, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x00, 0xD1, 0x70, 0x47, 0x03, 0x49, 0x03, 0x48, 0x23, 0xF0, +0xF7, 0xB9, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, 0xAC, 0x78, 0x15, 0x00, 0x60, 0x78, 0x15, 0x00, 0x4F, 0xF4, 0x7A, 0x70, +0x70, 0x47, 0x00, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, +0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x01, 0x28, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x00, 0xBF, +0xFC, 0x13, 0x34, 0x40, 0x04, 0x4A, 0x13, 0x68, 0xC0, 0x00, 0x00, 0xF0, 0x08, 0x00, 0x23, 0xF0, 0x08, 0x03, 0x18, 0x43, +0x10, 0x60, 0x70, 0x47, 0xA0, 0x10, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x60, 0x70, 0x47, 0x00, 0xBF, +0x00, 0x00, 0x33, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x00, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, +0x02, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x80, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x06, 0x4B, 0x02, 0x68, +0x1A, 0x60, 0x42, 0x68, 0x5A, 0x60, 0x0A, 0x68, 0x9A, 0x60, 0x4A, 0x68, 0xDA, 0x60, 0x8A, 0x68, 0x1A, 0x61, 0xCA, 0x68, +0x5A, 0x61, 0x70, 0x47, 0xA8, 0x08, 0x33, 0x40, 0x30, 0xB4, 0x06, 0x49, 0x06, 0x4D, 0x07, 0x4B, 0x00, 0x24, 0xC0, 0xF3, +0x0A, 0x00, 0x40, 0xF2, 0xFF, 0x72, 0x28, 0x60, 0x0C, 0x60, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0xC4, 0x08, 0x33, 0x40, +0xC0, 0x08, 0x33, 0x40, 0xC8, 0x08, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x20, 0x01, 0x38, 0xC0, 0xB2, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0xC0, 0xF3, 0x03, 0x10, 0x01, 0x38, 0xC0, 0xB2, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0x03, 0x4B, 0x18, 0x68, 0x00, 0xF0, 0x0F, 0x00, 0x01, 0x38, 0xC0, 0xB2, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x33, 0x40, 0xF0, 0xB5, 0xBE, 0x4C, 0x94, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x76, 0xD1, +0xBC, 0x4B, 0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x66, 0xD0, 0xE0, 0x8C, 0x40, 0xF6, 0x7B, 0x14, 0xA0, 0x42, 0x40, 0xF2, +0xCA, 0x80, 0x40, 0xF6, 0x94, 0x14, 0xA0, 0x42, 0xB6, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, 0x90, 0xF9, 0x02, 0x60, +0x93, 0xF8, 0xBE, 0x40, 0xB3, 0x48, 0x06, 0xF1, 0x0F, 0x05, 0x1E, 0x2D, 0x00, 0x5D, 0xA8, 0xBF, 0x1E, 0x25, 0x0A, 0x2C, +0x4F, 0xEA, 0x20, 0x17, 0x00, 0xF0, 0x0F, 0x0C, 0x25, 0xEA, 0xE5, 0x75, 0x00, 0xF3, 0xCF, 0x80, 0x00, 0xF0, 0xE4, 0x80, +0xAB, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x10, 0xF9, 0x14, 0xE0, 0x75, 0x45, 0x00, 0xEB, 0x44, 0x04, 0x00, 0xF3, 0x06, 0x81, +0x64, 0x78, 0xA4, 0xEB, 0x0E, 0x04, 0x2C, 0x44, 0x60, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0x07, 0xF1, 0xFF, 0x37, +0xB8, 0xBF, 0x20, 0x46, 0x60, 0x44, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, 0x07, 0x10, 0x08, 0x70, 0x93, 0xF8, 0xBF, 0x10, +0x9D, 0x4B, 0x5B, 0x5C, 0x0A, 0x29, 0x4F, 0xEA, 0x23, 0x10, 0x03, 0xF0, 0x0F, 0x03, 0x17, 0xDC, 0x00, 0xF0, 0xD1, 0x80, +0x01, 0x31, 0x97, 0x4C, 0x01, 0xEB, 0x41, 0x01, 0x14, 0xF9, 0x11, 0x60, 0xAE, 0x42, 0x04, 0xEB, 0x41, 0x01, 0xC0, 0xF2, +0xD2, 0x80, 0x49, 0x78, 0x89, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, +0x5B, 0x19, 0x5B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0x13, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, +0xE5, 0x07, 0x68, 0xD5, 0x93, 0xF8, 0xB7, 0x00, 0x08, 0x70, 0x93, 0xF8, 0xAD, 0x30, 0x13, 0x70, 0xF0, 0xBD, 0x81, 0x4B, +0x93, 0xF8, 0xBD, 0x50, 0x00, 0x2D, 0x3A, 0xD0, 0xE0, 0x8C, 0x41, 0xF2, 0xC8, 0x44, 0xA0, 0x42, 0x4F, 0xD9, 0xB0, 0xF5, +0xAF, 0x5F, 0x7D, 0xD8, 0x7F, 0x48, 0x90, 0xF9, 0x01, 0x60, 0x93, 0xF8, 0xC3, 0x00, 0x7E, 0x4B, 0x1B, 0x5C, 0x0A, 0x28, +0x4F, 0xEA, 0x23, 0x15, 0x03, 0xF0, 0x0F, 0x03, 0x1D, 0xDC, 0x06, 0xF1, 0x0F, 0x04, 0x1E, 0x2C, 0xA8, 0xBF, 0x1E, 0x24, +0x0A, 0x28, 0x24, 0xEA, 0xE4, 0x74, 0x7A, 0xD0, 0x76, 0x4E, 0x00, 0xEB, 0x40, 0x00, 0x16, 0xF9, 0x10, 0x70, 0xBC, 0x42, +0x06, 0xEB, 0x40, 0x00, 0x00, 0xF3, 0x9E, 0x80, 0x40, 0x78, 0xC0, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, +0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x05, 0x13, 0xDB, 0xB2, +0x13, 0x70, 0x0B, 0x70, 0xF0, 0xBD, 0x93, 0xF8, 0xAC, 0x40, 0xA4, 0x07, 0x04, 0xD5, 0x93, 0xF8, 0xAE, 0x30, 0x0B, 0x70, +0x13, 0x70, 0xF0, 0xBD, 0x90, 0xF9, 0x00, 0x30, 0x61, 0x48, 0x6F, 0xF0, 0x04, 0x04, 0xA3, 0x42, 0xB8, 0xBF, 0x23, 0x46, +0x12, 0x2B, 0xA8, 0xBF, 0x12, 0x23, 0x05, 0x33, 0x5B, 0x10, 0xC3, 0x5C, 0x0B, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x59, 0x48, +0x90, 0xF9, 0x00, 0x60, 0xB1, 0xE7, 0x53, 0x48, 0x90, 0xF9, 0x00, 0x60, 0x3A, 0xE7, 0x90, 0xF9, 0x00, 0x30, 0x51, 0x4D, +0x52, 0x4C, 0x01, 0x2B, 0x6F, 0xF0, 0x01, 0x06, 0x18, 0x46, 0xB8, 0xBF, 0x01, 0x20, 0xB3, 0x42, 0xB8, 0xBF, 0x33, 0x46, +0x17, 0x28, 0xA8, 0xBF, 0x17, 0x20, 0x14, 0x2B, 0xA8, 0xBF, 0x14, 0x23, 0x01, 0x38, 0x02, 0x33, 0x40, 0x10, 0x5B, 0x10, +0x28, 0x5C, 0xE3, 0x5C, 0x08, 0x70, 0x13, 0x70, 0xF0, 0xBD, 0x74, 0x1C, 0x55, 0xDA, 0xA5, 0xF1, 0x0D, 0x00, 0x40, 0xB2, +0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, 0xA7, 0xF1, 0x02, 0x07, 0xB8, 0xBF, 0x20, 0x46, 0x3B, 0xE7, 0x41, 0xF2, 0x44, 0x64, +0xA0, 0x42, 0x3F, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x02, 0x60, 0x90, 0xF9, 0x03, 0x60, 0x7A, 0xE7, 0xB0, 0x1C, 0x53, 0xDB, +0x01, 0x2E, 0x00, 0xF3, 0x8D, 0x80, 0xA5, 0xF1, 0x0F, 0x00, 0x40, 0xB2, 0x28, 0xE7, 0x03, 0x36, 0x43, 0xDA, 0x09, 0x3C, +0x64, 0xB2, 0x6F, 0xF0, 0x04, 0x00, 0x01, 0x3D, 0x84, 0x42, 0xAC, 0xBF, 0x1B, 0x19, 0x1B, 0x18, 0x8D, 0xE7, 0x03, 0x36, +0x30, 0xDA, 0x09, 0x3D, 0x6D, 0xB2, 0x6F, 0xF0, 0x04, 0x01, 0x01, 0x38, 0x8D, 0x42, 0xAC, 0xBF, 0x5B, 0x19, 0x5B, 0x18, +0x38, 0xE7, 0x91, 0xF9, 0x04, 0x40, 0xAC, 0x42, 0x3B, 0xDD, 0xCC, 0x78, 0x89, 0x78, 0x61, 0x1A, 0x0D, 0x44, 0x43, 0xFA, +0x85, 0xF3, 0x2D, 0xE7, 0x94, 0xF9, 0x04, 0xE0, 0x75, 0x45, 0x57, 0xDA, 0xE0, 0x78, 0xA4, 0x78, 0x00, 0x1B, 0x28, 0x44, +0x40, 0xB2, 0xFB, 0xE6, 0x90, 0xF9, 0x04, 0x60, 0xB4, 0x42, 0x43, 0xDA, 0xC6, 0x78, 0x80, 0x78, 0x30, 0x1A, 0x04, 0x44, +0x43, 0xFA, 0x84, 0xF3, 0x61, 0xE7, 0xA5, 0xF1, 0x0F, 0x04, 0x60, 0xB2, 0x03, 0x28, 0xA8, 0xBF, 0x03, 0x20, 0xE9, 0xE6, +0x0F, 0x3D, 0x6D, 0xB2, 0x05, 0x2D, 0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x0A, 0xE7, 0x0F, 0x3C, 0x64, 0xB2, 0x05, 0x2C, +0xD4, 0xBF, 0x1B, 0x19, 0x05, 0x33, 0x4C, 0xE7, 0xA5, 0xF1, 0x0A, 0x00, 0x40, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0xA0, 0x42, +0x07, 0xF1, 0xFF, 0x37, 0xB8, 0xBF, 0x20, 0x46, 0xD0, 0xE6, 0x49, 0x79, 0x09, 0x1B, 0x0D, 0x44, 0x6D, 0xB2, 0x05, 0x2D, +0xD4, 0xBF, 0x5B, 0x19, 0x05, 0x33, 0x01, 0x30, 0xEE, 0xE6, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, +0x68, 0x25, 0x17, 0x00, 0xEC, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0xF8, 0x12, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, +0x04, 0x13, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, 0x40, 0x79, 0x80, 0x1B, 0x04, 0x44, 0x64, 0xB2, 0x05, 0x2C, 0xD4, 0xBF, +0x1B, 0x19, 0x05, 0x33, 0x01, 0x35, 0x1A, 0xE7, 0x60, 0x79, 0xA0, 0xEB, 0x0E, 0x00, 0x28, 0x44, 0x40, 0xB2, 0x05, 0x28, +0xA8, 0xBF, 0x05, 0x20, 0x01, 0x37, 0x9F, 0xE6, 0xA5, 0xF1, 0x11, 0x00, 0x40, 0xB2, 0x03, 0x28, 0x07, 0xF1, 0x02, 0x07, +0xA8, 0xBF, 0x03, 0x20, 0x96, 0xE6, 0x00, 0xBF, 0xF0, 0xB4, 0xB9, 0x4B, 0x93, 0xF8, 0x2A, 0x20, 0xDC, 0x8C, 0x52, 0xBB, +0xC0, 0xB9, 0x03, 0x29, 0x00, 0xF2, 0x91, 0x80, 0xB5, 0x4A, 0xB6, 0x4B, 0x92, 0xF8, 0xBE, 0x50, 0x5B, 0x5D, 0x02, 0x46, +0x01, 0x46, 0x07, 0x46, 0x40, 0xF6, 0x7B, 0x10, 0x84, 0x42, 0x00, 0xF2, 0xBA, 0x80, 0xB1, 0x48, 0x90, 0xF9, 0x00, 0x60, +0x00, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0xD8, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x04, 0x28, 0x40, 0xF2, 0x8F, 0x80, 0x09, 0x29, +0x40, 0xF2, 0x8E, 0x80, 0xA7, 0x4B, 0x93, 0xF8, 0xC2, 0x50, 0x08, 0x2D, 0x40, 0xF3, 0x17, 0x81, 0x01, 0x21, 0x0F, 0x46, +0x09, 0x25, 0xD4, 0x23, 0xE0, 0xE7, 0x04, 0x28, 0x44, 0xD9, 0x09, 0x29, 0x44, 0xD9, 0xA0, 0x4B, 0xA2, 0x49, 0x93, 0xF8, +0xC6, 0x30, 0x09, 0x2B, 0xA8, 0xBF, 0x09, 0x23, 0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0x4F, 0xF0, 0x00, 0x05, +0x53, 0xD9, 0xB4, 0xF5, 0xAF, 0x5F, 0x00, 0xF2, 0xCC, 0x80, 0x9B, 0x4A, 0x92, 0xF9, 0x01, 0x20, 0x00, 0x2D, 0xD1, 0xD1, +0x0A, 0x2B, 0x4F, 0xEA, 0x20, 0x14, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xDC, 0x02, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, +0x1E, 0x21, 0x0A, 0x2B, 0x21, 0xEA, 0xE1, 0x71, 0x00, 0xF0, 0x3C, 0x81, 0x91, 0x4A, 0x03, 0xEB, 0x43, 0x03, 0x12, 0xF9, +0x13, 0x50, 0x8D, 0x42, 0x02, 0xEB, 0x43, 0x02, 0x80, 0xF2, 0xF6, 0x80, 0x92, 0xF9, 0x04, 0x50, 0x8D, 0x42, 0x40, 0xF3, +0x40, 0x81, 0xD3, 0x78, 0x92, 0x78, 0x9B, 0x1A, 0x19, 0x44, 0x40, 0xFA, 0x81, 0xF0, 0x80, 0xF3, 0x04, 0x00, 0x40, 0xEA, +0x04, 0x10, 0xC0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x28, 0x0C, 0xD9, 0x07, 0x29, 0x2C, 0xD8, 0x04, 0x29, 0x0A, 0xD8, +0x7B, 0x4B, 0x93, 0xF8, 0xC3, 0x30, 0xA3, 0xF1, 0x0B, 0x05, 0xB5, 0xFA, 0x85, 0xF5, 0x6D, 0x09, 0x09, 0xE0, 0x09, 0x29, +0xF4, 0xD9, 0x76, 0x4B, 0x93, 0xF8, 0xC4, 0x30, 0x0A, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, 0x0A, 0x23, 0x75, 0x49, +0x41, 0xF2, 0xC8, 0x42, 0x94, 0x42, 0xC8, 0x5C, 0xAB, 0xD8, 0x73, 0x4A, 0x92, 0xF9, 0x00, 0x20, 0xAE, 0xE7, 0x09, 0x29, +0x26, 0xD8, 0x6C, 0x4B, 0x93, 0xF8, 0xBF, 0x50, 0x0B, 0x2D, 0x00, 0xF0, 0xF0, 0x80, 0x6F, 0x4B, 0x00, 0x22, 0x5B, 0x5D, +0x11, 0x46, 0x01, 0x27, 0x68, 0xE7, 0x66, 0x4B, 0x93, 0xF8, 0xC5, 0x30, 0x09, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0xA8, 0xBF, +0x09, 0x23, 0xDE, 0xE7, 0x01, 0x28, 0xE6, 0xD0, 0x07, 0x29, 0x0B, 0xD9, 0x5F, 0x4A, 0x65, 0x4B, 0x92, 0xF8, 0xC1, 0x50, +0x0A, 0x2D, 0xA8, 0xBF, 0x0A, 0x25, 0x00, 0x22, 0x5B, 0x5D, 0x11, 0x46, 0x01, 0x27, 0x4F, 0xE7, 0x04, 0x29, 0xD8, 0xD9, +0x58, 0x4A, 0x5E, 0x4B, 0x92, 0xF8, 0xC0, 0x50, 0xA5, 0xF1, 0x0B, 0x01, 0xB1, 0xFA, 0x81, 0xF1, 0x5B, 0x5D, 0x00, 0x22, +0x49, 0x09, 0x01, 0x27, 0x40, 0xE7, 0x40, 0xF6, 0x94, 0x10, 0x84, 0x42, 0x52, 0x48, 0x94, 0xBF, 0x90, 0xF9, 0x01, 0x60, +0x90, 0xF9, 0x02, 0x60, 0x00, 0x29, 0x7F, 0xF4, 0x40, 0xAF, 0x06, 0xF1, 0x0F, 0x01, 0x1E, 0x29, 0xA8, 0xBF, 0x1E, 0x21, +0x0B, 0x2D, 0x21, 0xEA, 0xE1, 0x74, 0x4F, 0xEA, 0x23, 0x10, 0x29, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xA8, 0xBF, 0x0B, 0x21, +0x00, 0x2F, 0x3B, 0xD1, 0x0A, 0x2D, 0x2C, 0xDC, 0x48, 0xD0, 0x49, 0x4D, 0x01, 0xEB, 0x41, 0x01, 0x15, 0xF9, 0x11, 0x60, +0xB4, 0x42, 0x05, 0xEB, 0x41, 0x01, 0x34, 0xDC, 0x49, 0x78, 0x89, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, +0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x83, 0xF3, 0x04, 0x03, 0x43, 0xEA, 0x00, 0x13, 0xD8, 0xB2, +0x00, 0x2A, 0x3F, 0xF4, 0x11, 0xAF, 0x82, 0x42, 0xBF, 0xF6, 0x0E, 0xAF, 0xD0, 0xB2, 0xF0, 0xBC, 0x70, 0x47, 0x41, 0xF2, +0x44, 0x62, 0x94, 0x42, 0x33, 0x4A, 0x94, 0xBF, 0x92, 0xF9, 0x02, 0x20, 0x92, 0xF9, 0x03, 0x20, 0x2C, 0xE7, 0x01, 0x36, +0x2A, 0xDA, 0xA4, 0xF1, 0x0D, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x02, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, +0x1B, 0x19, 0xDA, 0xE7, 0x0A, 0x2D, 0xD8, 0xDC, 0x58, 0xD0, 0x01, 0x31, 0xC1, 0xE7, 0x91, 0xF9, 0x04, 0x50, 0xAC, 0x42, +0x1E, 0xDA, 0xCD, 0x78, 0x89, 0x78, 0x69, 0x1A, 0x21, 0x44, 0x43, 0xFA, 0x81, 0xF3, 0xCA, 0xE7, 0xB1, 0x1C, 0x2B, 0xDB, +0x01, 0x2E, 0x76, 0xDC, 0xA4, 0xF1, 0x0F, 0x01, 0x43, 0xFA, 0x81, 0xF3, 0xC1, 0xE7, 0x1F, 0x4B, 0x08, 0xBF, 0xD4, 0x22, +0x5B, 0x5D, 0x00, 0x21, 0x01, 0x27, 0xC7, 0xE6, 0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, +0x03, 0x33, 0xB2, 0xE7, 0x49, 0x79, 0x49, 0x1B, 0x21, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, +0x01, 0x30, 0xA8, 0xE7, 0x53, 0x78, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, +0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0x08, 0xE7, 0xA4, 0xF1, 0x0A, 0x01, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x04, 0x01, 0x38, +0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x91, 0xE7, 0x00, 0xBF, 0xBC, 0x34, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, +0xEC, 0x12, 0x17, 0x00, 0x68, 0x25, 0x17, 0x00, 0x04, 0x13, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x0C, 0x79, 0x15, 0x00, +0xF8, 0x12, 0x17, 0x00, 0xB8, 0x78, 0x15, 0x00, 0x03, 0x36, 0x35, 0xDA, 0xA4, 0xF1, 0x09, 0x01, 0x49, 0xB2, 0x6F, 0xF0, +0x04, 0x04, 0x01, 0x38, 0xA1, 0x42, 0xAC, 0xBF, 0x5B, 0x18, 0x1B, 0x19, 0x71, 0xE7, 0x01, 0x21, 0x0F, 0x46, 0x00, 0x22, +0x0F, 0x23, 0x79, 0xE6, 0x03, 0x32, 0x09, 0xDA, 0x09, 0x39, 0x49, 0xB2, 0x6F, 0xF0, 0x04, 0x03, 0x01, 0x3C, 0x99, 0x42, +0xAC, 0xBF, 0x40, 0x18, 0xC0, 0x18, 0xCC, 0xE6, 0x0F, 0x39, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, +0xC5, 0xE6, 0x53, 0x79, 0x5B, 0x1B, 0x19, 0x44, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x40, 0x18, 0x05, 0x30, 0x01, 0x34, +0xBB, 0xE6, 0xA4, 0xF1, 0x11, 0x01, 0x49, 0xB2, 0x03, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x03, 0x33, 0x02, 0x30, 0x46, 0xE7, +0xA4, 0xF1, 0x0F, 0x01, 0x49, 0xB2, 0x05, 0x29, 0xD4, 0xBF, 0x5B, 0x18, 0x05, 0x33, 0x3E, 0xE7, 0x14, 0x22, 0xF6, 0x23, +0x02, 0x70, 0x0B, 0x70, 0x70, 0x47, 0x00, 0xBF, 0x08, 0xB5, 0x09, 0x49, 0x09, 0x48, 0x22, 0xF0, 0xF3, 0xFD, 0x09, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x05, 0x49, 0x06, 0x48, +0x39, 0x22, 0x23, 0xF0, 0x5F, 0xB8, 0x00, 0xBF, 0x50, 0x79, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x1F, 0x49, 0x20, 0x4A, 0x88, 0x68, 0x20, 0x4B, 0x10, 0xB4, 0xD2, 0xF8, +0x14, 0x44, 0x04, 0x65, 0x10, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0x44, 0x65, 0x20, 0x20, 0x18, 0x60, +0x88, 0x68, 0xD2, 0xF8, 0xA0, 0x42, 0xC4, 0x65, 0x80, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0xD8, 0x40, 0x84, 0x64, +0x04, 0x20, 0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x0C, 0x44, 0xC4, 0x64, 0xF8, 0x24, 0x08, 0x20, 0x83, 0xF8, 0x03, 0x43, +0x18, 0x60, 0x88, 0x68, 0xD2, 0xF8, 0x1C, 0x41, 0xC0, 0xF8, 0x0C, 0x41, 0x4F, 0xF4, 0x00, 0x20, 0x58, 0x60, 0x89, 0x68, +0xD2, 0xF8, 0x2C, 0x21, 0xC1, 0xF8, 0x10, 0x21, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x41, 0x4F, 0xF4, 0x00, 0x12, +0x58, 0x60, 0x99, 0x60, 0x1A, 0x60, 0x62, 0xB6, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, +0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x33, 0x49, 0x34, 0x4B, 0x0A, 0x68, 0x00, 0x28, 0x22, 0xF4, 0x00, 0x62, +0xF0, 0xB5, 0x32, 0x4D, 0x0A, 0x60, 0x06, 0xBF, 0x1D, 0x46, 0x30, 0x26, 0x20, 0x26, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, +0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x2A, 0x4F, 0x2C, 0x4C, 0x3A, 0x68, 0x22, 0xF4, 0x80, 0x52, 0x3A, 0x60, 0x3A, 0x68, +0x42, 0xF4, 0x80, 0x62, 0x3A, 0x60, 0x3A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x3A, 0x60, 0xB6, 0x00, 0x19, 0x46, 0x3A, 0x46, +0x4F, 0xF0, 0xFF, 0x0E, 0xC8, 0x1C, 0xC0, 0xB2, 0xAC, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, 0x13, 0x60, +0x5C, 0xF8, 0x04, 0x3B, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, +0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x38, 0xC0, 0xB2, 0x70, 0x45, 0xE8, 0xD1, 0x04, 0x31, 0x04, 0x30, +0xB1, 0x42, 0x5F, 0xFA, 0x80, 0xFE, 0x05, 0xF1, 0x10, 0x05, 0xDD, 0xD1, 0x3B, 0x68, 0x23, 0xF4, 0x80, 0x63, 0x3B, 0x60, +0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, +0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, +0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xF0, 0xBD, 0x00, 0xBF, 0x60, 0x40, 0x34, 0x40, +0x1C, 0x13, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x44, 0x4A, 0x45, 0x49, 0x13, 0x68, 0xF0, 0xB4, +0x44, 0x4D, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x00, 0x28, 0x0C, 0xBF, 0x28, 0x46, 0x08, 0x46, 0x32, 0x23, 0x00, 0xBF, +0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x3B, 0x4A, 0x3E, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x13, 0x60, +0x13, 0x68, 0x43, 0xF4, 0x80, 0x63, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x03, 0x21, 0xA0, 0xF1, +0x0C, 0x04, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x54, 0xF8, 0x21, 0x30, 0x2B, 0x60, 0x13, 0x68, +0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9E, 0x04, 0xFC, 0xD5, +0x04, 0x31, 0x43, 0x29, 0xE9, 0xD1, 0x28, 0x4B, 0x2B, 0x4E, 0x2A, 0x4D, 0x04, 0x1F, 0x02, 0x21, 0x1A, 0x68, 0x22, 0xF0, +0xFF, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, +0x00, 0xBF, 0x1A, 0x68, 0x90, 0x04, 0xFC, 0xD5, 0x37, 0x68, 0x54, 0xF8, 0x21, 0x20, 0x18, 0x68, 0x27, 0xF0, 0x7F, 0x47, +0x02, 0xF0, 0x7F, 0x42, 0x20, 0xF0, 0xFF, 0x00, 0x3A, 0x43, 0x08, 0x43, 0x18, 0x60, 0x2A, 0x60, 0x1A, 0x68, 0x42, 0xF4, +0x80, 0x72, 0x1A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x1A, 0x68, 0x92, 0x04, 0xFC, 0xD5, 0x04, 0x31, +0x42, 0x29, 0xD3, 0xD1, 0x1A, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x1A, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, +0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, +0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, +0x00, 0x62, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x1C, 0x16, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, +0x64, 0x40, 0x34, 0x40, 0x68, 0x40, 0x34, 0x40, 0x2C, 0x49, 0x2D, 0x4B, 0x0A, 0x68, 0x30, 0xB4, 0x2C, 0x4C, 0x00, 0x28, +0x22, 0xF4, 0x80, 0x72, 0x0C, 0xBF, 0x18, 0x46, 0x20, 0x46, 0x0A, 0x60, 0x0C, 0xBF, 0x20, 0x24, 0x10, 0x24, 0x32, 0x23, +0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x22, 0x49, 0x24, 0x4D, 0x0A, 0x68, 0x22, 0xF4, 0x00, 0x72, +0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x04, 0x38, 0x0A, 0x60, +0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, +0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, 0x01, 0x33, +0x9C, 0x42, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, +0xFF, 0x03, 0xFA, 0xD1, 0x0A, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, +0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x05, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, +0x80, 0x72, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x6C, 0x40, 0x34, 0x40, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, +0x70, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0xA6, 0x49, 0xA7, 0x4C, 0xA7, 0x4B, 0xA8, 0x4A, 0xDF, 0xF8, 0xE8, 0xE2, +0x00, 0x28, 0x0E, 0xBF, 0xA4, 0x46, 0x8C, 0x46, 0x9E, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xA3, 0x4C, 0xA4, 0x49, +0x23, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x23, 0x60, 0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0xA1, 0x4A, 0x23, 0xF4, 0x00, 0x63, +0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x24, 0x00, 0xBF, 0x01, 0x3C, 0x14, 0xF0, 0xFF, 0x04, +0xFA, 0xD1, 0xDF, 0xF8, 0x64, 0x82, 0x99, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x98, 0x4F, 0x23, 0xF4, 0x80, 0x53, 0xC8, 0xF8, +0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x80, 0x63, 0xC8, 0xF8, +0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0x42, 0x46, 0xFF, 0x26, 0xE1, 0x1C, +0xC9, 0xB2, 0x75, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x55, 0xF8, 0x04, 0x3B, 0x3B, 0x60, +0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, +0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0x8E, 0x42, 0xE8, 0xD1, 0x04, 0x34, 0x04, 0x36, 0x80, 0x2C, 0xF6, 0xB2, 0x0E, 0xF1, +0x10, 0x0E, 0xDE, 0xD1, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xC8, 0xF8, 0x00, 0x30, 0xC8, 0x23, 0x00, 0xBF, +0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x74, 0x4C, 0x75, 0x49, 0x22, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x22, 0x60, +0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x72, 0x10, 0x34, 0xAC, 0xF1, 0x04, 0x0C, +0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x5C, 0xF8, 0x04, 0x2F, 0x22, 0x60, 0x0A, 0x68, +0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, 0xFC, 0xD5, +0x01, 0x33, 0x10, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, +0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x5D, 0x49, 0x5E, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x0B, 0x60, 0x13, 0x68, +0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x03, 0xFA, 0xD1, 0x54, 0x49, +0x54, 0x4B, 0x0C, 0x68, 0x56, 0x4A, 0x57, 0x4D, 0x44, 0xF4, 0x80, 0x54, 0x0C, 0x60, 0x1C, 0x68, 0x44, 0xF4, 0x00, 0x74, +0x1C, 0x60, 0x0C, 0x68, 0x44, 0xF4, 0x00, 0x64, 0x0C, 0x60, 0x19, 0x68, 0x51, 0x4C, 0x41, 0xF4, 0x80, 0x71, 0x19, 0x60, +0x11, 0x68, 0x50, 0x4B, 0x41, 0xF4, 0x80, 0x51, 0x11, 0x60, 0x29, 0x68, 0x21, 0xF4, 0x80, 0x21, 0x29, 0x60, 0x21, 0x68, +0x21, 0xF0, 0x00, 0x51, 0x21, 0x60, 0xA5, 0xF5, 0xBC, 0x45, 0x1C, 0x68, 0x2C, 0x60, 0x49, 0x49, 0x5D, 0x68, 0x0D, 0x60, +0x48, 0x4C, 0x9D, 0x68, 0x25, 0x60, 0xDD, 0x68, 0x8D, 0x60, 0x1D, 0x69, 0xA5, 0x60, 0x5C, 0x69, 0x0C, 0x61, 0xD3, 0xE9, +0x06, 0x64, 0x44, 0x4D, 0x44, 0x4B, 0x2E, 0x60, 0x8C, 0x61, 0x9B, 0x78, 0x18, 0x31, 0xCB, 0xB1, 0xA5, 0xF6, 0x78, 0x65, +0x41, 0x4C, 0x2B, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x2B, 0x60, 0x23, 0x68, 0x01, 0xF5, 0xBB, 0x41, +0x7C, 0x31, 0x43, 0xF0, 0x80, 0x63, 0x23, 0x60, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, +0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x36, 0x4B, 0x93, 0xF8, 0xFA, 0x30, 0x38, 0xB9, 0x43, 0xBB, 0x35, 0x4A, +0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0xCB, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, +0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xB5, 0x03, +0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x32, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, +0x43, 0xF4, 0x32, 0x23, 0x13, 0x60, 0x24, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, +0x21, 0x49, 0x22, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, +0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x0B, 0x60, +0x13, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x13, 0x60, 0xBB, 0xE7, 0x00, 0xBF, 0x9C, 0x18, 0x17, 0x00, +0x1C, 0x18, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x60, 0x40, 0x34, 0x40, +0x6C, 0x40, 0x34, 0x40, 0x64, 0x40, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, +0x1C, 0x20, 0x34, 0x40, 0xDC, 0x18, 0x17, 0x00, 0x1C, 0xC2, 0x33, 0x40, 0x20, 0xC2, 0x33, 0x40, 0x30, 0xC2, 0x33, 0x40, +0x3C, 0x36, 0x17, 0x00, 0x38, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0xAC, 0xB3, 0x33, 0x40, +0xD4, 0xB3, 0x33, 0x40, 0x1C, 0x13, 0x17, 0x00, 0x10, 0xB4, 0x1C, 0x4B, 0x1C, 0x4C, 0x0F, 0xCB, 0x85, 0xB0, 0x0D, 0xF1, +0x10, 0x0C, 0x0C, 0xE9, 0x0F, 0x00, 0x63, 0x68, 0xDB, 0x06, 0x16, 0xD5, 0x61, 0x68, 0xA3, 0x69, 0x5C, 0xFA, 0x83, 0xF3, +0xC8, 0x04, 0x13, 0xF8, 0x10, 0x2C, 0x22, 0xD4, 0x60, 0x68, 0x14, 0x49, 0x14, 0x4B, 0x10, 0xF4, 0x80, 0x7F, 0x08, 0xBF, +0x0B, 0x46, 0x11, 0x06, 0x44, 0xBF, 0x5B, 0x00, 0x02, 0xF0, 0x7F, 0x02, 0xB3, 0xFB, 0xF2, 0xF3, 0x00, 0xE0, 0x0F, 0x4B, +0x0B, 0x4A, 0x0F, 0x4C, 0x52, 0x69, 0x0F, 0x48, 0x0F, 0x49, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x23, 0x60, 0xD0, 0xF8, +0x84, 0x20, 0xD2, 0xB2, 0xB3, 0xFB, 0xF2, 0xF3, 0x0B, 0x60, 0x05, 0xB0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x09, 0x4B, +0xE1, 0xE7, 0x00, 0xBF, 0x60, 0x79, 0x15, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x38, 0x9C, 0x1C, 0x00, 0xD0, 0x12, 0x13, +0x00, 0x75, 0x19, 0x03, 0x18, 0x13, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, 0x00, 0x70, 0x38, 0x39, +0x70, 0xB4, 0x5D, 0x4C, 0x5D, 0x48, 0x23, 0x68, 0x5D, 0x4D, 0x5E, 0x49, 0x5E, 0x4A, 0x23, 0xF4, 0xC0, 0x63, 0x43, 0xF4, +0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x95, 0xF8, 0xFA, 0x40, 0x23, 0xF4, 0xBC, 0x03, 0x23, 0xF4, 0x70, 0x53, 0x43, 0xF4, +0x60, 0x23, 0x43, 0xF4, 0x80, 0x63, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x60, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, +0xFE, 0x33, 0x43, 0xF4, 0x98, 0x33, 0x13, 0x60, 0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0xF5, 0x11, 0x12, 0xA2, 0xF6, +0x4C, 0x52, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x13, 0x60, 0x4C, 0x4D, 0x4C, 0x48, 0x2B, 0x68, 0x4C, 0x4C, 0x4D, 0x4A, +0x4D, 0x49, 0x4E, 0x4E, 0x43, 0xF0, 0x80, 0x63, 0x2B, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x63, 0x03, 0x60, 0x23, 0x68, +0x23, 0xF4, 0x7F, 0x73, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x80, 0x53, 0x43, 0xF4, 0x00, 0x63, +0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xCC, 0x03, 0x43, 0xF0, 0xC4, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x7F, 0x43, +0xA5, 0xF5, 0xF8, 0x55, 0x43, 0xF4, 0x78, 0x13, 0x0C, 0x3D, 0x43, 0xF4, 0x78, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x1B, 0x0C, +0xA4, 0xF5, 0x00, 0x54, 0x1B, 0x04, 0x34, 0x3C, 0x43, 0xF0, 0x84, 0x03, 0x2B, 0x60, 0x23, 0x68, 0x37, 0x4D, 0x23, 0xF4, +0x40, 0x63, 0x43, 0xF4, 0x00, 0x63, 0x23, 0x60, 0xD0, 0xF8, 0x04, 0x31, 0x02, 0xF5, 0xF8, 0x52, 0x23, 0xF4, 0xE0, 0x23, +0x18, 0x32, 0x43, 0xF4, 0x80, 0x33, 0xC0, 0xF8, 0x04, 0x31, 0x13, 0x68, 0x23, 0xF0, 0x76, 0x53, 0x23, 0xF0, 0x07, 0x03, +0x01, 0xF5, 0xF7, 0x51, 0x43, 0xF0, 0x04, 0x53, 0x04, 0x31, 0x43, 0xF0, 0x07, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x04, 0xF5, +0x00, 0x54, 0x02, 0xF1, 0xEF, 0x52, 0x00, 0xF5, 0x01, 0x50, 0x1C, 0x34, 0x02, 0xF5, 0x3D, 0x22, 0x02, 0xF6, 0x44, 0x02, +0x1D, 0x40, 0x08, 0x30, 0x22, 0x4B, 0x0D, 0x60, 0x32, 0x60, 0x23, 0x60, 0x03, 0x68, 0x21, 0x4A, 0x21, 0x4C, 0x23, 0xF4, +0x7F, 0x23, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF4, 0x32, 0x33, 0x03, 0x60, 0xCB, 0x68, 0x43, 0xF4, 0x00, 0x63, 0xCB, 0x60, +0x13, 0x68, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x07, 0x08, 0xD5, 0xA2, 0xF5, +0x0F, 0x12, 0xA2, 0xF5, 0x03, 0x52, 0x24, 0x3A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x53, 0x13, 0x60, 0x70, 0xBC, 0x70, 0x47, +0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0xC0, 0x63, 0x43, 0xF0, 0x00, 0x73, 0x13, 0x60, 0x70, 0xE7, 0x20, 0x40, 0x34, 0x40, +0x24, 0x40, 0x34, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x28, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, 0x38, 0x40, 0x34, 0x40, +0x30, 0x20, 0x34, 0x40, 0x48, 0x40, 0x34, 0x40, 0x28, 0x21, 0x34, 0x40, 0x24, 0x21, 0x34, 0x40, 0x2C, 0x40, 0x34, 0x40, +0x03, 0x00, 0x00, 0xFF, 0x08, 0x51, 0x2E, 0x1A, 0x08, 0x01, 0x58, 0x40, 0x94, 0x40, 0x04, 0x40, 0xB8, 0xB3, 0x33, 0x40, +0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, +0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xDE, 0x73, 0x1B, 0x68, +0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, +0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, +0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE6, 0x73, 0x1B, 0x68, +0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, +0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4D, +0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xE8, 0x73, 0x1B, 0x68, +0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, +0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x0D, 0x4D, +0x0D, 0x4C, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4F, 0xF4, 0xEA, 0x73, 0x1B, 0x68, +0x98, 0x47, 0x01, 0x23, 0x23, 0x60, 0x2B, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x5C, 0x40, 0x04, 0x40, +0x2D, 0xE9, 0xF0, 0x47, 0x4C, 0x4B, 0x4D, 0x4D, 0x08, 0x22, 0xC3, 0xF8, 0x00, 0x21, 0xAB, 0x78, 0x33, 0xB9, 0x4B, 0x4A, +0x93, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x43, 0xF4, 0x00, 0x33, 0x93, 0x60, 0x47, 0x4A, 0x13, 0x6B, 0x03, 0xF0, 0x22, 0x03, +0x02, 0x2B, 0xFA, 0xD1, 0x93, 0x68, 0x45, 0x4C, 0x41, 0x49, 0x45, 0x48, 0x23, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x01, 0x13, +0x43, 0xF4, 0x04, 0x43, 0x93, 0x60, 0x06, 0x23, 0x23, 0x60, 0x53, 0x6D, 0x40, 0x4C, 0x23, 0xF4, 0x40, 0x13, 0x53, 0x65, +0x4F, 0xF4, 0x00, 0x63, 0xC1, 0xF8, 0x34, 0x31, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x03, +0x01, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x08, 0xD1, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, +0x09, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x2E, 0x49, 0x2C, 0x4E, 0x0B, 0x68, 0x0A, 0x68, +0x30, 0x48, 0xC3, 0xF3, 0x09, 0x03, 0x22, 0xF4, 0x7F, 0x72, 0x22, 0xF0, 0x03, 0x02, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x43, +0x0B, 0x60, 0x73, 0x6F, 0x2B, 0x4A, 0x43, 0xF0, 0x02, 0x03, 0x73, 0x67, 0x03, 0x68, 0x2A, 0x4E, 0x23, 0xF4, 0x00, 0x63, +0x03, 0x60, 0x13, 0x68, 0x96, 0xF8, 0xA9, 0x00, 0x43, 0xF0, 0x80, 0x73, 0x13, 0x60, 0x68, 0xB1, 0x0B, 0x6B, 0x5F, 0x06, +0x05, 0xD4, 0x0B, 0x6B, 0x58, 0x07, 0x02, 0xD5, 0x22, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x1A, 0x4B, 0x1A, 0x6B, 0x52, 0x06, +0x40, 0xF1, 0x10, 0x82, 0x1F, 0x4B, 0xD6, 0xF8, 0xA0, 0x20, 0x1A, 0x60, 0xAB, 0x78, 0x00, 0x2B, 0x3E, 0xD0, 0x1D, 0x4B, +0x1A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x6C, 0x82, 0x11, 0x4B, 0x0E, 0x48, 0x02, 0x21, 0x11, 0x70, 0x1A, 0x6D, +0xA9, 0x78, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x02, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x61, 0x5A, 0x6A, 0x22, 0xF0, +0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, +0x00, 0x29, 0x33, 0xD0, 0x03, 0xF0, 0xB0, 0xFC, 0x0C, 0x4F, 0x33, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x3C, 0x36, 0x17, 0x00, +0x00, 0x60, 0x50, 0x40, 0x10, 0x00, 0x58, 0x40, 0x00, 0xFC, 0xFF, 0xFF, 0x78, 0x36, 0x17, 0x00, 0x00, 0x01, 0x58, 0x40, +0x20, 0x01, 0x58, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x74, 0x36, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0xC0, 0x4B, 0xC1, 0x49, 0x1A, 0x6D, 0x42, 0xF4, 0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, +0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, 0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, +0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0xB7, 0x4F, 0xD7, 0xF8, 0xCC, 0x30, 0x98, 0x47, 0x03, 0xF0, 0xF4, 0xF9, +0xD7, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xB2, 0x4B, 0xB3, 0x49, 0x1B, 0x68, 0xB3, 0x4A, 0xA8, 0x78, 0x1B, 0x0C, 0x0B, 0x70, +0x04, 0x23, 0x1B, 0x68, 0x1B, 0x09, 0x13, 0x70, 0x10, 0xB9, 0xD7, 0xF8, 0x80, 0x34, 0x98, 0x47, 0xAE, 0x48, 0xAF, 0x4D, +0xFF, 0xF7, 0x78, 0xFE, 0xAE, 0x48, 0xFF, 0xF7, 0x9D, 0xFE, 0x03, 0x46, 0x1A, 0x0C, 0xAD, 0x49, 0x2A, 0x70, 0x1B, 0x0F, +0x02, 0x22, 0x0B, 0x70, 0xAB, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0xE2, 0xFE, 0x4F, 0xF4, 0x80, 0x52, 0x11, 0x46, 0xA9, 0x48, +0xFF, 0xF7, 0xDC, 0xFE, 0xA8, 0x4A, 0xA9, 0x49, 0xA9, 0x48, 0xFF, 0xF7, 0xD7, 0xFE, 0x2B, 0x78, 0x01, 0x2B, 0x00, 0xF0, +0x8E, 0x81, 0xA7, 0x48, 0x4F, 0xF4, 0x7F, 0x52, 0x4F, 0xF4, 0x9E, 0x51, 0xFF, 0xF7, 0xCC, 0xFE, 0x04, 0x22, 0xA4, 0x48, +0x11, 0x46, 0xFF, 0xF7, 0xC7, 0xFE, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x04, 0xD0, 0xA1, 0x48, 0x07, 0x22, 0x00, 0x21, +0xFF, 0xF7, 0xBE, 0xFE, 0x01, 0x21, 0x02, 0x20, 0x03, 0xF0, 0x5C, 0xFE, 0x04, 0x22, 0x9D, 0x48, 0x00, 0x21, 0xFF, 0xF7, +0xB5, 0xFE, 0x01, 0x21, 0x03, 0x20, 0x03, 0xF0, 0x53, 0xFE, 0x08, 0x22, 0x98, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0xAC, 0xFE, +0x00, 0x21, 0x05, 0x20, 0x03, 0xF0, 0x4A, 0xFE, 0x95, 0x48, 0x20, 0x22, 0x00, 0x21, 0xFF, 0xF7, 0xA3, 0xFE, 0x20, 0x22, +0x11, 0x46, 0x93, 0x48, 0xFF, 0xF7, 0x9E, 0xFE, 0x20, 0x22, 0x11, 0x46, 0x91, 0x48, 0xFF, 0xF7, 0x99, 0xFE, 0x02, 0x22, +0x90, 0x48, 0x11, 0x46, 0xFF, 0xF7, 0x94, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x00, 0xF0, +0x60, 0x00, 0x20, 0x28, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0xF4, 0xFC, 0x02, 0x11, 0x46, 0x89, 0x48, 0xFF, 0xF7, 0x84, 0xFE, +0x88, 0x4A, 0x89, 0x48, 0x4F, 0xF0, 0x46, 0x41, 0xFF, 0xF7, 0x7E, 0xFE, 0x87, 0x48, 0x3F, 0x22, 0x1F, 0x21, 0xFF, 0xF7, +0x79, 0xFE, 0x4F, 0xF4, 0x80, 0x22, 0x85, 0x48, 0x00, 0x21, 0xFF, 0xF7, 0x73, 0xFE, 0x84, 0x48, 0x4F, 0xF4, 0x8E, 0x71, +0xFF, 0xF7, 0x46, 0xFE, 0x82, 0x48, 0x4F, 0xF4, 0xF8, 0x22, 0x4F, 0xF4, 0xD8, 0x21, 0xFF, 0xF7, 0x67, 0xFE, 0x40, 0x22, +0x11, 0x46, 0x7F, 0x48, 0xFF, 0xF7, 0x62, 0xFE, 0x4F, 0xF4, 0xC0, 0x32, 0x11, 0x46, 0x7D, 0x48, 0xFF, 0xF7, 0x5C, 0xFE, +0x7C, 0x48, 0x4F, 0xF4, 0xE0, 0x62, 0x4F, 0xF4, 0x00, 0x71, 0xFF, 0xF7, 0x55, 0xFE, 0x96, 0xF8, 0xC7, 0x70, 0xB7, 0xB3, +0x78, 0x4A, 0x96, 0xF8, 0xC8, 0x10, 0x78, 0x4B, 0x96, 0xF8, 0xC9, 0x00, 0x11, 0x70, 0x96, 0xF8, 0xCA, 0x10, 0x50, 0x70, +0x91, 0x70, 0x96, 0xF8, 0xCB, 0x50, 0x96, 0xF8, 0xCC, 0x00, 0x96, 0xF8, 0xCD, 0x10, 0x96, 0xF8, 0xCE, 0x20, 0x1D, 0x70, +0x58, 0x70, 0x99, 0x70, 0xDA, 0x70, 0x4F, 0xF4, 0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xF4, 0x60, 0x2F, +0xC0, 0xF3, 0x42, 0x41, 0x0E, 0xD0, 0x6A, 0x4A, 0x8D, 0x01, 0x02, 0xF1, 0x40, 0x00, 0x52, 0xF8, 0x04, 0x3F, 0x23, 0xF4, +0xE0, 0x73, 0x2B, 0x43, 0x90, 0x42, 0x13, 0x60, 0xF7, 0xD1, 0x65, 0x48, 0x03, 0xF0, 0x68, 0xFD, 0x23, 0x68, 0x1C, 0x78, +0x01, 0x2C, 0x00, 0xF0, 0xEF, 0x80, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0xD2, 0x76, 0x0A, 0x20, 0x33, 0x68, 0xDF, 0xF8, +0x6C, 0xA1, 0x98, 0x47, 0x33, 0x68, 0x05, 0x46, 0x0B, 0x20, 0x98, 0x47, 0x33, 0x68, 0x80, 0x46, 0x0F, 0x20, 0x98, 0x47, +0x5F, 0xEA, 0x95, 0x7C, 0x3A, 0x46, 0x0C, 0xBF, 0x4F, 0xF0, 0x08, 0x09, 0x4F, 0xF0, 0x10, 0x09, 0x4F, 0xEA, 0x15, 0x6E, +0xD3, 0x00, 0x25, 0xFA, 0x03, 0xF3, 0xDF, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x38, 0xD1, 0x00, 0x2B, +0x54, 0xD1, 0x00, 0x2F, 0x40, 0xF0, 0x1F, 0x81, 0x01, 0x32, 0x03, 0x2A, 0xEE, 0xD1, 0xDF, 0xF8, 0x24, 0xE1, 0x07, 0x0E, +0x00, 0x21, 0xCB, 0x00, 0x28, 0xFA, 0x03, 0xF3, 0xDE, 0xB2, 0xC3, 0xF3, 0x03, 0x13, 0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, +0xEB, 0xB1, 0x08, 0x22, 0x93, 0x42, 0x28, 0xBF, 0xD3, 0x1A, 0x5B, 0xB2, 0x0E, 0xF8, 0x01, 0x30, 0x01, 0x31, 0x04, 0x29, +0xEB, 0xD1, 0x9C, 0xE7, 0x4D, 0x00, 0x6A, 0x1C, 0x47, 0xFA, 0x02, 0xF2, 0x12, 0x01, 0x02, 0xF0, 0x10, 0x02, 0x13, 0x43, +0x13, 0xF0, 0xFF, 0x03, 0x1F, 0xD1, 0x47, 0xFA, 0x05, 0xF3, 0x1B, 0x01, 0x03, 0xF0, 0x10, 0x03, 0x06, 0xF0, 0x0F, 0x06, +0x1E, 0x43, 0x00, 0x2E, 0xE6, 0xD0, 0x33, 0x46, 0x4A, 0x46, 0xDD, 0xE7, 0x56, 0x00, 0x71, 0x1C, 0x4E, 0xFA, 0x01, 0xF1, +0x09, 0x01, 0x01, 0xF0, 0x10, 0x01, 0x0B, 0x43, 0x13, 0xF0, 0xFF, 0x03, 0x09, 0xD0, 0x10, 0x21, 0x8B, 0x42, 0x28, 0xBF, +0xCB, 0x1A, 0x5B, 0xB2, 0x0A, 0xF8, 0x02, 0x30, 0xB8, 0xE7, 0x10, 0x22, 0xC8, 0xE7, 0x4E, 0xFA, 0x06, 0xF3, 0x1B, 0x01, +0x03, 0xF0, 0x10, 0x03, 0x07, 0xF0, 0x0F, 0x07, 0x1F, 0x43, 0xAA, 0xE7, 0x08, 0x21, 0xEB, 0xE7, 0x00, 0x60, 0x50, 0x40, +0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x11, 0x13, 0x17, 0x00, 0x12, 0x13, 0x17, 0x00, 0x04, 0x02, 0x22, 0x03, +0x10, 0x13, 0x17, 0x00, 0x00, 0x00, 0x01, 0x50, 0x70, 0x25, 0x17, 0x00, 0x50, 0x91, 0x01, 0x50, 0x20, 0x91, 0x01, 0x50, +0xC0, 0xFD, 0x01, 0x00, 0xC0, 0xF1, 0x01, 0x00, 0x24, 0x91, 0x01, 0x50, 0x08, 0x88, 0x01, 0x50, 0x18, 0x88, 0x01, 0x50, +0x2C, 0x91, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x0C, 0x10, 0x01, 0x50, 0x10, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, +0x00, 0x30, 0x01, 0x50, 0x00, 0x88, 0x01, 0x50, 0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0x28, 0x91, 0x01, 0x50, +0x5C, 0x00, 0x01, 0x50, 0x58, 0x00, 0x01, 0x50, 0x74, 0x91, 0x01, 0x50, 0x18, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, +0x30, 0x88, 0x01, 0x50, 0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x18, 0x18, 0x17, 0x00, 0x74, 0x79, 0x15, 0x00, +0x1B, 0x6B, 0x59, 0x07, 0x7F, 0xF5, 0xEC, 0xAD, 0xD6, 0xF8, 0xA0, 0x30, 0x3F, 0x48, 0x40, 0x49, 0x40, 0x4A, 0x43, 0xF0, +0x00, 0x73, 0x01, 0x27, 0x07, 0x70, 0x0B, 0x60, 0x53, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0xE0, 0xE5, 0x3C, 0x4A, +0x3C, 0x49, 0x3D, 0x48, 0xFF, 0xF7, 0x40, 0xFD, 0x3C, 0x48, 0x4F, 0xF4, 0x08, 0x42, 0x4F, 0xF4, 0x00, 0x41, 0xFF, 0xF7, +0x39, 0xFD, 0x3A, 0x4A, 0x3A, 0x49, 0x3B, 0x48, 0xFF, 0xF7, 0x34, 0xFD, 0x3A, 0x48, 0x8F, 0x22, 0x06, 0x21, 0xFF, 0xF7, +0x2F, 0xFD, 0x66, 0xE6, 0x38, 0x49, 0x39, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0xFF, 0xF7, 0x28, 0xFD, 0x4F, 0xF0, 0xFF, 0x32, +0x36, 0x48, 0x4F, 0xF0, 0x02, 0x11, 0xFF, 0xF7, 0x21, 0xFD, 0x35, 0x49, 0x35, 0x48, 0xFF, 0xF7, 0xF5, 0xFC, 0x22, 0x46, +0x21, 0x46, 0x34, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x16, 0xBD, 0x32, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xFF, 0xF7, +0x11, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x30, 0x48, 0xFF, 0xF7, 0x0C, 0xFD, 0x02, 0x22, 0x11, 0x46, 0x2E, 0x48, 0xFF, 0xF7, +0x07, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x2A, 0x48, 0xFF, 0xF7, 0x01, 0xFD, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, +0x28, 0x48, 0xFF, 0xF7, 0xFB, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x27, 0x48, 0xFF, 0xF7, 0xF6, 0xFC, 0x25, 0x48, 0x4F, 0xF4, +0x00, 0x52, 0x00, 0x21, 0xFF, 0xF7, 0xF0, 0xFC, 0x64, 0xE6, 0x23, 0x4B, 0x0F, 0x49, 0x1A, 0x6D, 0x22, 0x4F, 0x42, 0xF4, +0x80, 0x22, 0x1A, 0x65, 0x0A, 0x69, 0x22, 0xF0, 0x80, 0x02, 0x0A, 0x61, 0x5A, 0x6A, 0x22, 0xF0, 0xFF, 0x02, 0x42, 0xF0, +0xDF, 0x02, 0x5A, 0x62, 0x5A, 0x6A, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x5F, 0x42, 0x5A, 0x62, 0x03, 0xF0, 0x48, 0xFA, +0xCC, 0xE5, 0x3B, 0x46, 0x49, 0x46, 0x1D, 0xE7, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, 0x00, 0x00, 0x50, 0x40, +0xC0, 0x3F, 0x00, 0x40, 0x40, 0x12, 0x00, 0x40, 0x08, 0x88, 0x01, 0x50, 0x04, 0x91, 0x01, 0x50, 0xE0, 0x01, 0x00, 0x22, +0xC0, 0x00, 0x00, 0x02, 0x08, 0x91, 0x01, 0x50, 0x00, 0x91, 0x01, 0x50, 0x00, 0x01, 0x00, 0x03, 0x0C, 0x80, 0x01, 0x50, +0x18, 0x80, 0x01, 0x50, 0x0A, 0x33, 0x41, 0x01, 0x38, 0x91, 0x01, 0x50, 0x04, 0x00, 0x01, 0x50, 0x04, 0x20, 0x01, 0x50, +0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, 0x00, 0x10, 0x01, 0x50, 0x00, 0x60, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x10, 0x4B, 0x11, 0x4A, 0x19, 0x68, 0x21, 0xF4, 0x78, 0x11, 0x41, 0xF4, 0x50, 0x11, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, +0x78, 0x11, 0x41, 0xF4, 0xA0, 0x11, 0x19, 0x60, 0x11, 0x69, 0x18, 0x68, 0x20, 0xF4, 0x78, 0x10, 0x40, 0xF4, 0x50, 0x10, +0x32, 0x31, 0x18, 0x60, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x78, 0x13, +0x43, 0xF4, 0x00, 0x13, 0x13, 0x60, 0x70, 0x47, 0x58, 0x40, 0x34, 0x40, 0x00, 0x10, 0x50, 0x40, 0x1E, 0x49, 0x1F, 0x4A, +0x0B, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x10, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x59, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, +0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x59, 0x07, 0xF6, 0xD5, 0x15, 0x49, 0x15, 0x4A, 0x0B, 0x68, +0x43, 0xF4, 0xC0, 0x23, 0x0B, 0x60, 0x13, 0x68, 0x9B, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, +0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0xF6, 0xD5, 0x0E, 0x4C, 0x0E, 0x48, 0x23, 0x68, 0x0E, 0x4A, 0x0F, 0x49, +0x43, 0xF4, 0x00, 0x33, 0x23, 0x60, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF0, 0x80, 0x73, 0x03, 0x60, 0x13, 0x68, +0x43, 0xF4, 0xA4, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0xA1, 0xBD, 0x00, 0xBF, +0x58, 0x40, 0x34, 0x40, 0x80, 0x40, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, 0x10, 0x00, 0x34, 0x40, 0x30, 0x20, 0x34, 0x40, +0x9C, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0x10, 0x48, 0x23, 0x68, 0x10, 0x49, 0x11, 0x4A, 0x23, 0xF4, 0x05, 0x43, +0x23, 0xF0, 0xEC, 0x03, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x00, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x73, +0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xC0, 0x23, 0x0A, 0x20, 0x13, 0x60, 0xFD, 0xF7, 0xD6, 0xFC, 0xBD, 0xE8, 0x10, 0x40, +0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xBD, 0x00, 0xBF, 0x30, 0x20, 0x34, 0x40, 0x2C, 0x20, 0x34, 0x40, +0x10, 0x00, 0x34, 0x40, 0x58, 0x40, 0x34, 0x40, 0xB8, 0x79, 0x15, 0x00, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, +0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, +0xFA, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0x11, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, +0xFA, 0xD1, 0x13, 0x68, 0xDB, 0x07, 0xF6, 0xD5, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, +0x13, 0x68, 0xDB, 0x07, 0xED, 0xD5, 0x0B, 0x4B, 0x1A, 0x68, 0x53, 0x0C, 0x00, 0x2A, 0xBC, 0xBF, 0x6F, 0xEA, 0x43, 0x43, +0x6F, 0xEA, 0x53, 0x43, 0x03, 0x60, 0xC2, 0xF3, 0x4E, 0x03, 0x12, 0x04, 0x44, 0xBF, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, +0x53, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x84, 0x21, 0x34, 0x40, 0x00, 0x22, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x41, +0x2A, 0x4F, 0x2B, 0x4D, 0x3B, 0x68, 0x2B, 0x4A, 0x23, 0xF4, 0x7F, 0x53, 0x3B, 0x60, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x63, +0x2B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x01, 0x20, 0xFD, 0xF7, 0x72, 0xFC, 0x00, 0x24, 0x26, 0x46, +0x4F, 0xF0, 0x07, 0x08, 0x02, 0x20, 0xFD, 0xF7, 0x6B, 0xFC, 0x2B, 0x68, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x36, 0x06, 0xF1, +0xFF, 0x36, 0x76, 0xB2, 0x1B, 0x06, 0x3B, 0x68, 0x54, 0xBF, 0x01, 0x34, 0x04, 0xF1, 0xFF, 0x34, 0x00, 0x2E, 0x23, 0xF4, +0x7F, 0x53, 0xDC, 0xBF, 0x70, 0x42, 0x43, 0xEA, 0x80, 0x23, 0x64, 0xB2, 0xD4, 0xBF, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xEA, +0x86, 0x23, 0x00, 0x2C, 0xDC, 0xBF, 0x60, 0x42, 0x43, 0xEA, 0x80, 0x13, 0x08, 0xF1, 0xFF, 0x32, 0xCC, 0xBF, 0x43, 0xEA, +0x84, 0x13, 0x43, 0xF4, 0x00, 0x73, 0x12, 0xF0, 0xFF, 0x08, 0x3B, 0x60, 0xD2, 0xD1, 0x0A, 0x48, 0x0A, 0x49, 0x02, 0x68, +0x22, 0xF4, 0x80, 0x62, 0x02, 0x60, 0x0A, 0x68, 0xC3, 0xF3, 0x83, 0x10, 0x22, 0xF0, 0x40, 0x02, 0xC3, 0xF3, 0x83, 0x23, +0x0A, 0x60, 0x43, 0xEA, 0x00, 0x10, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, 0x14, 0x40, 0x34, 0x40, +0x5C, 0x40, 0x34, 0x40, 0x01, 0x28, 0x15, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0x4B, 0x78, 0x10, 0x2B, 0x19, 0xD8, 0x30, 0x23, +0x8B, 0x70, 0x70, 0x47, 0xD2, 0xE9, 0x00, 0x32, 0x00, 0x2B, 0x24, 0xDD, 0x00, 0x2A, 0x37, 0xDB, 0xB3, 0xEB, 0x42, 0x0F, +0x0B, 0x78, 0xCC, 0xBF, 0x10, 0x3B, 0x18, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x10, 0xDA, +0x00, 0x2B, 0x1A, 0xDD, 0x40, 0x23, 0x0B, 0x70, 0x70, 0x47, 0x30, 0x2B, 0x0C, 0xD9, 0x60, 0x2B, 0x1A, 0xD8, 0x92, 0x68, +0x00, 0x2A, 0x28, 0xDB, 0x60, 0x2B, 0xDC, 0xD1, 0x20, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x20, 0x23, 0x0B, 0x70, 0x70, 0x47, +0x18, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x00, 0x2A, 0x1E, 0xDD, 0x0B, 0x78, 0x20, 0x3B, 0x4B, 0x70, 0x70, 0x47, 0x13, 0xF5, +0x00, 0x5F, 0xD4, 0xBF, 0xE0, 0x23, 0xC0, 0x23, 0x0B, 0x70, 0x70, 0x47, 0xC0, 0x2B, 0x09, 0xD8, 0x92, 0x68, 0x00, 0x2A, +0x19, 0xDD, 0x60, 0x23, 0x8B, 0x70, 0x70, 0x47, 0x0B, 0x78, 0x20, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD8, 0x2B, 0x0D, 0xD8, +0xE8, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xB3, 0xEB, 0x42, 0x0F, 0x0B, 0x78, 0xB4, 0xBF, +0x10, 0x33, 0x18, 0x33, 0x4B, 0x70, 0x70, 0x47, 0xD0, 0x23, 0x8B, 0x70, 0x70, 0x47, 0xA0, 0x2B, 0xFA, 0xD1, 0xE0, 0x23, +0x8B, 0x70, 0x70, 0x47, 0x01, 0x28, 0x1D, 0xD0, 0x02, 0x28, 0x08, 0xD0, 0x09, 0x78, 0x01, 0x39, 0x05, 0x29, 0x69, 0xD8, +0xDF, 0xE8, 0x01, 0xF0, 0x3C, 0x42, 0x39, 0x33, 0x2D, 0x2A, 0x10, 0xB4, 0x1C, 0x68, 0xB4, 0xF5, 0x00, 0x5F, 0x19, 0xDA, +0x00, 0x2C, 0x4A, 0xDD, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xAA, 0xBF, 0x03, 0x20, 0x10, 0x33, 0x10, 0x3B, 0x53, 0x70, +0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x1B, 0x68, 0xB3, 0xF5, 0x00, 0x5F, 0x04, 0xDA, 0x00, 0x2B, 0x2B, 0xDD, +0x50, 0x23, 0x13, 0x70, 0x70, 0x47, 0x30, 0x23, 0x13, 0x70, 0x70, 0x47, 0x13, 0x78, 0x01, 0x20, 0x10, 0x33, 0x53, 0x70, +0x08, 0x70, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC8, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x21, 0xDD, +0x70, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0x18, 0xDD, 0x90, 0x23, 0x93, 0x70, 0x70, 0x47, 0x38, 0x23, +0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, 0xF0, 0xDD, 0x20, 0x23, 0x93, 0x70, 0x70, 0x47, 0x9B, 0x68, 0x00, 0x2B, +0xF0, 0xDD, 0x40, 0x23, 0x93, 0x70, 0x70, 0x47, 0x13, 0xF5, 0x00, 0x5F, 0xD4, 0xBF, 0xD0, 0x23, 0xB0, 0x23, 0x13, 0x70, +0x70, 0x47, 0xE0, 0x23, 0x93, 0x70, 0x70, 0x47, 0xC0, 0x23, 0x93, 0x70, 0x70, 0x47, 0x14, 0xF5, 0x00, 0x5F, 0x05, 0xDC, +0x13, 0x78, 0x04, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xB4, 0xE7, 0x5B, 0x68, 0x00, 0x2B, 0x13, 0x78, 0xCC, 0xBF, +0x05, 0x20, 0x06, 0x20, 0x10, 0x3B, 0x53, 0x70, 0x08, 0x70, 0xAA, 0xE7, 0x88, 0x23, 0x93, 0x70, 0x70, 0x47, 0x00, 0xBF, +0x30, 0xB4, 0x0F, 0x29, 0x15, 0x46, 0x1C, 0x46, 0x02, 0x9A, 0x03, 0xD0, 0x30, 0xBC, 0x19, 0x46, 0xFF, 0xF7, 0x1C, 0xBF, +0x13, 0x46, 0x29, 0x46, 0x22, 0x46, 0x30, 0xBC, 0xFF, 0xF7, 0x7A, 0xBF, 0x70, 0xB4, 0x50, 0xEA, 0x01, 0x04, 0x02, 0xD1, +0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x18, 0x18, 0xBF, 0x00, 0x21, 0x03, 0xD1, 0x20, 0xE0, 0xE9, 0xB2, 0x81, 0x42, +0x1D, 0xDA, 0x53, 0xF8, 0x21, 0x40, 0x94, 0x42, 0x01, 0xF1, 0x01, 0x05, 0x03, 0xEB, 0x81, 0x06, 0xF4, 0xDC, 0xC0, 0xB2, +0x88, 0x42, 0x0F, 0xD9, 0x44, 0x1E, 0x61, 0x1A, 0x1C, 0x1F, 0xC9, 0xB2, 0x04, 0xEB, 0x80, 0x04, 0xA4, 0xEB, 0x81, 0x04, +0x03, 0xEB, 0x80, 0x03, 0x53, 0xF8, 0x04, 0x1C, 0x43, 0xF8, 0x04, 0x19, 0xA3, 0x42, 0xF9, 0xD1, 0x32, 0x60, 0x70, 0xBC, +0x70, 0x47, 0x70, 0xBC, 0x43, 0xF8, 0x20, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0xF1, 0xFF, 0x3C, +0x85, 0xB0, 0xCC, 0xF3, 0x47, 0x0C, 0x4F, 0xF0, 0x80, 0x34, 0x48, 0xF2, 0x80, 0x03, 0x01, 0x28, 0xCD, 0xE9, 0x01, 0xC4, +0xAD, 0xF8, 0x0C, 0x30, 0x40, 0xF2, 0x83, 0x80, 0x80, 0x24, 0xA2, 0x46, 0x16, 0x46, 0x00, 0x25, 0x01, 0x23, 0x43, 0xF2, +0xB0, 0x69, 0x8E, 0x46, 0x00, 0x92, 0x18, 0xE0, 0x80, 0x2C, 0x04, 0xBF, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x4F, 0xEA, +0x45, 0x07, 0x04, 0xAA, 0x17, 0x44, 0x04, 0xBF, 0x03, 0xF1, 0xFF, 0x34, 0x01, 0xF8, 0x08, 0x4C, 0x07, 0xF8, 0x07, 0x3C, +0x01, 0x33, 0xDB, 0xB2, 0x98, 0x42, 0x22, 0xD0, 0x04, 0xAA, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x08, 0x4C, 0x37, 0x68, +0x56, 0xF8, 0x04, 0x1F, 0x7F, 0x1A, 0x77, 0x45, 0xE0, 0xDD, 0x80, 0x2C, 0xEE, 0xD0, 0x00, 0x9A, 0x52, 0xF8, 0x24, 0x10, +0x49, 0x45, 0x4F, 0xEA, 0x45, 0x07, 0x04, 0xAA, 0x55, 0xDD, 0x02, 0xEB, 0x45, 0x01, 0x11, 0xF8, 0x07, 0x8C, 0x61, 0x46, +0x0C, 0x44, 0xA0, 0x45, 0x61, 0xDB, 0x01, 0x33, 0xDB, 0xB2, 0x01, 0x35, 0x98, 0x42, 0xED, 0xB2, 0xDC, 0xD1, 0x02, 0x2D, +0x00, 0x9A, 0x68, 0xD9, 0x9D, 0xF8, 0x08, 0x10, 0x80, 0x29, 0x3A, 0xD0, 0x9D, 0xF8, 0x09, 0x30, 0x52, 0xF8, 0x21, 0x40, +0x52, 0xF8, 0x23, 0x50, 0x58, 0x1C, 0x40, 0x1A, 0x64, 0x1B, 0xC0, 0xB2, 0x02, 0xAD, 0x94, 0xFB, 0xF0, 0xF4, 0x01, 0x27, +0xA4, 0xB2, 0x00, 0x26, 0x95, 0xF8, 0x02, 0xE0, 0xBE, 0xF1, 0x80, 0x0F, 0x5F, 0xFA, 0x87, 0xFC, 0x16, 0xD0, 0x95, 0xF8, +0x03, 0x80, 0x52, 0xF8, 0x2E, 0x30, 0x08, 0xF1, 0x01, 0x01, 0xA1, 0xEB, 0x0E, 0x01, 0xC9, 0xB2, 0x52, 0xF8, 0x28, 0xE0, +0x81, 0x42, 0xA3, 0xEB, 0x0E, 0x03, 0x93, 0xFB, 0xF1, 0xF3, 0x9B, 0xB2, 0x32, 0xD8, 0x61, 0xD0, 0x02, 0x2F, 0x05, 0xF1, +0x02, 0x05, 0x34, 0xD1, 0x04, 0xAB, 0x03, 0xEB, 0x46, 0x06, 0x16, 0xF8, 0x08, 0x1C, 0x16, 0xF8, 0x07, 0x3C, 0x5B, 0x1A, +0x01, 0x33, 0x01, 0xEB, 0x63, 0x03, 0xDB, 0xB2, 0x01, 0x93, 0x01, 0x9B, 0x52, 0xF8, 0x23, 0x00, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x02, 0xEB, 0x45, 0x08, 0x00, 0x9A, 0x18, 0xF8, 0x07, 0x8C, 0x52, 0xF8, 0x28, 0xB0, 0x25, 0x4A, 0x93, 0x45, +0xA3, 0xDB, 0xB1, 0xF5, 0x7A, 0x7F, 0x02, 0xDA, 0x23, 0x4A, 0x93, 0x45, 0x9D, 0xDA, 0x02, 0x21, 0x0C, 0x44, 0xA0, 0x45, +0x9D, 0xDA, 0x04, 0xAA, 0x17, 0x44, 0x07, 0xF8, 0x08, 0xAC, 0x07, 0xF8, 0x07, 0xAC, 0x75, 0xE7, 0x02, 0x2F, 0x1C, 0x46, +0x08, 0x46, 0x66, 0x46, 0x05, 0xF1, 0x02, 0x05, 0xCA, 0xD0, 0x02, 0x27, 0xAA, 0xE7, 0x04, 0xAB, 0x03, 0xEB, 0x45, 0x01, +0x6D, 0x00, 0x11, 0xF8, 0x08, 0x3C, 0x80, 0x2B, 0x8E, 0xD0, 0x52, 0xF8, 0x23, 0x00, 0x11, 0xF8, 0x07, 0x1C, 0x43, 0xF2, +0xB0, 0x64, 0xA0, 0x42, 0x0A, 0xDC, 0x0F, 0x4E, 0x52, 0xF8, 0x21, 0x40, 0xB4, 0x42, 0x05, 0xDB, 0xB0, 0xF5, 0x7A, 0x7F, +0x13, 0xDA, 0x14, 0xF5, 0x7A, 0x7F, 0x10, 0xDD, 0x9C, 0x44, 0x61, 0x45, 0xBF, 0xF6, 0x78, 0xAF, 0x04, 0xAB, 0x1D, 0x44, +0x80, 0x23, 0x05, 0xF8, 0x08, 0x3C, 0x05, 0xF8, 0x07, 0x3C, 0x6F, 0xE7, 0xA3, 0x42, 0x9B, 0xD2, 0x1C, 0x46, 0x66, 0x46, +0x98, 0xE7, 0x4F, 0xF0, 0x02, 0x0C, 0xEB, 0xE7, 0x50, 0xC9, 0xFF, 0xFF, 0x19, 0xFC, 0xFF, 0xFF, 0xD0, 0xED, 0x00, 0x7A, +0x90, 0xED, 0x01, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, +0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x5E, 0xDA, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, +0x08, 0xDD, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x01, 0x6A, 0xB4, 0xEE, 0xE6, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x50, 0xD9, +0xD0, 0xED, 0x02, 0x6A, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0xD1, 0xED, 0x00, 0x5A, 0x91, 0xED, +0x02, 0x6A, 0xF4, 0xEE, 0xC6, 0x5A, 0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xDA, 0xF4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, +0x32, 0xDC, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xD5, 0x91, 0xED, 0x01, 0x6A, 0xD1, 0xED, 0x02, 0x7A, +0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x2D, 0xDA, 0xB4, 0xEE, 0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDD, +0x91, 0xED, 0x01, 0x7A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1F, 0xD9, 0xD1, 0xED, +0x00, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x1A, 0xDD, 0x91, 0xED, 0x01, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, +0xF1, 0xEE, 0x10, 0xFA, 0x13, 0xDD, 0x91, 0xED, 0x02, 0x7A, 0xB5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x0C, 0xDD, +0x01, 0x20, 0x70, 0x47, 0x91, 0xED, 0x00, 0x6A, 0xD1, 0xED, 0x02, 0x7A, 0xB4, 0xEE, 0xE7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, +0xC3, 0xD8, 0x02, 0x20, 0x70, 0x47, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x01, 0xD4, 0x00, 0x20, 0x70, 0x47, +0xD1, 0xED, 0x01, 0x7A, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0xF6, 0xD5, 0xD1, 0xED, 0x02, 0x7A, 0xF5, 0xEE, +0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x4C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0x00, 0xF0, +0xC7, 0x80, 0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x22, 0xA1, 0xF1, 0x02, 0x08, 0x82, 0xB0, 0x44, 0x46, 0x17, 0x46, 0x94, 0x46, +0x10, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x02, 0xE0, 0x05, 0x2E, 0x11, 0xD0, 0x01, 0x32, 0x34, 0xF9, 0x02, 0x5F, 0x0E, 0xFA, +0x02, 0xF3, 0x00, 0x2D, 0xD6, 0xB2, 0x43, 0xEA, 0x00, 0x03, 0xF3, 0xDA, 0x01, 0x2A, 0xD8, 0xB2, 0x40, 0xF2, 0x83, 0x80, +0x01, 0x37, 0x05, 0x2E, 0xFF, 0xB2, 0xED, 0xD1, 0x04, 0x2F, 0x00, 0xF0, 0x81, 0x80, 0x02, 0x2F, 0x00, 0xF2, 0x81, 0x80, +0xBC, 0xF1, 0x00, 0x0F, 0x0B, 0xD1, 0xB1, 0xF9, 0x02, 0x30, 0xB1, 0xF9, 0x00, 0x20, 0x03, 0xF1, 0x09, 0x04, 0x94, 0x42, +0x02, 0xDB, 0x09, 0x3B, 0x9A, 0x42, 0x00, 0xDA, 0x4A, 0x80, 0xB1, 0xF9, 0x04, 0x20, 0xB1, 0xF9, 0x06, 0x30, 0x03, 0x24, +0x40, 0xF2, 0x04, 0x55, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x40, 0xAD, 0xF8, 0x02, 0x50, 0xC0, 0xF2, 0x8E, 0x80, 0xB1, 0xF9, +0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x9A, 0x42, 0x25, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x4F, 0xF0, 0x04, 0x07, 0x4F, 0xF0, +0x02, 0x04, 0x80, 0xF2, 0x8E, 0x80, 0x40, 0xF2, 0x05, 0x43, 0xAD, 0xF8, 0x02, 0x30, 0x4F, 0xF0, 0x05, 0x0E, 0x4F, 0xF0, +0x08, 0x08, 0x04, 0x26, 0x0A, 0x22, 0xCB, 0x5F, 0x8F, 0x5E, 0xBB, 0x42, 0x07, 0xDA, 0xBA, 0x46, 0x72, 0x46, 0x8D, 0xF8, +0x02, 0x40, 0x1F, 0x46, 0xA6, 0x46, 0x53, 0x46, 0x14, 0x46, 0x31, 0xF9, 0x09, 0x20, 0x31, 0xF9, 0x08, 0x80, 0x42, 0x45, +0x05, 0xDA, 0x8D, 0xF8, 0x03, 0x50, 0x8D, 0xF8, 0x01, 0x60, 0x42, 0x46, 0x35, 0x46, 0x97, 0x42, 0x05, 0xDD, 0x8D, 0xF8, +0x02, 0x50, 0x8D, 0xF8, 0x01, 0xE0, 0x3A, 0x46, 0x75, 0x46, 0x9D, 0xF8, 0x02, 0xE0, 0x9D, 0xF8, 0x01, 0x60, 0x31, 0xF9, +0x1E, 0x70, 0x31, 0xF9, 0x16, 0x80, 0x07, 0x32, 0xFE, 0x1D, 0x93, 0x42, 0xD4, 0xBF, 0x04, 0x23, 0x00, 0x23, 0xB0, 0x45, +0x9D, 0xF8, 0x03, 0x60, 0x31, 0xF9, 0x16, 0x20, 0x02, 0xF1, 0x07, 0x02, 0xD8, 0xBF, 0x43, 0xF0, 0x02, 0x03, 0xBA, 0x42, +0xA8, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x06, 0x2B, 0x4E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x4A, 0xA9, 0xA1, 0x9B, 0x93, 0x4A, +0xB1, 0x00, 0x0C, 0xF1, 0x01, 0x0C, 0x5F, 0xFA, 0x8C, 0xFC, 0x69, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0x78, 0xD0, 0x00, 0x23, +0x1C, 0x46, 0x1A, 0x46, 0x40, 0xFA, 0x03, 0xF5, 0xEF, 0x07, 0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, +0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, 0x92, 0xFB, 0xF4, 0xF2, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF4, +0xE6, 0x07, 0x48, 0xBF, 0x21, 0xF8, 0x13, 0x20, 0x01, 0x33, 0x06, 0x2B, 0xF6, 0xD1, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, +0x8B, 0x1E, 0x80, 0x20, 0x0A, 0x31, 0x33, 0xF9, 0x02, 0x2F, 0x00, 0x2A, 0xB8, 0xBF, 0x18, 0x80, 0x99, 0x42, 0xF8, 0xD1, +0x70, 0x47, 0xB1, 0xF9, 0x08, 0x20, 0xB1, 0xF9, 0x0A, 0x30, 0x02, 0x25, 0x9A, 0x42, 0x8D, 0xF8, 0x01, 0x50, 0x4F, 0xF0, +0x04, 0x09, 0x4F, 0xF0, 0x06, 0x07, 0xFF, 0xF6, 0x72, 0xAF, 0x4F, 0xF0, 0x0A, 0x08, 0x08, 0x22, 0x4F, 0xF0, 0x04, 0x0E, +0x75, 0xE7, 0xBC, 0xF1, 0x00, 0x0F, 0x69, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x02, 0x23, 0x40, 0xFA, 0x03, 0xF5, 0xED, 0x07, +0x05, 0xD4, 0x31, 0xF8, 0x13, 0x50, 0x01, 0x34, 0x2A, 0x44, 0xE4, 0xB2, 0x12, 0xB2, 0x01, 0x33, 0x06, 0x2B, 0xF2, 0xD1, +0x64, 0xB9, 0xC3, 0x07, 0x03, 0xD4, 0x0B, 0x88, 0x1A, 0x44, 0x12, 0xB2, 0x01, 0x24, 0x87, 0x07, 0x04, 0xD4, 0x4B, 0x88, +0x01, 0x34, 0x13, 0x44, 0xE4, 0xB2, 0x1A, 0xB2, 0x00, 0x23, 0x92, 0xFB, 0xF4, 0xF4, 0x00, 0xE0, 0x01, 0x33, 0x40, 0xFA, +0x03, 0xF2, 0xD6, 0x07, 0xDD, 0xB2, 0x03, 0xD5, 0x01, 0x2B, 0x14, 0xD9, 0x21, 0xF8, 0x13, 0x40, 0x05, 0x2D, 0xF3, 0xD1, +0xBC, 0xF1, 0x01, 0x0F, 0xA9, 0xD1, 0xC2, 0x07, 0x0F, 0xD4, 0x83, 0x07, 0xA5, 0xD5, 0x0B, 0x88, 0x4B, 0x80, 0xA2, 0xE7, +0x0A, 0x31, 0x80, 0x23, 0x28, 0xF8, 0x02, 0x3F, 0x88, 0x45, 0xFB, 0xD1, 0x9B, 0xE7, 0xBC, 0xF1, 0x02, 0x0F, 0xDF, 0xD1, +0xE6, 0xE7, 0x4B, 0x88, 0x0B, 0x80, 0x94, 0xE7, 0x01, 0x22, 0x02, 0xFA, 0x0E, 0xF3, 0xB2, 0x40, 0x13, 0x43, 0x18, 0x43, +0xC0, 0xB2, 0xB1, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, 0xC0, 0xB2, 0xAB, 0xE7, 0x01, 0x23, 0x03, 0xFA, +0x06, 0xF6, 0x30, 0x43, 0xA3, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0xA3, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x04, 0xF4, 0x20, 0x43, +0xAB, 0x40, 0x18, 0x43, 0xC0, 0xB2, 0x9B, 0xE7, 0x01, 0x23, 0x03, 0xFA, 0x06, 0xF6, 0x30, 0x43, 0xC0, 0xB2, 0x95, 0xE7, +0x40, 0xF0, 0x3C, 0x00, 0x92, 0xE7, 0x00, 0xBF, 0xF0, 0xB5, 0xD1, 0xED, 0x01, 0x6A, 0x91, 0xED, 0x00, 0x7A, 0x2D, 0xED, +0x08, 0x8B, 0xF4, 0xEE, 0xC7, 0x6A, 0xF1, 0xEE, 0x10, 0xFA, 0x83, 0xB0, 0x0C, 0x46, 0x07, 0x46, 0x15, 0x46, 0x1E, 0x46, +0x05, 0xDC, 0xF0, 0xEE, 0x66, 0x7A, 0xF0, 0xEE, 0x47, 0x6A, 0xB0, 0xEE, 0x67, 0x7A, 0xD4, 0xED, 0x02, 0x7A, 0xF4, 0xEE, +0xE6, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x08, 0xDC, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x48, 0xBF, 0xB0, 0xEE, +0x67, 0x7A, 0xF0, 0xEE, 0x66, 0x7A, 0x77, 0xEE, 0xC7, 0x7A, 0xB0, 0xEE, 0x08, 0xBA, 0xFC, 0xEE, 0xE7, 0x7A, 0x17, 0xEE, +0x90, 0x3A, 0xB3, 0x70, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, 0x02, 0x9A, 0x6A, 0xEE, 0x0A, 0x7A, +0x28, 0xEE, 0xA8, 0x6A, 0x69, 0xEE, 0xA9, 0xAA, 0x36, 0xEE, 0x27, 0x6A, 0x38, 0xEE, 0x8A, 0x7A, 0x76, 0xEE, 0x2A, 0xAA, +0x37, 0xEE, 0x29, 0x9A, 0x2A, 0xEE, 0x8B, 0xBA, 0x69, 0xEE, 0x09, 0x7A, 0x3B, 0xEE, 0x67, 0xBA, 0xB5, 0xEE, 0xC0, 0xBA, +0xF1, 0xEE, 0x10, 0xFA, 0x40, 0xF3, 0xD0, 0x80, 0x1B, 0xEE, 0x10, 0x0A, 0x33, 0xF0, 0x44, 0xF8, 0x6F, 0xA3, 0xD3, 0xE9, +0x00, 0x23, 0x33, 0xF0, 0x09, 0xFB, 0x80, 0xB1, 0x9F, 0xED, 0x6E, 0xBA, 0x33, 0x78, 0x6E, 0x49, 0x43, 0xF0, 0x04, 0x03, +0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, 0x73, 0xF8, 0xD4, 0xED, 0x00, 0x8A, 0x94, 0xED, 0x01, 0xAA, 0xD4, 0xED, +0x02, 0x9A, 0x95, 0xED, 0x00, 0x4A, 0xD5, 0xED, 0x01, 0x4A, 0x95, 0xED, 0x02, 0x5A, 0xF7, 0xEE, 0x00, 0x7A, 0x87, 0xEE, +0x8B, 0x6A, 0x0D, 0x2F, 0xF0, 0xEE, 0x08, 0x6A, 0x26, 0xEE, 0x49, 0x7A, 0x66, 0xEE, 0x26, 0x6A, 0x2A, 0xEE, 0x86, 0x6A, +0x66, 0xEE, 0xA8, 0x7A, 0x66, 0xEE, 0x8A, 0x5A, 0x67, 0xEE, 0x28, 0x8A, 0x27, 0xEE, 0x0A, 0xAA, 0x77, 0xEE, 0x87, 0x7A, +0x26, 0xEE, 0xA9, 0x8A, 0x78, 0xEE, 0x86, 0x8A, 0x67, 0xEE, 0x29, 0x9A, 0x75, 0xEE, 0x87, 0x5A, 0x3A, 0xEE, 0x06, 0xAA, +0x38, 0xEE, 0x07, 0x8A, 0x67, 0xEE, 0x84, 0x7A, 0x68, 0xEE, 0x84, 0x8A, 0x79, 0xEE, 0x86, 0x9A, 0x25, 0xEE, 0xA4, 0x7A, +0x2A, 0xEE, 0x24, 0xAA, 0x77, 0xEE, 0x87, 0x7A, 0x78, 0xEE, 0x8A, 0x8A, 0x28, 0xEE, 0x05, 0x8A, 0x69, 0xEE, 0x85, 0x9A, +0x37, 0xEE, 0x88, 0x8A, 0x78, 0xEE, 0xA9, 0x8A, 0x2E, 0xD9, 0xF3, 0xEE, 0x04, 0x7A, 0xB4, 0xEE, 0xE7, 0x8A, 0xF1, 0xEE, +0x10, 0xFA, 0x27, 0xD5, 0x33, 0x78, 0x44, 0x49, 0x43, 0xF0, 0x08, 0x03, 0x33, 0x70, 0x4F, 0xF4, 0x00, 0x50, 0x21, 0xF0, +0x1D, 0xF8, 0xB7, 0xEE, 0x00, 0x8A, 0xF0, 0xEE, 0x00, 0x6A, 0xB1, 0xEE, 0x68, 0x7A, 0xC7, 0xEE, 0x08, 0x7A, 0x9F, 0xED, +0x3D, 0x7A, 0xF4, 0xEE, 0xC7, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x21, 0xDC, 0xF5, 0xEE, 0xC0, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, +0x4E, 0xD4, 0xB6, 0xEE, 0x00, 0x7A, 0x77, 0xEE, 0x87, 0x7A, 0xFC, 0xEE, 0xE7, 0x7A, 0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF8, +0x04, 0x30, 0x12, 0xE0, 0x18, 0xEE, 0x10, 0x0A, 0x32, 0xF0, 0xBA, 0xFF, 0x2A, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x33, 0xF0, +0x7F, 0xFA, 0x00, 0x28, 0xCC, 0xD1, 0x68, 0xEE, 0x08, 0x6A, 0xF7, 0xEE, 0x00, 0x7A, 0x76, 0xEE, 0xA7, 0x6A, 0xD2, 0xE7, +0xFF, 0x23, 0x73, 0x70, 0xD4, 0xED, 0x00, 0x7A, 0x94, 0xED, 0x01, 0x7A, 0xD4, 0xED, 0x02, 0x4A, 0x95, 0xED, 0x00, 0x5A, +0xD5, 0xED, 0x01, 0x5A, 0x95, 0xED, 0x02, 0x6A, 0x68, 0xEE, 0x27, 0x7A, 0x28, 0xEE, 0x07, 0x7A, 0x77, 0xEE, 0xA8, 0x7A, +0x37, 0xEE, 0x28, 0x7A, 0x28, 0xEE, 0x24, 0x8A, 0x77, 0xEE, 0xC5, 0x7A, 0x37, 0xEE, 0x65, 0x7A, 0x38, 0xEE, 0x28, 0x8A, +0x27, 0xEE, 0x07, 0x7A, 0x38, 0xEE, 0x46, 0x8A, 0x67, 0xEE, 0xA7, 0x7A, 0x28, 0xEE, 0x08, 0x8A, 0x77, 0xEE, 0x87, 0x7A, +0x37, 0xEE, 0x88, 0x8A, 0xC8, 0xEE, 0x26, 0x7A, 0xC6, 0xED, 0x01, 0x7A, 0x03, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xF0, 0xBD, +0x00, 0x23, 0xCC, 0xE7, 0xF1, 0xEE, 0x4B, 0x7A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x72, 0xFF, 0x06, 0xA3, 0xD3, 0xE9, +0x00, 0x23, 0x33, 0xF0, 0x37, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x3D, 0xAF, 0x9F, 0xED, 0x08, 0xBA, 0x2A, 0xE7, 0x00, 0xBF, +0xAF, 0xF3, 0x00, 0x80, 0xF1, 0x68, 0xE3, 0x88, 0xB5, 0xF8, 0xE4, 0x3E, 0x00, 0x50, 0xC3, 0x47, 0xD4, 0x79, 0x15, 0x00, +0x00, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x7F, 0x43, 0xAC, 0xC5, 0x27, 0xB7, 0x2D, 0xE9, 0xF0, 0x47, 0x09, 0x29, 0x8E, 0xB0, +0x88, 0x46, 0x1D, 0x46, 0x70, 0xD9, 0x03, 0x28, 0x6E, 0xD0, 0x4F, 0xF0, 0x86, 0x4A, 0x57, 0x1E, 0x00, 0x26, 0x0D, 0xF1, +0x18, 0x09, 0x00, 0x22, 0x10, 0x46, 0xF1, 0xB2, 0xD3, 0xB2, 0x8B, 0x42, 0x19, 0xD0, 0x00, 0x2B, 0x00, 0xF0, 0xAF, 0x80, +0xBB, 0x5C, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0x67, 0x7A, 0x03, 0xEB, 0x80, 0x03, 0x43, 0xED, 0x0E, 0x7A, +0x84, 0x00, 0x55, 0xF8, 0x22, 0x30, 0x07, 0xEE, 0x90, 0x3A, 0x0E, 0xAB, 0xF8, 0xEE, 0xE7, 0x7A, 0x1C, 0x44, 0x01, 0x30, +0xC0, 0xB2, 0x44, 0xED, 0x0B, 0x7A, 0x01, 0x32, 0x04, 0x2A, 0xDF, 0xD1, 0x00, 0x23, 0x03, 0xA9, 0x68, 0x46, 0x09, 0xF8, +0x36, 0x30, 0xFF, 0xF7, 0x9F, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x09, 0xF8, 0x36, 0x00, 0x00, 0xF0, 0x95, 0x80, 0x01, 0x36, +0x04, 0x2E, 0xCC, 0xD1, 0x07, 0xAD, 0x00, 0x24, 0x2A, 0x46, 0x23, 0x46, 0x80, 0x21, 0x12, 0xF8, 0x04, 0x0C, 0x00, 0x28, +0x40, 0xF0, 0x82, 0x80, 0x0E, 0xA8, 0x80, 0x29, 0x00, 0xEB, 0xC1, 0x00, 0x00, 0xF0, 0x8A, 0x80, 0x92, 0xED, 0x00, 0x7A, +0x50, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, 0x98, 0xBF, 0x19, 0x46, 0x01, 0x33, 0xDB, 0xB2, +0x04, 0x2B, 0x02, 0xF1, 0x08, 0x02, 0xE4, 0xD1, 0x00, 0x2C, 0x00, 0xF0, 0x84, 0x80, 0x80, 0x29, 0x76, 0xD0, 0x0E, 0xAB, +0x03, 0xEB, 0xC1, 0x00, 0x42, 0x46, 0x10, 0xF8, 0x1F, 0x4C, 0x10, 0xF8, 0x20, 0x3C, 0x55, 0x49, 0x4F, 0xF4, 0x00, 0x50, +0x20, 0xF0, 0x22, 0xFF, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x13, 0x78, 0xD5, 0xED, 0x00, 0x6A, 0x95, 0xED, +0x01, 0x7A, 0xD5, 0xED, 0x02, 0x7A, 0x05, 0xEE, 0x90, 0x3A, 0x53, 0x78, 0x06, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0x65, 0x5A, +0xB8, 0xEE, 0x46, 0x6A, 0xF8, 0xEE, 0xE6, 0x6A, 0xB8, 0xEE, 0xC7, 0x7A, 0xF8, 0xEE, 0xE7, 0x7A, 0x4F, 0xF0, 0x86, 0x42, +0x00, 0x23, 0xB8, 0xF1, 0x09, 0x0F, 0xCD, 0xED, 0x01, 0x5A, 0x8D, 0xED, 0x02, 0x6A, 0xCD, 0xED, 0x03, 0x6A, 0x8D, 0xED, +0x04, 0x7A, 0xCD, 0xED, 0x05, 0x7A, 0x00, 0x92, 0x8D, 0xF8, 0x18, 0x30, 0x16, 0xD8, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, +0x40, 0x46, 0xFF, 0xF7, 0x17, 0xFE, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x4C, 0xD1, 0x9D, 0xF8, 0x19, 0x40, +0x35, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xE2, 0xFE, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, +0x03, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0x1C, 0xFC, 0x10, 0xF0, 0x0E, 0x0F, 0x8D, 0xF8, 0x18, 0x00, 0x18, 0xBF, 0x03, 0x46, +0x49, 0xD0, 0xC8, 0xF1, 0x09, 0x04, 0x64, 0x01, 0xE6, 0xE7, 0x0E, 0xAB, 0x03, 0xEB, 0x80, 0x03, 0x84, 0x00, 0x43, 0xF8, +0x38, 0xAC, 0x54, 0xE7, 0x06, 0x07, 0x1B, 0xD4, 0x01, 0x28, 0x08, 0xBF, 0x01, 0x24, 0x87, 0xE7, 0x09, 0xEB, 0xC6, 0x03, +0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xE3, 0xFD, 0x62, 0xE7, 0x19, 0x46, 0x7D, 0xE7, 0x00, 0x23, 0x15, 0xF8, +0x04, 0x2C, 0x01, 0x2A, 0x17, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x04, 0x2B, 0x05, 0xF1, 0x08, 0x05, 0xF5, 0xD1, 0x80, 0x29, +0x7F, 0xF4, 0x7B, 0xAF, 0x17, 0x49, 0x42, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xA4, 0xFE, 0xC8, 0xF1, 0x09, 0x04, +0x64, 0x01, 0x20, 0x46, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x80, 0x24, 0xB2, 0xE7, 0x0E, 0xAA, 0x80, 0x29, 0x02, 0xEB, +0xC1, 0x02, 0x0A, 0xD0, 0x95, 0xED, 0x00, 0x7A, 0x52, 0xED, 0x07, 0x7A, 0xB4, 0xEE, 0x67, 0x7A, 0xF1, 0xEE, 0x10, 0xFA, +0x98, 0xBF, 0x19, 0x46, 0xD7, 0xE7, 0x19, 0x46, 0xD5, 0xE7, 0x06, 0xAB, 0x03, 0xAA, 0x69, 0x46, 0x40, 0x46, 0xFF, 0xF7, +0xAB, 0xFD, 0x9D, 0xF8, 0x18, 0x30, 0x13, 0xF0, 0x0E, 0x0F, 0x93, 0xD0, 0xA9, 0xE7, 0x00, 0xBF, 0x14, 0x7A, 0x15, 0x00, +0x30, 0x7A, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9A, 0x4A, 0xDF, 0xF8, 0x8C, 0x82, 0x13, 0x68, 0x2D, 0xED, 0x08, 0x8B, +0x23, 0xF4, 0xFF, 0x43, 0x43, 0xF4, 0xCE, 0x35, 0x8B, 0xB0, 0x43, 0xF4, 0x1D, 0x43, 0x0C, 0x46, 0x45, 0xF4, 0x80, 0x75, +0x01, 0x46, 0x13, 0x60, 0x01, 0x20, 0x15, 0x60, 0x0D, 0x46, 0x03, 0x91, 0xFC, 0xF7, 0xBA, 0xFD, 0xA2, 0x7B, 0x8F, 0x48, +0x02, 0xF0, 0x0F, 0x03, 0x01, 0x68, 0x12, 0x09, 0x9B, 0x02, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, +0x03, 0x60, 0x02, 0x20, 0xFC, 0xF7, 0xAA, 0xFD, 0xAB, 0x6B, 0xC3, 0xF3, 0x07, 0x22, 0x02, 0x92, 0x4F, 0xEA, 0x02, 0x4B, +0xDA, 0xB2, 0x01, 0x92, 0x4F, 0xEA, 0x03, 0x6A, 0x4F, 0xF0, 0x00, 0x09, 0xDD, 0xE9, 0x01, 0x32, 0xB9, 0xF1, 0x00, 0x0F, +0x18, 0xBF, 0x13, 0x46, 0xA3, 0xF1, 0x40, 0x02, 0x12, 0xB2, 0x40, 0x33, 0x5F, 0xFA, 0x89, 0xF1, 0x00, 0x2A, 0xAD, 0xF8, +0x14, 0x20, 0xAD, 0xF8, 0x16, 0x30, 0x00, 0x91, 0xC0, 0xF2, 0xEA, 0x80, 0xFF, 0x2B, 0x01, 0xD9, 0x77, 0x4B, 0x05, 0x93, +0x00, 0x25, 0x2E, 0x46, 0x05, 0x24, 0x48, 0xF2, 0x80, 0x07, 0xBD, 0xF9, 0x14, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xB9, 0xF1, +0x00, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xFF, 0xF7, 0xAE, 0xF8, +0xBD, 0xF9, 0x16, 0x30, 0x4A, 0xEA, 0x03, 0x43, 0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x09, 0xA9, 0x07, 0xA8, 0xFF, 0xF7, +0xA3, 0xF8, 0xDD, 0xE9, 0x06, 0x02, 0xDD, 0xE9, 0x08, 0x13, 0x01, 0x3C, 0x12, 0x1A, 0x5B, 0x1A, 0x14, 0xF0, 0xFF, 0x04, +0x16, 0x44, 0x1D, 0x44, 0xD9, 0xD1, 0x62, 0x4B, 0x83, 0xFB, 0x06, 0x12, 0xF6, 0x17, 0xC6, 0xEB, 0x62, 0x06, 0x07, 0xEE, +0x90, 0x6A, 0x83, 0xFB, 0x05, 0x13, 0xED, 0x17, 0xC5, 0xEB, 0x63, 0x05, 0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x5A, +0xF8, 0xEE, 0xE7, 0x7A, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x9B, 0x01, 0x2B, 0x40, 0xF0, 0x9D, 0x80, +0xC7, 0xEE, 0x27, 0x9A, 0x03, 0x9B, 0x54, 0x49, 0x54, 0x4F, 0x4F, 0xF4, 0x00, 0x50, 0x1E, 0x1F, 0x03, 0xF1, 0x3C, 0x08, +0xB6, 0xEE, 0x00, 0xAA, 0x79, 0xEE, 0x88, 0x9A, 0xF7, 0xEE, 0x00, 0xAA, 0x69, 0xEE, 0x8A, 0x9A, 0x8A, 0xEE, 0xA9, 0x8A, +0xFD, 0xEE, 0xC8, 0x8A, 0x18, 0xEE, 0x90, 0x2A, 0x20, 0xF0, 0xCA, 0xFD, 0xF8, 0xEE, 0xE8, 0x8A, 0xDF, 0xED, 0x49, 0x7A, +0x49, 0x49, 0x38, 0xEE, 0x68, 0x8A, 0x4F, 0xF4, 0x00, 0x50, 0x28, 0xEE, 0x27, 0x8A, 0xFD, 0xEE, 0xC8, 0x7A, 0x17, 0xEE, +0x90, 0x2A, 0x20, 0xF0, 0xB9, 0xFD, 0x69, 0xEE, 0xA9, 0x7A, 0x39, 0xEE, 0xAA, 0xBA, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, +0x71, 0xFD, 0x40, 0x4B, 0x00, 0x22, 0x32, 0xF0, 0x0F, 0xFC, 0x7A, 0xEE, 0xE9, 0xAA, 0x04, 0x46, 0x0D, 0x46, 0x56, 0xF8, +0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x08, 0xEE, 0x90, 0x2A, 0xDB, 0xB2, 0x08, 0xEE, 0x10, 0x3A, 0xF8, 0xEE, 0xE8, 0x8A, +0xB8, 0xEE, 0xC8, 0x8A, 0x68, 0xEE, 0xAA, 0x8A, 0x28, 0xEE, 0x0B, 0x8A, 0x69, 0xEE, 0xA8, 0x7A, 0x78, 0xEE, 0x67, 0x7A, +0x29, 0xEE, 0x88, 0x8A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x4E, 0xFD, 0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xCC, 0xFE, +0x33, 0xF0, 0x5A, 0xF8, 0x78, 0xEE, 0x28, 0x7A, 0x09, 0xEE, 0x10, 0x0A, 0x17, 0xEE, 0x90, 0x0A, 0x32, 0xF0, 0x40, 0xFD, +0x22, 0x46, 0x2B, 0x46, 0x32, 0xF0, 0xBE, 0xFE, 0x33, 0xF0, 0x4C, 0xF8, 0x07, 0xEE, 0x90, 0x0A, 0x77, 0xEE, 0x8A, 0x7A, +0x39, 0xEE, 0x0A, 0x9A, 0xFD, 0xEE, 0xE7, 0x7A, 0xB0, 0x45, 0x17, 0xEE, 0x90, 0x3A, 0xFD, 0xEE, 0xC9, 0x7A, 0x4F, 0xEA, +0x03, 0x23, 0xCD, 0xED, 0x00, 0x7A, 0x9D, 0xF8, 0x00, 0x20, 0x03, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x02, 0x03, 0x43, 0xEA, +0x07, 0x03, 0x33, 0x60, 0xB5, 0xD1, 0x0B, 0xB0, 0xBD, 0xEC, 0x08, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0xEA, 0x03, 0x63, +0x3B, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0x08, 0xA9, 0x06, 0xA8, 0xFE, 0xF7, 0xE9, 0xFF, 0xBD, 0xF9, 0x16, 0x30, 0x4B, 0xEA, +0x03, 0x63, 0x3B, 0x43, 0x39, 0xE7, 0xF1, 0xEE, 0x67, 0x7A, 0x87, 0xEE, 0x87, 0x8A, 0x09, 0xF1, 0x01, 0x09, 0x01, 0xE7, +0x4F, 0xF4, 0x00, 0x03, 0x05, 0x93, 0x15, 0xE7, 0x58, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, 0x80, 0x00, 0xFF, 0x00, +0x67, 0x66, 0x66, 0x66, 0x48, 0x7A, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x7A, 0x44, 0x58, 0x7A, 0x15, 0x00, +0x00, 0x00, 0xF0, 0x3F, 0x4C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xB5, 0x4C, 0x2D, 0xED, 0x04, 0x8B, 0x27, 0x68, +0xAD, 0xF2, 0xE4, 0x7D, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0xB2, 0x49, 0x0A, 0x94, 0x3A, 0x46, 0x4F, 0xF4, 0x00, 0x50, +0x9A, 0x46, 0xCD, 0xE9, 0x13, 0x56, 0x20, 0xF0, 0x17, 0xFD, 0xAE, 0x4B, 0xAE, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, +0x20, 0xF0, 0x10, 0xFD, 0xAC, 0x4B, 0xAD, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x09, 0xFD, 0xAB, 0x4B, +0xAB, 0x49, 0x1A, 0x68, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x02, 0xFD, 0xA9, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, +0xFD, 0xFC, 0x16, 0xF0, 0x01, 0x03, 0x15, 0x93, 0x07, 0xD1, 0xA6, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, +0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, 0x14, 0x9A, 0xC2, 0xF3, 0x40, 0x03, 0x03, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x09, 0xEE, +0x10, 0x3A, 0xC2, 0xF3, 0x81, 0x03, 0x00, 0xF0, 0x9C, 0x82, 0x01, 0x2B, 0x14, 0xBF, 0x0A, 0x23, 0x05, 0x23, 0x08, 0xEE, +0x90, 0x3A, 0x9A, 0x4A, 0x9A, 0x4E, 0x14, 0x68, 0xDF, 0xF8, 0x7C, 0xE2, 0x99, 0x4B, 0x9A, 0x49, 0xDF, 0xF8, 0x78, 0x92, +0xDF, 0xF8, 0x78, 0xB2, 0x98, 0x48, 0xDF, 0xF8, 0x78, 0xC2, 0x98, 0x4F, 0xDF, 0xF8, 0x74, 0x82, 0x24, 0xF0, 0x04, 0x04, +0x14, 0x60, 0x35, 0x68, 0x00, 0x24, 0x25, 0xF4, 0x70, 0x45, 0x35, 0x60, 0xCE, 0xF8, 0x00, 0x40, 0x1D, 0x68, 0x45, 0xF0, +0x80, 0x05, 0x1D, 0x60, 0x0D, 0x68, 0x45, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x15, 0x68, 0x01, 0x26, 0x45, 0xF0, 0x04, 0x05, +0x15, 0x60, 0xCB, 0xF8, 0x00, 0x60, 0xC9, 0xF8, 0x00, 0x40, 0x15, 0x68, 0x25, 0xF0, 0x04, 0x05, 0x15, 0x60, 0x0D, 0x68, +0x25, 0xF0, 0x00, 0x45, 0x0D, 0x60, 0x1D, 0x68, 0x25, 0xF0, 0x80, 0x05, 0x1D, 0x60, 0x15, 0x68, 0x45, 0xF0, 0x04, 0x05, +0x15, 0x60, 0x82, 0x4D, 0x2A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x2A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x42, 0x22, 0xF0, +0x04, 0x02, 0x42, 0xF4, 0x80, 0x42, 0x32, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x07, 0x22, 0x42, 0xF0, 0xC0, 0x62, +0x42, 0xF4, 0x84, 0x72, 0x1A, 0x60, 0x0B, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x0A, 0x03, 0x0B, 0x60, 0x03, 0x68, +0x43, 0xF0, 0x3F, 0x03, 0x03, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x0B, 0x94, 0x43, 0xF4, 0x00, 0x63, 0x38, 0xAA, 0x78, 0xA9, +0x10, 0x92, 0x0F, 0x91, 0xCC, 0xF8, 0x00, 0x30, 0x0D, 0xF1, 0x7F, 0x03, 0xCD, 0xE9, 0x11, 0x21, 0x0D, 0x93, 0x08, 0xEE, +0x10, 0x4A, 0x0D, 0xF1, 0xAF, 0x03, 0x81, 0x46, 0x0E, 0x93, 0x00, 0x23, 0x0C, 0x93, 0x9D, 0xF8, 0x30, 0x50, 0x18, 0xEE, +0x10, 0x3A, 0x2B, 0x43, 0x09, 0x93, 0x00, 0x24, 0x3D, 0xE0, 0x0C, 0x9B, 0x00, 0x2B, 0x6C, 0xD0, 0x66, 0x00, 0x0D, 0x9B, +0x26, 0x44, 0x48, 0xF2, 0x80, 0x0B, 0x13, 0xF8, 0x06, 0xA0, 0x0E, 0x9B, 0x9E, 0x5D, 0x4F, 0xEA, 0x0A, 0x63, 0x43, 0xEA, +0x0A, 0x43, 0x43, 0xEA, 0x0B, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0xE3, 0xFE, 0xB2, 0x45, +0x0A, 0xD0, 0x33, 0x06, 0x43, 0xEA, 0x06, 0x46, 0x46, 0xEA, 0x0B, 0x06, 0xC8, 0xF8, 0x00, 0x60, 0x19, 0xA9, 0x17, 0xA8, +0xFE, 0xF7, 0xD6, 0xFE, 0x04, 0xEB, 0x84, 0x03, 0xB8, 0xAA, 0xDE, 0x00, 0x00, 0x21, 0x02, 0xEB, 0xC3, 0x03, 0x28, 0x46, +0x18, 0x9A, 0xFF, 0xF7, 0x51, 0xF8, 0x0D, 0xF5, 0xAC, 0x63, 0x33, 0x44, 0x19, 0x9A, 0x01, 0x34, 0x00, 0x21, 0x28, 0x46, +0xFF, 0xF7, 0x48, 0xF8, 0x10, 0x2C, 0xB8, 0xAE, 0x0D, 0xF5, 0xAC, 0x6B, 0x59, 0xD0, 0x3B, 0x68, 0x23, 0xF4, 0xFF, 0x43, +0x43, 0xEA, 0x44, 0x23, 0x43, 0xF4, 0x01, 0x42, 0x43, 0xF4, 0xC0, 0x33, 0x43, 0xF4, 0x80, 0x73, 0x3A, 0x60, 0x01, 0x20, +0x3B, 0x60, 0xFC, 0xF7, 0x71, 0xFB, 0x09, 0x9B, 0xE6, 0xB2, 0x00, 0x2B, 0x3D, 0xD0, 0x0A, 0x9B, 0xD9, 0xF8, 0x00, 0x10, +0x1A, 0x5D, 0x02, 0xF0, 0x0F, 0x03, 0x9B, 0x02, 0x12, 0x09, 0x43, 0xEA, 0x82, 0x13, 0x21, 0xF4, 0x7F, 0x52, 0x13, 0x43, +0xC9, 0xF8, 0x00, 0x30, 0x02, 0x20, 0xFC, 0xF7, 0x5B, 0xFB, 0x0B, 0x9B, 0x00, 0x2B, 0x98, 0xD1, 0x4F, 0xF0, 0x80, 0x33, +0xC8, 0xF8, 0x00, 0x30, 0x19, 0xA9, 0x18, 0xA8, 0xFE, 0xF7, 0x8C, 0xFE, 0xB4, 0xE7, 0x10, 0x9B, 0x04, 0xEB, 0x44, 0x0B, +0x03, 0xEB, 0x04, 0x12, 0x20, 0xAB, 0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x00, 0x92, 0x31, 0x46, 0x0D, 0xF1, 0x5A, 0x02, +0xFE, 0xF7, 0xF2, 0xFF, 0x0F, 0x9B, 0x4F, 0xEA, 0x04, 0x1A, 0x0A, 0xEB, 0x03, 0x02, 0x2C, 0xAB, 0x31, 0x46, 0x00, 0x92, +0x18, 0xEE, 0x10, 0x0A, 0x5B, 0x44, 0x0D, 0xF1, 0x5B, 0x02, 0x66, 0x00, 0xFE, 0xF7, 0xE2, 0xFF, 0x73, 0xE7, 0xFE, 0xF7, +0xA7, 0xFE, 0x0A, 0x9B, 0x18, 0x55, 0x02, 0x20, 0xFC, 0xF7, 0x28, 0xFB, 0xCE, 0xE7, 0x0C, 0x9B, 0x18, 0xEE, 0x90, 0x2A, +0x01, 0x33, 0x93, 0x42, 0x0C, 0x93, 0x7F, 0xF4, 0x58, 0xAF, 0x18, 0xEE, 0x90, 0xAA, 0x00, 0x25, 0x45, 0xE0, 0x00, 0xBF, +0x10, 0x20, 0x34, 0x40, 0x60, 0x7A, 0x15, 0x00, 0x1C, 0x20, 0x34, 0x40, 0x74, 0x7A, 0x15, 0x00, 0x04, 0x22, 0x34, 0x40, +0x88, 0x7A, 0x15, 0x00, 0x18, 0x00, 0x58, 0x40, 0x9C, 0x7A, 0x15, 0x00, 0xB0, 0x7A, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, +0x30, 0x20, 0x34, 0x40, 0x60, 0x20, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x64, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, +0x58, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x68, 0x20, 0x34, 0x40, 0x0C, 0xB6, 0x33, 0x40, 0x08, 0xB6, 0x33, 0x40, +0x20, 0x40, 0x34, 0x40, 0x4C, 0x40, 0x34, 0x40, 0x06, 0x2D, 0x34, 0xBF, 0x32, 0x21, 0x64, 0x21, 0x09, 0x91, 0xFE, 0xF7, +0xDB, 0xFF, 0x11, 0x9B, 0x09, 0x99, 0x84, 0x46, 0x43, 0xF8, 0x04, 0xC0, 0x5A, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD2, 0xFF, +0x01, 0x35, 0x12, 0x9B, 0x10, 0x2D, 0x18, 0x51, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0x14, 0xD0, 0xBA, 0xF1, +0x01, 0x0F, 0x32, 0x46, 0x4F, 0xEA, 0x05, 0x14, 0x50, 0x46, 0xDF, 0xD1, 0x11, 0x9B, 0x30, 0x68, 0x18, 0x51, 0x01, 0x35, +0x12, 0x9B, 0xDB, 0xF8, 0x00, 0x10, 0x19, 0x51, 0x10, 0x2D, 0x06, 0xF1, 0x28, 0x06, 0x0B, 0xF1, 0x28, 0x0B, 0xEA, 0xD1, +0x11, 0x9A, 0x0B, 0x9B, 0x04, 0x32, 0x11, 0x92, 0x12, 0x9A, 0x04, 0x32, 0x12, 0x92, 0x0D, 0x9A, 0x01, 0x32, 0x0D, 0x92, +0x0E, 0x9A, 0x01, 0x32, 0x01, 0x33, 0x0E, 0x92, 0x19, 0xEE, 0x10, 0x2A, 0x0B, 0x93, 0xDB, 0xB2, 0x9A, 0x42, 0x08, 0xEE, +0x10, 0x3A, 0x3F, 0xF6, 0xE0, 0xAE, 0x20, 0xAD, 0x2C, 0xAC, 0xAB, 0x46, 0x0B, 0x95, 0xDD, 0xF8, 0x40, 0x80, 0x0F, 0x9F, +0x09, 0x94, 0x19, 0xEE, 0x10, 0x5A, 0xA2, 0x46, 0x00, 0x26, 0x09, 0xE0, 0x13, 0x9A, 0x42, 0xF8, 0x26, 0x30, 0x01, 0x36, +0x0B, 0xF1, 0x03, 0x0B, 0x08, 0xF1, 0x10, 0x08, 0x0A, 0xF1, 0x03, 0x0A, 0x5F, 0xFA, 0x86, 0xF9, 0x49, 0x46, 0x43, 0x46, +0x5A, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x98, 0xFB, 0x07, 0xEB, 0x06, 0x13, 0x04, 0x46, 0x52, 0x46, 0x49, 0x46, 0x28, 0x46, +0xFF, 0xF7, 0x90, 0xFB, 0x03, 0x02, 0xE2, 0xB2, 0x03, 0xF4, 0x7F, 0x43, 0x13, 0x43, 0x43, 0xF0, 0x00, 0x43, 0x09, 0x2E, +0x43, 0xF4, 0x00, 0x03, 0xDA, 0xD9, 0x1A, 0xAB, 0x03, 0xEB, 0x46, 0x02, 0x1D, 0xAB, 0x03, 0xEB, 0x46, 0x03, 0xB9, 0xF1, +0x0F, 0x0F, 0x22, 0xF8, 0x14, 0x4C, 0x23, 0xF8, 0x14, 0x0C, 0xD0, 0xD1, 0x14, 0x9B, 0x09, 0x9C, 0x0B, 0x9D, 0xC3, 0xF3, +0x40, 0x10, 0x1A, 0xA9, 0x09, 0x90, 0xFF, 0xF7, 0xD3, 0xF8, 0x09, 0x98, 0x1D, 0xA9, 0xFF, 0xF7, 0xCF, 0xF8, 0x13, 0x9B, +0xDF, 0xF8, 0x98, 0xC1, 0x1D, 0xA8, 0x1A, 0xA9, 0x03, 0xF1, 0x24, 0x06, 0x03, 0xF1, 0x3C, 0x07, 0x30, 0xF9, 0x02, 0x3B, +0x31, 0xF9, 0x02, 0x2B, 0x1B, 0x02, 0x03, 0xF4, 0x7F, 0x43, 0xD2, 0xB2, 0x13, 0x43, 0x43, 0xEA, 0x0C, 0x03, 0x46, 0xF8, +0x04, 0x3F, 0xBE, 0x42, 0xF0, 0xD1, 0x10, 0x9B, 0xDF, 0xF8, 0x6C, 0x81, 0xDD, 0xF8, 0x3C, 0xA0, 0x03, 0xF5, 0x80, 0x77, +0x00, 0x26, 0x99, 0x46, 0xD9, 0xF8, 0x0C, 0x20, 0xAB, 0x78, 0xD9, 0xF8, 0x08, 0xC0, 0x68, 0x78, 0xD9, 0xF8, 0x04, 0x10, +0x06, 0x92, 0x15, 0xF8, 0x03, 0x2B, 0x05, 0x93, 0x59, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x03, 0x0C, 0xCD, 0xE9, +0x01, 0x21, 0x80, 0x23, 0x32, 0x46, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xC6, 0xFA, 0xDA, 0xF8, 0x0C, 0x20, +0xA3, 0x78, 0x60, 0x78, 0xDA, 0xF8, 0x04, 0x10, 0xDA, 0xF8, 0x08, 0xC0, 0x06, 0x92, 0x14, 0xF8, 0x03, 0x2B, 0x05, 0x93, +0x5A, 0xF8, 0x10, 0x3B, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0xCD, 0xE9, 0x03, 0x0C, 0x32, 0x46, 0x36, 0x49, 0x80, 0x23, +0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0xAC, 0xFA, 0x4F, 0x45, 0x06, 0xF1, 0x01, 0x06, 0xC7, 0xD1, 0x13, 0x9B, 0x32, 0x4E, +0x1D, 0x1F, 0x00, 0x24, 0x55, 0xF8, 0x04, 0x3F, 0xC3, 0xF3, 0x07, 0x22, 0x00, 0x92, 0xDB, 0xB2, 0x22, 0x46, 0x31, 0x46, +0x01, 0x34, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x97, 0xFA, 0x10, 0x2C, 0xF0, 0xD1, 0x14, 0x9B, 0xDB, 0x06, 0x0D, 0xD5, +0x15, 0x9B, 0x3B, 0xB1, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x00, 0x61, 0x43, 0xF4, 0xC0, 0x53, 0x11, 0x60, 0x13, 0x60, +0x0A, 0x99, 0x13, 0x98, 0xFF, 0xF7, 0x0C, 0xFC, 0x22, 0x49, 0x23, 0x4A, 0x0B, 0x68, 0x23, 0x4E, 0x23, 0x4C, 0x24, 0x48, +0x23, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0xEE, 0x43, 0x23, 0xF0, 0x09, 0x03, 0x43, 0xF4, 0x58, 0x53, +0xA1, 0xF5, 0xD6, 0x41, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x74, 0x39, 0x02, 0xF5, 0xFF, 0x52, 0x1C, 0x32, 0x00, 0x23, +0x4F, 0xF0, 0x80, 0x35, 0x33, 0x60, 0x25, 0x60, 0x03, 0x60, 0x0B, 0x60, 0x13, 0x68, 0x17, 0x49, 0x23, 0xF4, 0x7F, 0x43, +0x00, 0xF5, 0x09, 0x40, 0x23, 0xF0, 0x80, 0x03, 0xFC, 0x30, 0x43, 0xF4, 0x80, 0x34, 0x13, 0x60, 0x14, 0x60, 0x03, 0x68, +0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0x20, 0xF0, 0x4F, 0xFA, 0x0D, 0xF2, 0xE4, 0x7D, 0xBD, 0xEC, +0x04, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x23, 0x08, 0xEE, 0x90, 0x3A, 0x65, 0xE5, 0x00, 0xBF, 0xF0, 0x7A, 0x15, 0x00, +0x1C, 0x7B, 0x15, 0x00, 0x04, 0x40, 0x34, 0x40, 0x80, 0x21, 0x34, 0x40, 0x5C, 0x20, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, +0x4C, 0x40, 0x34, 0x40, 0x08, 0xB6, 0x33, 0x40, 0x3C, 0x7B, 0x15, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC4, 0x7A, 0x15, 0x00, +0xF0, 0xB5, 0x07, 0x78, 0x43, 0x68, 0x83, 0xB0, 0x0E, 0x46, 0x3A, 0x46, 0x27, 0x49, 0x01, 0x93, 0x4F, 0xF4, 0x00, 0x50, +0x20, 0xF0, 0x22, 0xFA, 0x01, 0x9B, 0x30, 0x1F, 0x06, 0xF1, 0x3C, 0x01, 0x4F, 0xF0, 0x80, 0x32, 0x40, 0xF8, 0x04, 0x2F, +0x88, 0x42, 0xFB, 0xD1, 0x06, 0xF1, 0x3F, 0x00, 0x06, 0xF1, 0x4F, 0x02, 0x00, 0x24, 0x00, 0xF8, 0x01, 0x4F, 0x82, 0x42, +0xFB, 0xD1, 0x30, 0x46, 0x34, 0x65, 0x06, 0xF1, 0x94, 0x05, 0x40, 0xF8, 0x54, 0x4F, 0x00, 0x24, 0x40, 0xF8, 0x04, 0x4F, +0xA8, 0x42, 0xFB, 0xD1, 0xBA, 0x09, 0x18, 0xD0, 0x15, 0x4C, 0xDF, 0xF8, 0x74, 0xC0, 0x21, 0x68, 0x14, 0x4D, 0x15, 0x4A, +0x15, 0x48, 0x21, 0xF4, 0x00, 0x11, 0x21, 0x60, 0xF9, 0x09, 0x00, 0x29, 0x08, 0xBF, 0x62, 0x46, 0x2A, 0x60, 0x05, 0x68, +0x11, 0x49, 0x12, 0x4C, 0x12, 0x4A, 0x01, 0xEA, 0x05, 0x01, 0x08, 0xBF, 0x22, 0x46, 0x0A, 0x43, 0x02, 0x60, 0x01, 0x93, +0xFE, 0xF7, 0x08, 0xFC, 0x0E, 0x4A, 0x01, 0x9B, 0xD2, 0xF8, 0xBC, 0x44, 0x38, 0x46, 0x06, 0xF1, 0x40, 0x02, 0x31, 0x46, +0xA0, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFE, 0xF7, 0x44, 0xBC, 0x50, 0x7B, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, +0x10, 0x20, 0x34, 0x40, 0x76, 0x62, 0xF7, 0x0B, 0x1C, 0x20, 0x34, 0x40, 0xFF, 0x0F, 0x00, 0xE0, 0x00, 0x50, 0x98, 0x00, +0x00, 0x90, 0x9B, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x76, 0x62, 0xB7, 0x0B, 0x17, 0x4B, 0x01, 0x22, 0x30, 0xB4, 0x1A, 0x60, +0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0x08, 0xDB, +0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x00, 0x2B, 0xF6, 0xDA, 0x0E, 0x4A, +0x0C, 0x4B, 0x15, 0x68, 0x1C, 0x68, 0xC5, 0xF3, 0x10, 0x02, 0xED, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x02, 0x42, 0x6F, 0xEA, +0x12, 0x42, 0xC4, 0xF3, 0x10, 0x03, 0x02, 0x60, 0xE2, 0x03, 0x44, 0xBF, 0x6F, 0xEA, 0x03, 0x43, 0x6F, 0xEA, 0x13, 0x43, +0x30, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x6C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x8C, 0x08, 0x62, 0x40, +0x30, 0xB4, 0x11, 0x4C, 0x11, 0x4D, 0x12, 0x4B, 0x04, 0xEA, 0x02, 0x42, 0xC1, 0xF3, 0x0E, 0x01, 0x0A, 0x43, 0x2A, 0x60, +0x1A, 0x68, 0x00, 0xF0, 0x07, 0x00, 0x22, 0xF0, 0xE0, 0x62, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x00, 0x42, +0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x1A, 0x68, +0x22, 0xF0, 0x00, 0x42, 0x30, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, +0x28, 0x05, 0x62, 0x40, 0x38, 0xB5, 0x28, 0x4C, 0x28, 0x4A, 0x23, 0x68, 0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x43, +0x43, 0xF0, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x03, 0x02, +0x42, 0xF0, 0x02, 0x03, 0x0B, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, +0x42, 0xF0, 0x03, 0x02, 0x1A, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x19, 0x4A, +0x13, 0x68, 0x98, 0x07, 0x08, 0xD4, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x13, 0x68, +0x98, 0x07, 0xF6, 0xD5, 0x13, 0x4C, 0x22, 0x68, 0x51, 0x00, 0x0E, 0xD4, 0x12, 0x4D, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, +0x20, 0xF0, 0x28, 0xF9, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x22, 0x68, 0x53, 0x00, +0xF1, 0xD5, 0x0C, 0x4A, 0x0C, 0x49, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x03, 0x13, 0x60, 0x4F, 0xF4, 0x00, 0x50, 0xBD, 0xE8, +0x38, 0x40, 0x20, 0xF0, 0x13, 0xB9, 0x00, 0xBF, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, +0x80, 0x40, 0x34, 0x40, 0x04, 0x22, 0x34, 0x40, 0x68, 0x7B, 0x15, 0x00, 0x04, 0x00, 0x62, 0x40, 0x7C, 0x7B, 0x15, 0x00, +0x10, 0xB5, 0x0F, 0x4C, 0x0F, 0x4A, 0x23, 0x68, 0x0F, 0x48, 0x10, 0x49, 0x23, 0xF4, 0x80, 0x03, 0x23, 0x60, 0x13, 0x68, +0x23, 0xF0, 0x03, 0x03, 0x13, 0x60, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, +0x01, 0x03, 0x0B, 0x60, 0x14, 0x20, 0xFC, 0xF7, 0x45, 0xF8, 0xBD, 0xE8, 0x10, 0x40, 0x06, 0x49, 0x4F, 0xF4, 0x00, 0x50, +0x20, 0xF0, 0xE2, 0xB8, 0x04, 0x00, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x08, 0x01, 0x60, 0x40, 0x08, 0x05, 0x62, 0x40, +0x88, 0x7B, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0x07, 0x46, 0x10, 0x1A, 0x0E, 0x46, 0x9B, 0x46, 0xDD, 0xE9, +0x0E, 0x54, 0x9D, 0xF8, 0x30, 0x90, 0x9D, 0xF8, 0x34, 0x80, 0x32, 0xF0, 0x65, 0xFD, 0x82, 0x46, 0xAB, 0xEB, 0x06, 0x00, +0x32, 0xF0, 0x60, 0xFD, 0xBA, 0xF1, 0x00, 0x0F, 0x11, 0xD0, 0x07, 0xFA, 0x09, 0xF7, 0x07, 0xEE, 0x90, 0x7A, 0xB8, 0xEE, +0xE7, 0x7A, 0x07, 0xEE, 0x90, 0xAA, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, 0xCD, 0xED, +0x01, 0x7A, 0x9D, 0xF9, 0x04, 0xA0, 0x85, 0xF8, 0x00, 0xA0, 0xA8, 0xB1, 0x06, 0xFA, 0x08, 0xF6, 0x07, 0xEE, 0x90, 0x6A, +0xB8, 0xEE, 0xE7, 0x7A, 0x07, 0xEE, 0x90, 0x0A, 0xF8, 0xEE, 0xE7, 0x7A, 0xC7, 0xEE, 0x27, 0x6A, 0xFD, 0xEE, 0xE6, 0x7A, +0xCD, 0xED, 0x01, 0x7A, 0x9D, 0xF9, 0x04, 0x30, 0x23, 0x70, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x46, 0x23, 0x70, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0xA1, 0x4F, 0xA2, 0x4C, 0x3D, 0x68, 0xA2, 0x4E, +0xAD, 0xB2, 0x25, 0x43, 0x2D, 0xED, 0x02, 0x8B, 0x3D, 0x60, 0x35, 0x68, 0x91, 0xB0, 0x25, 0xF0, 0x01, 0x05, 0x86, 0x46, +0x35, 0x60, 0x8C, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x9B, 0x49, 0xCD, 0xF8, 0x1C, 0xE0, 0xCD, 0xE9, 0x08, 0x23, 0x08, 0xEE, +0x10, 0xCA, 0x75, 0x46, 0x20, 0xF0, 0x72, 0xF8, 0x3B, 0x68, 0x9B, 0xB2, 0x23, 0x43, 0x3B, 0x60, 0x00, 0x2D, 0x00, 0xF0, +0x16, 0x81, 0x00, 0x26, 0x34, 0x46, 0x35, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x32, 0x23, 0x00, 0xBF, +0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0xDD, 0xE9, 0x0C, 0x32, +0x8A, 0x49, 0xCD, 0xE9, 0x00, 0x32, 0x4F, 0xF4, 0x00, 0x50, 0x23, 0x46, 0x2A, 0x46, 0x20, 0xF0, 0x4F, 0xF8, 0x0C, 0x9B, +0x00, 0x2B, 0xC0, 0xF2, 0xA5, 0x80, 0x00, 0x2E, 0x00, 0xF0, 0xB9, 0x80, 0x01, 0x2E, 0x00, 0xF0, 0xDD, 0x80, 0x0D, 0x9B, +0x15, 0xF1, 0x7C, 0x0F, 0xAC, 0xBF, 0x2A, 0x1F, 0x2A, 0x1D, 0x00, 0x2B, 0x80, 0xF2, 0xA1, 0x80, 0x01, 0x2E, 0x4F, 0xF0, +0x02, 0x08, 0x00, 0xF0, 0xDA, 0x80, 0x7B, 0x2C, 0x00, 0xF3, 0xA1, 0x80, 0x23, 0x1D, 0x4F, 0xF0, 0x02, 0x09, 0xA3, 0xF1, +0x80, 0x01, 0x38, 0x68, 0xC9, 0xB2, 0x09, 0x04, 0xA2, 0xF1, 0x80, 0x0C, 0x41, 0xEA, 0x0C, 0x61, 0x80, 0xB2, 0x01, 0x43, +0x39, 0x60, 0x32, 0x21, 0x00, 0xBF, 0x01, 0x39, 0x89, 0xB2, 0x00, 0x29, 0xFA, 0xD1, 0x0F, 0xA9, 0x0E, 0xA8, 0xCD, 0xE9, +0x05, 0x23, 0xFF, 0xF7, 0x55, 0xFE, 0xDD, 0xE9, 0x0E, 0x10, 0xDD, 0xE9, 0x05, 0x23, 0x01, 0x90, 0x00, 0x91, 0x4F, 0xF4, +0x00, 0x50, 0x68, 0x49, 0x20, 0xF0, 0x0E, 0xF8, 0x0D, 0xF1, 0x2F, 0x03, 0x03, 0x93, 0x0D, 0xF1, 0x2E, 0x03, 0xCD, 0xE9, +0x01, 0x93, 0xDD, 0xE9, 0x0C, 0x01, 0xDD, 0xE9, 0x0E, 0x23, 0xCD, 0xF8, 0x00, 0x80, 0xFF, 0xF7, 0x27, 0xFF, 0x9D, 0xF9, +0x2F, 0x30, 0x9D, 0xF9, 0x2E, 0x20, 0x5E, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0xF6, 0xFF, 0x9D, 0xF9, 0x2F, 0x30, +0x9D, 0xF9, 0x2E, 0x20, 0x39, 0x68, 0xE4, 0x1A, 0x6F, 0xF0, 0x7F, 0x03, 0x9C, 0x42, 0xB8, 0xBF, 0x1C, 0x46, 0xAD, 0x1A, +0x7F, 0x2C, 0xA8, 0xBF, 0x7F, 0x24, 0x9D, 0x42, 0xB8, 0xBF, 0x1D, 0x46, 0x04, 0xEB, 0x03, 0x08, 0x7F, 0x2D, 0xA8, 0xBF, +0x7F, 0x25, 0x5F, 0xFA, 0x88, 0xF8, 0xA5, 0xF1, 0x80, 0x02, 0x4F, 0xEA, 0x08, 0x43, 0x43, 0xEA, 0x02, 0x63, 0x89, 0xB2, +0x0B, 0x43, 0x01, 0x36, 0x3B, 0x60, 0x07, 0x9B, 0xF6, 0xB2, 0xB3, 0x42, 0x5F, 0xFA, 0x82, 0xF9, 0x7F, 0xF4, 0x68, 0xAF, +0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x59, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xFE, 0xFD, +0xDD, 0xE9, 0x0C, 0x13, 0x2A, 0x46, 0x01, 0x93, 0x00, 0x91, 0x23, 0x46, 0x3F, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, +0xB7, 0xFF, 0x08, 0x9B, 0x83, 0xF8, 0x00, 0x90, 0x09, 0x9B, 0xDD, 0xE9, 0x0C, 0x12, 0x18, 0xEE, 0x10, 0x0A, 0x83, 0xF8, +0x00, 0x80, 0xFF, 0xF7, 0x1D, 0xFE, 0x11, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0xB3, 0x01, 0x2E, +0x29, 0xD0, 0x0D, 0x9B, 0x7B, 0x2D, 0xD4, 0xBF, 0x2A, 0x1D, 0x2A, 0x1F, 0x00, 0x2B, 0xFF, 0xF6, 0x5F, 0xAF, 0x01, 0x2E, +0x4F, 0xF0, 0x02, 0x08, 0x26, 0xD0, 0x14, 0xF1, 0x7C, 0x0F, 0xFF, 0xF6, 0x5F, 0xAF, 0x23, 0x1F, 0x4F, 0xF0, 0x02, 0x09, +0x5D, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x20, 0x02, 0x0A, 0xDA, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, 0x04, 0xF1, +0x20, 0x03, 0x52, 0xE7, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x20, 0x02, 0xF4, 0xDB, 0x4F, 0xF0, 0x05, 0x08, 0xC1, 0x46, +0xA4, 0xF1, 0x20, 0x03, 0x47, 0xE7, 0x6F, 0x2D, 0xD3, 0xDC, 0x0D, 0x9B, 0x00, 0x2B, 0x05, 0xF1, 0x10, 0x02, 0x4F, 0xF0, +0x04, 0x08, 0x12, 0xDB, 0x14, 0xF1, 0x70, 0x0F, 0xD5, 0xDB, 0xA4, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x36, 0xE7, +0x15, 0xF1, 0x70, 0x0F, 0xFF, 0xF6, 0x1F, 0xAF, 0x0D, 0x9B, 0x00, 0x2B, 0xA5, 0xF1, 0x10, 0x02, 0x4F, 0xF0, 0x04, 0x08, +0xEC, 0xDA, 0x6F, 0x2C, 0x3F, 0xF7, 0x23, 0xAF, 0x04, 0xF1, 0x10, 0x03, 0x4F, 0xF0, 0x04, 0x09, 0x23, 0xE7, 0x07, 0x9C, +0x4F, 0xF0, 0x80, 0x08, 0x25, 0x46, 0xC1, 0x46, 0x0D, 0xF1, 0x34, 0x0B, 0x0D, 0xF1, 0x30, 0x0A, 0x7E, 0xE7, 0x00, 0xBF, +0x4C, 0x40, 0x34, 0x40, 0x00, 0x00, 0x80, 0x80, 0x1C, 0x40, 0x34, 0x40, 0x94, 0x7B, 0x15, 0x00, 0xA8, 0x7B, 0x15, 0x00, +0xCC, 0x7B, 0x15, 0x00, 0xF0, 0x7B, 0x15, 0x00, 0x0C, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x22, 0x4B, 0x23, 0x4E, +0x1A, 0x68, 0x00, 0x25, 0x22, 0xF4, 0x7F, 0x52, 0x1A, 0x60, 0x98, 0x46, 0x2F, 0x46, 0x4F, 0xF0, 0x07, 0x09, 0x02, 0x20, +0xFB, 0xF7, 0x86, 0xFE, 0x33, 0x68, 0xD8, 0xF8, 0x00, 0x40, 0xDA, 0x05, 0x54, 0xBF, 0x01, 0x37, 0x07, 0xF1, 0xFF, 0x37, +0x7F, 0xB2, 0x1B, 0x06, 0x54, 0xBF, 0x01, 0x35, 0x05, 0xF1, 0xFF, 0x35, 0x00, 0x2F, 0x24, 0xF4, 0x7F, 0x54, 0xDC, 0xBF, +0x7B, 0x42, 0x44, 0xEA, 0x83, 0x24, 0x6D, 0xB2, 0xD4, 0xBF, 0x44, 0xF4, 0x00, 0x54, 0x44, 0xEA, 0x87, 0x24, 0x00, 0x2D, +0xDC, 0xBF, 0x6B, 0x42, 0x44, 0xEA, 0x83, 0x14, 0x09, 0xF1, 0xFF, 0x33, 0xCC, 0xBF, 0x44, 0xEA, 0x85, 0x14, 0x44, 0xF4, +0x00, 0x74, 0x13, 0xF0, 0xFF, 0x09, 0xC8, 0xF8, 0x00, 0x40, 0xD0, 0xD1, 0x07, 0x49, 0x2B, 0x46, 0x3A, 0x46, 0x4F, 0xF4, +0x00, 0x50, 0x1F, 0xF0, 0xF7, 0xFE, 0xC4, 0xF3, 0x87, 0x10, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x50, 0x40, 0x34, 0x40, +0x14, 0x40, 0x34, 0x40, 0x34, 0x7C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4E, 0x4A, 0x4F, 0x4D, 0x13, 0x68, 0x87, 0xB0, +0xC1, 0xF3, 0x03, 0x24, 0x03, 0x93, 0x23, 0xF0, 0x00, 0x43, 0x23, 0xF4, 0xE0, 0x03, 0x43, 0xEA, 0x04, 0x53, 0x43, 0xF0, +0x0A, 0x03, 0x13, 0x60, 0x2C, 0x68, 0x48, 0x4B, 0x24, 0xF4, 0xC0, 0x54, 0xC1, 0xF3, 0x01, 0x62, 0x22, 0x43, 0x2A, 0x60, +0x1A, 0x68, 0x01, 0xF0, 0x0F, 0x04, 0xC1, 0xF3, 0x03, 0x15, 0x42, 0xF0, 0x3F, 0x02, 0xA5, 0x42, 0x02, 0x94, 0xC1, 0xF3, +0x03, 0x3A, 0x1A, 0x60, 0x5E, 0xD8, 0xDF, 0xF8, 0x04, 0x81, 0x3E, 0x4E, 0xDF, 0xF8, 0x00, 0xB1, 0x44, 0x19, 0x99, 0x46, +0xEF, 0xB2, 0xD8, 0xF8, 0x00, 0x20, 0x22, 0xF4, 0xFF, 0x42, 0x42, 0xEA, 0x45, 0x22, 0x42, 0xF4, 0x40, 0x40, 0x42, 0xF4, +0xE0, 0x31, 0xC8, 0xF8, 0x00, 0x00, 0x2A, 0x46, 0xC8, 0xF8, 0x00, 0x10, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x49, 0x1F, 0xF0, +0xA9, 0xFE, 0x32, 0x68, 0x42, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0x42, 0xF0, 0x40, 0x02, 0xCB, 0xF8, +0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0xFF, 0xF7, 0x5D, 0xFF, 0x04, 0xF8, +0x01, 0x0B, 0x32, 0x68, 0x22, 0xF4, 0x80, 0x62, 0x32, 0x60, 0xD9, 0xF8, 0x00, 0x20, 0x22, 0xF0, 0x40, 0x02, 0xC9, 0xF8, +0x00, 0x20, 0x32, 0x22, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x0D, 0xF1, 0x17, 0x03, 0x01, 0x93, +0x0D, 0xF1, 0x16, 0x03, 0x39, 0x46, 0x00, 0x93, 0x05, 0xAA, 0x0D, 0xF1, 0x15, 0x03, 0x50, 0x46, 0xFF, 0xF7, 0xE8, 0xFD, +0x01, 0x35, 0x02, 0x9B, 0x9D, 0xF8, 0x16, 0xC0, 0x9D, 0xF8, 0x17, 0x00, 0x9D, 0xF8, 0x14, 0x10, 0x9D, 0xF8, 0x15, 0x20, +0x84, 0xF8, 0x04, 0xC0, 0xEF, 0xB2, 0xBB, 0x42, 0x60, 0x72, 0xA1, 0x73, 0xE2, 0x74, 0xA8, 0xD2, 0x11, 0x4A, 0x0D, 0x48, +0x13, 0x68, 0x0D, 0x49, 0x0A, 0x4C, 0x23, 0xF4, 0x7F, 0x43, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0x43, 0xF4, 0x80, 0x33, +0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0xC0, 0x53, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x3F, 0x03, 0x0B, 0x60, 0x03, 0x9B, +0x23, 0x60, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1C, 0x05, 0x62, 0x40, 0x04, 0x40, 0x34, 0x40, 0x50, 0x40, 0x34, 0x40, +0x14, 0x40, 0x34, 0x40, 0x54, 0x7C, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x5C, 0x40, 0x34, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, +0x3C, 0x4D, 0x3D, 0x49, 0x81, 0x46, 0x89, 0xB0, 0x4F, 0xF4, 0x00, 0x50, 0x1F, 0xF0, 0x34, 0xFE, 0x2B, 0x68, 0xD9, 0xF8, +0x00, 0x40, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xB2, 0x04, 0xF0, 0x7F, 0x0A, 0xC4, 0xF3, 0x03, 0x18, 0x04, 0xF0, +0x0F, 0x04, 0x4A, 0xDB, 0x33, 0x4D, 0x34, 0x4F, 0x2E, 0x68, 0x2B, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x2B, 0x60, 0xD7, 0xF8, +0x00, 0xB0, 0x3B, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x3B, 0x60, 0x50, 0x46, 0xFF, 0xF7, 0xB2, 0xFC, 0xD9, 0xF8, 0x00, 0x10, +0x01, 0xA8, 0xFF, 0xF7, 0x25, 0xFF, 0xFF, 0xF7, 0x0D, 0xFD, 0xC7, 0xF8, 0x00, 0xB0, 0x2B, 0x68, 0x2B, 0x68, 0x06, 0xF4, +0x80, 0x76, 0x1E, 0x43, 0xA0, 0x45, 0x2E, 0x60, 0x26, 0xD8, 0x25, 0x48, 0x0D, 0xF1, 0x05, 0x03, 0xA4, 0xEB, 0x08, 0x04, +0x43, 0x44, 0x01, 0xAA, 0x42, 0x44, 0x53, 0xFA, 0x84, 0xF4, 0x00, 0xEB, 0x08, 0x10, 0x15, 0x78, 0x53, 0x79, 0x92, 0xF8, +0x0A, 0xC0, 0xD7, 0x7B, 0x16, 0x7D, 0x29, 0x06, 0x1B, 0x04, 0x01, 0xF0, 0x70, 0x41, 0x43, 0xEA, 0x0C, 0x63, 0x41, 0xEA, +0x05, 0x51, 0x3B, 0x43, 0x01, 0x32, 0x09, 0x0E, 0x43, 0xEA, 0x06, 0x23, 0xA2, 0x42, 0x80, 0xF8, 0x07, 0x12, 0xC0, 0xF8, +0x00, 0x32, 0x00, 0xF1, 0x10, 0x00, 0xE4, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xF0, 0x0C, 0x0F, 0x08, 0xD1, +0xA0, 0x45, 0xAF, 0xD9, 0x0E, 0x49, 0x0F, 0x48, 0x41, 0xF2, 0x7F, 0x02, 0x1F, 0xF0, 0xFA, 0xFF, 0xA8, 0xE7, 0x0B, 0x49, +0x0C, 0x48, 0x41, 0xF2, 0x7E, 0x02, 0x1F, 0xF0, 0xF3, 0xFF, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEB, 0xDB, +0x9C, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x7C, 0x15, 0x00, 0x00, 0x04, 0x60, 0x40, 0x18, 0x00, 0x58, 0x40, +0x1C, 0x13, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x7C, 0x15, 0x00, 0x78, 0x7C, 0x15, 0x00, 0x24, 0x4B, 0x25, 0x4A, +0x06, 0x21, 0x10, 0xB4, 0xC3, 0xF8, 0x00, 0x11, 0x53, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x53, 0x60, 0x53, 0x68, 0x43, 0xF4, +0x00, 0x33, 0x53, 0x60, 0x13, 0x6B, 0x03, 0xF0, 0x44, 0x03, 0x04, 0x2B, 0xFA, 0xD1, 0x1D, 0x4B, 0x1D, 0x4C, 0x1B, 0x68, +0x1D, 0x48, 0x19, 0x49, 0xA4, 0xFB, 0x03, 0x43, 0x9B, 0x0C, 0x43, 0xF0, 0x00, 0x44, 0x44, 0xF4, 0xA0, 0x14, 0x43, 0xF4, +0xA0, 0x13, 0x03, 0x60, 0x04, 0x60, 0x03, 0x60, 0x53, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x43, 0xF4, 0xC4, 0x33, 0x43, 0xF0, +0x02, 0x03, 0x4F, 0xF4, 0x80, 0x50, 0x53, 0x60, 0xC1, 0xF8, 0x34, 0x01, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, +0x4B, 0x6F, 0x43, 0xF0, 0x01, 0x03, 0x4B, 0x67, 0x53, 0x6C, 0x43, 0xF0, 0x08, 0x43, 0x53, 0x64, 0x53, 0x6D, 0x23, 0xF4, +0x00, 0x13, 0x53, 0x65, 0x53, 0x6D, 0x43, 0xF0, 0x02, 0x03, 0x53, 0x65, 0x53, 0x6D, 0x23, 0xF4, 0x00, 0x63, 0x53, 0x65, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0x18, 0x13, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, +0x08, 0x00, 0x58, 0x40, 0x3B, 0x4A, 0x3C, 0x48, 0x13, 0x68, 0x3C, 0x49, 0xDF, 0xF8, 0x24, 0xC1, 0x43, 0xF0, 0x7C, 0x53, +0xF0, 0xB4, 0x13, 0x60, 0x39, 0x4C, 0x3A, 0x4B, 0x23, 0x60, 0x03, 0xF1, 0xBE, 0x43, 0xA3, 0xF5, 0x69, 0x03, 0xA3, 0xF6, +0x77, 0x33, 0x03, 0x60, 0x36, 0x4B, 0x0B, 0x60, 0x36, 0x4F, 0x37, 0x4E, 0x37, 0x4D, 0x40, 0xF6, 0x77, 0x13, 0xCC, 0xF8, +0x00, 0x30, 0x36, 0x4B, 0x3B, 0x60, 0x04, 0xF5, 0x00, 0x24, 0x01, 0xF5, 0x2F, 0x11, 0x00, 0xF5, 0x2F, 0x10, 0x49, 0xF2, +0x02, 0x43, 0x02, 0xF5, 0x00, 0x22, 0x33, 0x60, 0x0C, 0x34, 0x30, 0x4B, 0x2B, 0x60, 0x01, 0xF5, 0x05, 0x61, 0x00, 0xF6, +0x58, 0x00, 0x02, 0xF6, 0x7C, 0x02, 0x07, 0xF5, 0x2F, 0x17, 0x2C, 0x4D, 0x25, 0x60, 0x07, 0xF6, 0x68, 0x07, 0x0B, 0x60, +0x06, 0xF5, 0x37, 0x16, 0x03, 0x60, 0x13, 0x60, 0x40, 0xF6, 0x34, 0x03, 0x3B, 0x60, 0x06, 0xF2, 0xE4, 0x46, 0x26, 0x4B, +0x33, 0x60, 0x01, 0xF5, 0xFE, 0x31, 0x03, 0xF1, 0x50, 0x53, 0x88, 0x31, 0x03, 0xF5, 0x54, 0x13, 0x0F, 0x33, 0x0B, 0x60, +0x00, 0xF5, 0xFE, 0x30, 0x03, 0xF1, 0x48, 0x43, 0x1F, 0x4D, 0x00, 0xF5, 0x90, 0x70, 0x02, 0xF5, 0xFE, 0x32, 0xA3, 0xF5, +0x78, 0x13, 0x02, 0xF5, 0xB4, 0x72, 0xA3, 0xF2, 0x1F, 0x63, 0x4F, 0xF0, 0x36, 0x36, 0x2B, 0x60, 0x06, 0x60, 0x4F, 0xF4, +0x7F, 0x40, 0x10, 0x60, 0x04, 0xF5, 0x01, 0x34, 0x02, 0xF1, 0xAC, 0x42, 0x20, 0x34, 0x15, 0x4B, 0x15, 0x4D, 0x25, 0x60, +0xA2, 0xF5, 0xB5, 0x12, 0x45, 0xF2, 0x55, 0x30, 0xA2, 0xF6, 0x8A, 0x62, 0xC1, 0xF8, 0xA8, 0x00, 0xF0, 0xBC, 0x1A, 0x60, +0x70, 0x47, 0x00, 0xBF, 0x0C, 0x00, 0x58, 0x40, 0x2C, 0x40, 0x34, 0x40, 0x30, 0x40, 0x34, 0x40, 0x04, 0x01, 0x58, 0x40, +0xFB, 0x23, 0x09, 0x00, 0x08, 0x51, 0x2E, 0x1A, 0x24, 0x40, 0x34, 0x40, 0x28, 0x40, 0x34, 0x40, 0x8C, 0x04, 0x60, 0x40, +0x94, 0xC5, 0x2E, 0x00, 0x34, 0x08, 0x50, 0x00, 0x58, 0x00, 0x7E, 0x02, 0x13, 0x20, 0x20, 0x20, 0xA0, 0x05, 0x62, 0x40, +0x1C, 0x05, 0x62, 0x40, 0x0F, 0x12, 0x15, 0x0C, 0x20, 0x40, 0x34, 0x40, 0x63, 0x49, 0x64, 0x4A, 0x0B, 0x68, 0x23, 0xF4, +0x00, 0x63, 0xF0, 0xB4, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x32, 0x23, 0x00, 0xBF, 0x01, 0x3B, +0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0xDF, 0xF8, 0x6C, 0xC1, 0x5B, 0x4A, 0xDC, 0xF8, 0x00, 0x30, 0x5A, 0x4F, 0x5B, 0x4E, +0x23, 0xF4, 0x80, 0x53, 0xCC, 0xF8, 0x00, 0x30, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, +0x43, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x30, 0x43, 0xF4, 0x00, 0x63, 0xCC, 0xF8, 0x00, 0x30, +0x62, 0x46, 0xFF, 0x25, 0x2B, 0x1D, 0x2C, 0x46, 0xDD, 0xB2, 0x29, 0x46, 0x38, 0x46, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, +0x0B, 0x43, 0x13, 0x60, 0x50, 0xF8, 0x04, 0x3B, 0x33, 0x60, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0xBF, +0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x13, 0x68, 0x9B, 0x04, 0xFC, 0xD5, 0x01, 0x39, 0xC9, 0xB2, 0xA1, 0x42, 0xE8, 0xD1, +0x8F, 0x2D, 0x07, 0xF1, 0x10, 0x07, 0xDF, 0xD1, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x80, 0x63, 0xCC, 0xF8, 0x00, 0x30, +0xC8, 0x23, 0x00, 0xBF, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x36, 0x4D, 0x37, 0x49, 0x2A, 0x68, 0x39, 0x48, +0x39, 0x4C, 0x22, 0xF4, 0x00, 0x62, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x0A, 0x68, 0x42, 0xF4, +0x80, 0x72, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x1F, 0x02, 0x1A, 0x43, 0x0A, 0x60, 0x50, 0xF8, 0x04, 0x2F, 0x22, 0x60, +0x0A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x0A, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x0A, 0x68, 0x52, 0x05, +0xFC, 0xD5, 0x01, 0x33, 0x20, 0x2B, 0xE9, 0xD1, 0x0B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x0B, 0x60, 0xC8, 0x23, 0x00, 0xBF, +0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x2B, 0xFA, 0xD1, 0x1F, 0x4C, 0x24, 0x48, 0x22, 0x68, 0x24, 0x49, 0x24, 0x4D, 0x22, 0xF4, +0x80, 0x72, 0x22, 0x60, 0x02, 0x68, 0x22, 0xF0, 0x02, 0x02, 0x02, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, 0x0A, 0x60, +0x32, 0x22, 0x2B, 0x60, 0x00, 0xBF, 0x01, 0x3A, 0x92, 0xB2, 0x00, 0x2A, 0xFA, 0xD1, 0x13, 0x49, 0x13, 0x4A, 0x08, 0x68, +0x1A, 0x4D, 0x1B, 0x4C, 0x1B, 0x4B, 0x40, 0xF4, 0x80, 0x50, 0x08, 0x60, 0x08, 0x68, 0x40, 0xF4, 0x00, 0x60, 0x08, 0x60, +0x11, 0x68, 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x11, 0x68, 0x41, 0xF4, 0x80, 0x71, 0x11, 0x60, 0x2A, 0x68, 0x42, 0xF4, +0x80, 0x52, 0x2A, 0x60, 0x22, 0x68, 0x22, 0xF4, 0x80, 0x22, 0x22, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x00, 0x52, 0x1A, 0x60, +0x1A, 0x68, 0x42, 0xF0, 0x80, 0x42, 0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x60, 0x40, 0x34, 0x40, 0x6C, 0x40, 0x34, 0x40, +0x1C, 0x13, 0x17, 0x00, 0x64, 0x40, 0x34, 0x40, 0x18, 0x18, 0x17, 0x00, 0x70, 0x40, 0x34, 0x40, 0x18, 0x00, 0x58, 0x40, +0x58, 0x40, 0x34, 0x40, 0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0x1C, 0x20, 0x34, 0x40, +0x10, 0xB5, 0x09, 0x4C, 0x82, 0xB0, 0xD4, 0xF8, 0xC0, 0x34, 0x01, 0x90, 0x98, 0x47, 0xD4, 0xF8, 0xC4, 0x34, 0x98, 0x47, +0xD4, 0xF8, 0xC8, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xCC, 0x34, 0x00, 0x21, 0x01, 0xA8, 0x98, 0x47, 0x02, 0xB0, 0x10, 0xBD, +0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x2D, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x17, 0xD0, 0x0F, 0x24, 0x4F, 0xF4, +0x00, 0x62, 0x11, 0x46, 0x29, 0x48, 0xFD, 0xF7, 0x61, 0xFA, 0x4F, 0xF4, 0x40, 0x72, 0x28, 0x48, 0x00, 0x21, 0xFD, 0xF7, +0x5B, 0xFA, 0x21, 0x46, 0x26, 0x48, 0xFD, 0xF7, 0x2F, 0xFA, 0x02, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x24, 0x48, 0x11, 0x46, +0xFD, 0xF7, 0x50, 0xBA, 0x04, 0xF0, 0x2E, 0xFD, 0x22, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, +0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x1F, 0x48, 0x1F, 0xF0, 0x52, 0xFB, 0x1E, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, +0x02, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x13, 0x69, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x61, 0x13, 0x69, 0xDB, 0x07, 0xFC, 0xD4, +0x18, 0x48, 0x1F, 0xF0, 0x41, 0xFB, 0x18, 0x4A, 0x18, 0x48, 0x4F, 0xF4, 0x00, 0x21, 0xFD, 0xF7, 0x2B, 0xFA, 0x17, 0x4B, +0x4F, 0xF4, 0x80, 0x61, 0x4F, 0xF4, 0x00, 0x02, 0xC3, 0xF8, 0x28, 0x11, 0xC3, 0xF8, 0x18, 0x21, 0x23, 0x68, 0x1B, 0x78, +0x02, 0x2B, 0xB5, 0xD1, 0x04, 0xF0, 0xB6, 0xFE, 0x00, 0x28, 0xB1, 0xD0, 0x0F, 0x4B, 0x10, 0x48, 0xD3, 0xF8, 0x00, 0x41, +0x21, 0x46, 0x1F, 0xF0, 0x23, 0xFB, 0xAA, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x0C, 0x88, 0x01, 0x50, 0x14, 0x88, 0x01, 0x50, +0x00, 0x70, 0x01, 0x50, 0x08, 0x70, 0x01, 0x50, 0x00, 0xE1, 0x00, 0xE0, 0x9C, 0x7C, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, +0xA8, 0x7C, 0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x90, 0x01, 0x50, 0x00, 0x00, 0x10, 0x40, 0x2C, 0x19, 0x17, 0x00, +0xB8, 0x7C, 0x15, 0x00, 0x38, 0xB5, 0x36, 0x4C, 0x36, 0x48, 0x44, 0x22, 0x00, 0x21, 0xFB, 0xF7, 0x91, 0xF8, 0x23, 0x68, +0x1A, 0x07, 0xC3, 0xF3, 0xC0, 0x01, 0x51, 0xD5, 0x22, 0x46, 0x00, 0xBF, 0x13, 0x68, 0xDB, 0x06, 0xFB, 0xD5, 0x30, 0x4D, +0x30, 0x48, 0x29, 0x68, 0x30, 0x4B, 0x00, 0x68, 0x30, 0x4A, 0xC1, 0xF8, 0x44, 0x02, 0x00, 0x21, 0x19, 0x60, 0x11, 0x60, +0x19, 0x68, 0x2E, 0x48, 0x2E, 0x4C, 0x21, 0xF0, 0x03, 0x01, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, +0x0C, 0x01, 0x41, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x71, 0x41, 0xF4, 0x00, 0x71, 0x19, 0x60, +0x19, 0x68, 0x21, 0xF4, 0x40, 0x61, 0x41, 0xF4, 0x00, 0x61, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF4, 0x40, 0x51, 0x41, 0xF4, +0x00, 0x51, 0x19, 0x60, 0x11, 0x68, 0x21, 0xF0, 0x40, 0x51, 0x41, 0xF0, 0x00, 0x51, 0x11, 0x60, 0x11, 0x68, 0x21, 0xF0, +0x40, 0x41, 0x41, 0xF0, 0x00, 0x41, 0x11, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x32, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, +0x40, 0x22, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x12, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x40, 0x02, 0x1A, 0x60, +0x1A, 0x68, 0x42, 0xF0, 0x40, 0x72, 0x1A, 0x60, 0x04, 0x60, 0x38, 0xBD, 0x23, 0x68, 0x09, 0x4D, 0x43, 0xF0, 0x08, 0x03, +0x23, 0x60, 0x28, 0x68, 0x4F, 0xF4, 0x12, 0x72, 0xFB, 0xF7, 0x30, 0xF8, 0x23, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x23, 0x60, +0xA4, 0xE7, 0x00, 0xBF, 0x80, 0x40, 0x04, 0x40, 0x04, 0x35, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x84, 0x1A, 0x17, 0x00, +0x14, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x33, 0x1F, 0x00, 0xC0, 0x0C, 0x4B, 0x10, 0xB5, +0x1C, 0x68, 0x14, 0xF4, 0xF8, 0x54, 0x00, 0xD1, 0x10, 0xBD, 0x60, 0x08, 0x1E, 0xF0, 0x02, 0xF8, 0x08, 0x4A, 0x09, 0x49, +0x09, 0x4B, 0x0C, 0x60, 0x14, 0x60, 0x1A, 0x78, 0x00, 0x2A, 0xF3, 0xD0, 0x07, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, +0x0B, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x1C, 0x41, 0x04, 0x40, 0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, +0x3C, 0x36, 0x17, 0x00, 0x10, 0x00, 0x58, 0x40, 0x2D, 0xE9, 0xF8, 0x4F, 0x29, 0x4B, 0x06, 0x46, 0x53, 0xF8, 0x20, 0x00, +0x1E, 0xF0, 0x04, 0xF8, 0x27, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x26, 0x4B, 0xD3, 0xF8, 0x00, 0xA0, 0xDA, 0xF8, +0x3C, 0x32, 0x0A, 0xF5, 0x0F, 0x7B, 0x8B, 0xB3, 0x23, 0x4D, 0xDF, 0xF8, 0x98, 0x90, 0xDF, 0xF8, 0x98, 0x80, 0x05, 0xF2, +0x14, 0x57, 0x1D, 0xE0, 0x95, 0xF8, 0x10, 0x35, 0x85, 0xF8, 0x11, 0x45, 0x01, 0x33, 0xA9, 0xFB, 0x03, 0x24, 0xA4, 0x09, +0x04, 0xEB, 0xC4, 0x04, 0x04, 0xEB, 0xC4, 0x04, 0x1C, 0x1B, 0x85, 0xF8, 0x10, 0x45, 0x1E, 0xF0, 0xA1, 0xF8, 0xD8, 0xF8, +0x00, 0x20, 0x05, 0xEB, 0x04, 0x11, 0x02, 0x44, 0xC1, 0xE9, 0x01, 0x26, 0x38, 0x46, 0x1E, 0xF0, 0x53, 0xF8, 0xDA, 0xF8, +0x3C, 0x32, 0x5B, 0xB1, 0x95, 0xF8, 0x11, 0x15, 0x95, 0xF8, 0x12, 0x25, 0x91, 0x42, 0x58, 0x46, 0x01, 0xF1, 0x01, 0x04, +0xD8, 0xD3, 0x0D, 0x48, 0x01, 0xF0, 0x54, 0xF8, 0x08, 0x4B, 0x01, 0x24, 0x1C, 0x60, 0x20, 0x20, 0x08, 0x36, 0x1D, 0xF0, +0x9B, 0xFF, 0x04, 0xFA, 0x06, 0xF6, 0x08, 0x4B, 0x06, 0xF4, 0xF8, 0x56, 0x1E, 0x60, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, +0x80, 0x7E, 0x15, 0x00, 0x4C, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x58, 0x58, 0x17, 0x00, 0xCC, 0x7C, 0x15, 0x00, +0x0C, 0x41, 0x04, 0x40, 0xE7, 0x87, 0x45, 0xCA, 0x84, 0x1A, 0x17, 0x00, 0x1D, 0x4B, 0x10, 0xB5, 0x1C, 0x68, 0xA0, 0x06, +0x2C, 0xD4, 0xE1, 0x06, 0x20, 0xD4, 0xA2, 0x07, 0x16, 0xD4, 0x63, 0x00, 0x08, 0xD5, 0x19, 0x4B, 0x01, 0x20, 0xD3, 0xF8, +0x78, 0x34, 0x98, 0x47, 0x17, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xDB, 0x10, 0xBD, 0x13, 0x4B, +0xD3, 0xF8, 0x68, 0x34, 0x98, 0x47, 0x12, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x10, 0xBD, 0x4F, 0xF0, 0x80, 0x50, +0x1D, 0xF0, 0x5E, 0xFF, 0x0E, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xE0, 0xE7, 0x0C, 0x49, 0x0B, 0x4A, 0x10, 0x23, 0x0B, 0x60, +0x4F, 0xF4, 0x00, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x51, 0xFF, 0xD4, 0xE7, 0x07, 0x49, 0x06, 0x4A, 0x20, 0x23, 0x0B, 0x60, +0x4F, 0xF4, 0x80, 0x10, 0x13, 0x60, 0x1D, 0xF0, 0x47, 0xFF, 0xC8, 0xE7, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x08, 0x41, 0x04, 0x40, 0x10, 0x41, 0x04, 0x40, 0x06, 0x4A, 0x07, 0x49, 0x12, 0x68, 0xD2, 0xF8, 0x24, 0x02, 0x20, 0x23, +0x0B, 0x60, 0x08, 0xB1, 0x01, 0x20, 0x70, 0x47, 0x03, 0x4A, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x38, 0x18, 0x00, +0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x15, 0x4C, 0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x14, 0x4B, +0x18, 0x68, 0xD0, 0xF8, 0x24, 0x32, 0xBB, 0xB1, 0x00, 0xF5, 0x09, 0x70, 0x1E, 0xF0, 0x02, 0xF8, 0x10, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0x01, 0xDB, 0x14, 0x30, 0x10, 0xBD, 0x00, 0x28, 0xFB, 0xD1, +0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x92, 0x32, 0x1F, 0xF0, 0x00, 0xFC, 0x14, 0x20, 0x10, 0xBD, 0x06, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x22, 0x60, 0xF5, 0xDA, 0xEE, 0xE7, 0x00, 0xBF, 0x54, 0x40, 0x04, 0x40, +0x00, 0x38, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x7C, 0x15, 0x00, 0x10, 0xB5, 0x0A, 0x4C, +0x23, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xD3, 0xF8, 0x14, 0x02, 0x40, 0xB1, 0x03, 0xF5, 0x05, 0x70, +0x1D, 0xF0, 0xCC, 0xFF, 0x01, 0x23, 0x23, 0x60, 0x00, 0xB1, 0x04, 0x30, 0x10, 0xBD, 0x01, 0x23, 0x23, 0x60, 0x10, 0xBD, +0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x4B, 0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, +0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x41, 0x04, 0x40, +0x01, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x00, 0x41, 0x04, 0x40, 0xF8, 0xB5, 0x04, 0x46, 0x40, 0x89, 0x29, 0x4F, +0x10, 0x30, 0x1D, 0xF0, 0xA3, 0xFB, 0x3E, 0x68, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x22, 0xDB, 0xA3, 0x88, +0x62, 0x89, 0xE0, 0x88, 0xAB, 0x80, 0x00, 0x21, 0x0C, 0x23, 0x2B, 0x81, 0x6A, 0x81, 0xE8, 0x80, 0x29, 0x60, 0xE3, 0x18, +0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, 0x10, 0x32, 0x14, 0x44, 0x05, 0xF1, 0x08, 0x02, 0x53, 0xF8, 0x04, 0x1B, +0x42, 0xF8, 0x04, 0x1F, 0xA3, 0x42, 0xF9, 0xD1, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x05, 0xF1, 0x0C, 0x00, +0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xD8, 0xBA, 0x00, 0x28, 0xDA, 0xD1, 0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x6F, 0x42, +0x1F, 0xF0, 0x82, 0xFB, 0x3E, 0x68, 0xD2, 0xE7, 0x0D, 0x28, 0x0D, 0xD8, 0x0B, 0x28, 0xEB, 0xD9, 0x0C, 0x49, 0x0E, 0x48, +0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, 0x76, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0xBE, 0xBA, +0x06, 0x49, 0x09, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x6B, 0xFB, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x90, 0x62, 0x1F, 0xF0, +0x65, 0xFB, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, +0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x46, 0x40, 0x89, 0x2B, 0x4F, 0x10, 0x30, 0x1D, 0xF0, 0x43, 0xFB, 0x3E, 0x68, +0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x2A, 0xDB, 0xAB, 0x88, 0x6A, 0x89, 0xEF, 0x88, 0xA3, 0x80, 0x00, 0x21, +0x0C, 0x23, 0x23, 0x81, 0x62, 0x81, 0xE7, 0x80, 0x21, 0x60, 0xEB, 0x18, 0x62, 0xB1, 0x01, 0x3A, 0x22, 0xF0, 0x03, 0x02, +0x10, 0x32, 0x2A, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x53, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x93, 0x42, 0xF9, 0xD1, +0x1A, 0x4A, 0x53, 0x7D, 0x59, 0x1C, 0x51, 0x75, 0x2B, 0x81, 0xB6, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, 0x17, 0x4B, +0x04, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x1A, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x1D, 0xF0, 0x70, 0xBA, 0x00, 0x28, 0xD2, 0xD1, +0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x8E, 0x42, 0x1F, 0xF0, 0x1A, 0xFB, 0x3E, 0x68, 0xCA, 0xE7, 0x0D, 0x2F, 0x08, 0xD8, +0x0B, 0x2F, 0xE8, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x0E, 0xFB, 0xE1, 0xE7, 0x09, 0x49, +0x0B, 0x48, 0xBB, 0x22, 0x1F, 0xF0, 0x08, 0xFB, 0x06, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xA3, 0x42, 0x1F, 0xF0, 0x02, 0xFB, +0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x04, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0x79, 0x15, 0x00, +0xFC, 0x7C, 0x15, 0x00, 0x20, 0x7D, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x0B, 0x4C, 0x23, 0x68, 0x9A, 0x07, +0x0A, 0xD5, 0x0A, 0x4F, 0x0A, 0x4E, 0x02, 0x25, 0x38, 0x68, 0x35, 0x60, 0x04, 0x30, 0xFF, 0xF7, 0x8B, 0xFF, 0x23, 0x68, +0x9B, 0x07, 0xF7, 0xD4, 0x4F, 0xF0, 0x80, 0x50, 0x1D, 0xF0, 0x0C, 0xFE, 0x04, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0xF8, 0xBD, +0x04, 0x41, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, +0xDF, 0xF8, 0x20, 0x93, 0xD9, 0xF8, 0x00, 0x20, 0x13, 0x78, 0x03, 0x2B, 0x82, 0xB0, 0x04, 0x46, 0x00, 0xF0, 0x16, 0x81, +0x00, 0x27, 0x3E, 0x46, 0x01, 0x2B, 0x00, 0xF0, 0xC2, 0x80, 0x02, 0x2B, 0x4F, 0xF0, 0x00, 0x05, 0x00, 0xF0, 0xD3, 0x80, +0x62, 0x89, 0xA3, 0x88, 0x33, 0x80, 0xF2, 0x80, 0x7A, 0xB9, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0x1C, 0xD0, +0x02, 0x2B, 0x2F, 0xD0, 0x01, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, +0x41, 0xBA, 0xA3, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x20, 0x81, 0x06, 0xF1, 0x0C, 0x00, +0x04, 0xF1, 0x0C, 0x01, 0x31, 0xF0, 0x40, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x03, 0x2B, 0xE2, 0xD1, 0x9B, 0x4E, +0x33, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x9A, 0x4B, 0x18, 0x68, 0x39, 0x1F, 0x00, 0xF5, 0x03, 0x70, 0x1D, 0xF0, 0x36, 0xFE, +0x97, 0x4B, 0x01, 0x21, 0x02, 0x22, 0x31, 0x60, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0xCF, 0xD1, +0x60, 0x89, 0x10, 0xF0, 0x03, 0x03, 0x40, 0xF0, 0xE9, 0x80, 0x19, 0x46, 0x9C, 0x46, 0x90, 0x4E, 0x42, 0xF2, 0x34, 0x03, +0xF2, 0x5A, 0xB2, 0xF5, 0xC3, 0x7F, 0x00, 0xF2, 0xFD, 0x80, 0x57, 0x1C, 0xBF, 0xB2, 0x4F, 0xEA, 0xC2, 0x0E, 0x8B, 0x4B, +0xA8, 0xF8, 0x0C, 0x20, 0xD3, 0xF8, 0x00, 0xA0, 0x00, 0xF1, 0x10, 0x03, 0x0A, 0xEB, 0x0E, 0x00, 0x0C, 0xEB, 0x03, 0x02, +0x45, 0x60, 0x2A, 0xF8, 0x0E, 0x20, 0xC2, 0x78, 0x02, 0xF0, 0x31, 0x02, 0x42, 0xF0, 0x04, 0x02, 0xC2, 0x70, 0x96, 0xF8, +0x02, 0x2C, 0x42, 0xF2, 0x34, 0x0C, 0x0B, 0x44, 0x01, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x00, 0x0E, 0x26, 0xF8, 0x0C, 0x70, +0x86, 0xF8, 0x02, 0x2C, 0xC8, 0xE9, 0x01, 0x03, 0x88, 0xF8, 0x0E, 0x10, 0xC8, 0xF8, 0x00, 0xE0, 0xEF, 0xF3, 0x10, 0x83, +0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x19, 0x60, 0x76, 0x4E, 0x76, 0x48, 0x33, 0x68, 0x41, 0x46, 0x01, 0x33, +0x33, 0x60, 0x1D, 0xF0, 0xE3, 0xFD, 0x74, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x33, 0xB1, 0x6E, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, +0x7F, 0xF4, 0x77, 0xAF, 0x01, 0xF0, 0xF2, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x0C, 0x81, 0xA1, 0x7A, 0x68, 0x4A, 0x0C, 0x31, +0x29, 0x70, 0x61, 0x89, 0x0C, 0x31, 0x00, 0x27, 0x09, 0x12, 0x11, 0x26, 0x69, 0x70, 0xAE, 0x70, 0xEF, 0x70, 0x61, 0x89, +0x86, 0x68, 0x47, 0x60, 0x10, 0x31, 0xC1, 0xF3, 0x0B, 0x01, 0x32, 0x40, 0x0A, 0x43, 0x42, 0xF0, 0x00, 0x42, 0x05, 0x60, +0x82, 0x60, 0x03, 0xF0, 0x35, 0xF8, 0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x1D, 0xF0, 0x99, 0xB9, 0x63, 0x89, +0x6C, 0x2B, 0x40, 0xF2, 0x8C, 0x80, 0x58, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x05, 0x46, +0x00, 0x2D, 0x00, 0xF0, 0x8A, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0xF1, 0x04, 0x06, 0x7F, 0xF4, +0x2D, 0xAF, 0x63, 0x89, 0x6C, 0x2B, 0x7A, 0xD9, 0x4D, 0x4B, 0x1B, 0x68, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, +0x05, 0x46, 0x00, 0x2D, 0x75, 0xD0, 0x42, 0x4A, 0x42, 0xF2, 0x24, 0x03, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, +0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3D, 0x4E, 0x42, 0x48, +0x33, 0x68, 0x01, 0x33, 0x33, 0x60, 0x1D, 0xF0, 0xB7, 0xFD, 0x33, 0x68, 0x80, 0x46, 0x33, 0xB1, 0x37, 0x4A, 0x01, 0x3B, +0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xA3, 0x7A, 0x0C, 0x33, 0x2B, 0x70, 0x63, 0x89, 0x0C, 0x33, +0x1B, 0x12, 0x11, 0x22, 0x6B, 0x70, 0x00, 0x23, 0xAA, 0x70, 0xEB, 0x70, 0x2E, 0x1D, 0xF3, 0xE6, 0x28, 0x4D, 0x2B, 0x68, +0x00, 0x2B, 0xFC, 0xD0, 0x27, 0x4B, 0x18, 0x68, 0xD0, 0xF8, 0x04, 0x32, 0xD3, 0xB1, 0x00, 0xF5, 0x01, 0x70, 0x1D, 0xF0, +0x93, 0xFD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x22, 0x00, 0x2B, 0x2A, 0x60, 0xC0, 0xF2, 0x8B, 0x80, +0x07, 0x1D, 0xD9, 0xF8, 0x00, 0x20, 0x3E, 0x46, 0x27, 0x4B, 0xB3, 0x60, 0x13, 0x78, 0xCD, 0xE6, 0xC3, 0xF1, 0x04, 0x03, +0x5F, 0xFA, 0x83, 0xFC, 0x61, 0x46, 0x12, 0xE7, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x01, 0x21, 0x00, 0x2B, +0x29, 0x60, 0xC0, 0xF2, 0x82, 0x80, 0x04, 0x26, 0x37, 0x46, 0xE9, 0xE7, 0xB2, 0xF5, 0x80, 0x6F, 0x7F, 0xF6, 0xDC, 0xAE, +0x4F, 0xF4, 0xB1, 0x62, 0x1A, 0x49, 0x1B, 0x48, 0x1F, 0xF0, 0x76, 0xF9, 0x62, 0x89, 0xD3, 0xE6, 0x4F, 0xF0, 0x00, 0x0E, +0x72, 0x46, 0x01, 0x27, 0x01, 0xE7, 0x01, 0xF0, 0xCF, 0xFF, 0x05, 0x46, 0x76, 0xE7, 0x05, 0xF0, 0x2B, 0xF8, 0x05, 0x46, +0x87, 0xE7, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x11, 0x48, 0x00, 0xF0, 0x1D, 0xFD, 0xB2, 0xE6, 0x38, 0x36, 0x17, 0x00, +0x50, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0x00, 0x41, 0x04, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0x7F, +0x1C, 0x58, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x2A, 0xDE, 0xDE, 0xAD, 0x70, 0x79, 0x15, 0x00, 0xDC, 0x7D, 0x15, 0x00, +0x68, 0x7D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x20, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, 0x20, 0x4A, 0x2B, 0x68, 0xD2, 0xF8, 0x44, 0x24, 0x01, 0x33, 0x2B, 0x60, 0x90, 0x47, +0x2A, 0x68, 0x03, 0x46, 0x32, 0xB1, 0x19, 0x49, 0x01, 0x3A, 0x09, 0x68, 0x2A, 0x60, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, +0x18, 0x48, 0x01, 0x93, 0x1D, 0xF0, 0x4E, 0xFD, 0x00, 0x90, 0x17, 0x48, 0x1D, 0xF0, 0x4A, 0xFD, 0xDD, 0xE9, 0x00, 0x13, +0x02, 0x46, 0x15, 0x48, 0x00, 0xF0, 0xD0, 0xFC, 0x65, 0xE6, 0x14, 0x48, 0x00, 0xF0, 0xCC, 0xFC, 0x61, 0xE6, 0x60, 0xB1, +0x07, 0x1D, 0x7F, 0xF4, 0x72, 0xAF, 0x40, 0xF2, 0x31, 0x52, 0x10, 0x49, 0x10, 0x48, 0x1F, 0xF0, 0x05, 0xF9, 0x3E, 0x46, +0xD9, 0xF8, 0x00, 0x20, 0x6A, 0xE7, 0x40, 0xF2, 0x26, 0x32, 0x0B, 0x49, 0x0C, 0x48, 0x04, 0x26, 0x1F, 0xF0, 0xFA, 0xF8, +0x37, 0x46, 0xD9, 0xF8, 0x00, 0x20, 0x5F, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xA0, 0x56, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0xA4, 0x7D, 0x15, 0x00, 0x08, 0x7E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, +0x54, 0x7D, 0x15, 0x00, 0x44, 0x7D, 0x15, 0x00, 0x10, 0xB4, 0x15, 0x49, 0x15, 0x4C, 0x16, 0x4B, 0x4F, 0xF4, 0x4C, 0x02, +0x22, 0x60, 0x0A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x30, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, +0x1A, 0x68, 0x22, 0xF4, 0x40, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x4F, 0xF0, 0x60, 0x50, 0x22, 0xF4, 0x40, 0x42, 0x1A, 0x60, +0x20, 0x60, 0x08, 0x60, 0x1A, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x22, 0xF4, 0x40, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, +0x40, 0x72, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x40, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x0C, 0x40, 0x04, 0x40, +0x08, 0x40, 0x04, 0x40, 0x18, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x01, 0x46, 0x04, 0x46, 0x05, 0x48, 0x1E, 0xF0, 0x30, 0xFE, +0x04, 0x4A, 0x05, 0x4B, 0x14, 0x60, 0x4F, 0xF0, 0x80, 0x72, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x2C, 0x7E, 0x15, 0x00, +0x98, 0x40, 0x04, 0x40, 0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x00, 0x72, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, +0x00, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x4F, 0xF0, 0x80, 0x62, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, +0x08, 0xB5, 0x25, 0x4B, 0x19, 0x68, 0x4A, 0x03, 0x04, 0xD5, 0x4F, 0xF4, 0x80, 0x22, 0x43, 0xF8, 0x14, 0x2C, 0x08, 0xBD, +0x08, 0x03, 0x04, 0xD5, 0x20, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x08, 0xBD, 0x4A, 0x02, 0x0F, 0xD4, 0x0B, 0x02, +0x1D, 0xD4, 0x08, 0x01, 0x10, 0xD5, 0x1C, 0x4B, 0x1A, 0x4A, 0xDB, 0x7D, 0x4F, 0xF0, 0x00, 0x61, 0x01, 0x2B, 0x11, 0x60, +0xE9, 0xD1, 0xBD, 0xE8, 0x08, 0x40, 0x23, 0xF0, 0xED, 0xBE, 0x15, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, +0x11, 0xF0, 0x80, 0x53, 0x16, 0xD0, 0x12, 0x49, 0x10, 0x4B, 0x01, 0x20, 0x4F, 0xF0, 0x80, 0x52, 0x48, 0x75, 0x1A, 0x60, +0x08, 0xBD, 0x0D, 0x4B, 0x0E, 0x48, 0x4F, 0xF4, 0x00, 0x02, 0x1A, 0x60, 0x00, 0xF0, 0x0E, 0xFC, 0x03, 0x20, 0x00, 0xF0, +0x93, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x08, 0xBD, 0x8A, 0x00, 0xC4, 0xD5, 0x05, 0x49, 0x04, 0x4A, +0x4B, 0x75, 0x4F, 0xF0, 0x00, 0x53, 0x13, 0x60, 0x08, 0xBD, 0x00, 0xBF, 0x1C, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, +0x4C, 0x36, 0x17, 0x00, 0x40, 0x7E, 0x15, 0x00, 0x00, 0x40, 0x04, 0x40, 0x15, 0x4B, 0xD3, 0xF8, 0x24, 0x31, 0x59, 0x06, +0x09, 0xD5, 0x10, 0xB5, 0x13, 0x4C, 0x23, 0x68, 0x1A, 0x07, 0x88, 0xB0, 0xC3, 0xF3, 0xC0, 0x00, 0x03, 0xD4, 0x08, 0xB0, +0x10, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x0F, 0x49, 0x20, 0x22, 0x68, 0x46, 0x31, 0xF0, 0xC6, 0xFA, 0x0D, 0x4B, 0x1B, 0x68, +0x23, 0x68, 0xC3, 0xF3, 0x40, 0x00, 0x9B, 0x07, 0xEF, 0xD5, 0x0B, 0x4B, 0x0B, 0x4A, 0x4F, 0xF4, 0x00, 0x11, 0x19, 0x60, +0x10, 0x68, 0x10, 0xF4, 0x40, 0x13, 0xFB, 0xD0, 0x08, 0x4A, 0xC0, 0xF3, 0x00, 0x50, 0x13, 0x60, 0xE1, 0xE7, 0x00, 0xBF, +0x00, 0x00, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x30, 0x95, 0x16, 0x00, 0x30, 0x60, 0x50, 0x40, 0x00, 0x40, 0x04, 0x40, +0x04, 0x40, 0x04, 0x40, 0x08, 0x40, 0x04, 0x40, 0x01, 0x28, 0x06, 0xD0, 0x02, 0x28, 0x09, 0xD1, 0x0B, 0x4B, 0x4F, 0xF4, +0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x52, 0x72, 0x1E, 0xF0, +0xE1, 0xBF, 0x00, 0xBF, 0x00, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, +0x38, 0xB5, 0x22, 0x48, 0xFC, 0xF7, 0xFA, 0xFB, 0x83, 0x07, 0x23, 0xD5, 0x20, 0x48, 0x00, 0xF0, 0x8B, 0xFB, 0x20, 0x48, +0xFC, 0xF7, 0xF2, 0xFB, 0x04, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0xEE, 0xFB, 0x03, 0x46, 0x1D, 0x48, 0x1C, 0x40, 0xFC, 0xF7, +0xE9, 0xFB, 0x84, 0x42, 0x1F, 0xD0, 0x05, 0x20, 0x00, 0xF0, 0x14, 0xFC, 0x01, 0x28, 0x04, 0x46, 0x17, 0xD0, 0x03, 0x20, +0x00, 0xF0, 0x06, 0xFC, 0x02, 0x25, 0x21, 0x46, 0x15, 0x48, 0x00, 0xF0, 0x6F, 0xFB, 0x28, 0x46, 0xBD, 0xE8, 0x38, 0x40, +0xFF, 0xF7, 0xB2, 0xBF, 0x01, 0x46, 0x12, 0x48, 0x00, 0xF0, 0x66, 0xFB, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x08, 0xDB, 0x38, 0xBD, 0x05, 0x46, 0xE9, 0xE7, 0x20, 0x22, 0x0D, 0x48, 0x11, 0x46, 0xFC, 0xF7, 0x12, 0xFC, +0xD9, 0xE7, 0xBD, 0xE8, 0x38, 0x40, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0xD3, 0x62, 0x1E, 0xF0, 0x93, 0xBF, 0x00, 0xBF, +0x08, 0x30, 0x01, 0x50, 0x54, 0x7E, 0x15, 0x00, 0x20, 0x10, 0x01, 0x50, 0x18, 0x10, 0x01, 0x50, 0x60, 0x7E, 0x15, 0x00, +0x6C, 0x7E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x24, 0x10, 0x01, 0x50, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, +0x02, 0x48, 0x38, 0x22, 0x00, 0x21, 0xFA, 0xF7, 0x91, 0xBA, 0x00, 0xBF, 0x48, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, +0x5D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x80, 0x46, 0x0F, 0x46, 0x16, 0x46, 0xC0, 0xF2, 0xA8, 0x80, +0x00, 0x23, 0x3B, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x56, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0xB5, 0x01, 0x05, 0xF1, 0x80, 0x42, 0x02, 0xF5, 0xE2, 0x24, 0x53, 0x49, 0x23, 0x68, 0x08, 0x68, 0x43, 0xF0, 0x01, 0x03, +0x00, 0xF1, 0x01, 0x0C, 0x02, 0xF5, 0xE0, 0x22, 0x23, 0x60, 0xC1, 0xF8, 0x00, 0xC0, 0x23, 0x68, 0xDB, 0x03, 0xFC, 0xD5, +0xDF, 0xF8, 0x38, 0xE1, 0x5E, 0xF8, 0x26, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0x05, 0xF1, 0x80, 0x43, 0x03, 0xF5, +0xE0, 0x23, 0x41, 0xF2, 0x0C, 0x0A, 0x53, 0xF8, 0x0A, 0xA0, 0x1A, 0xF4, 0x00, 0x6F, 0x61, 0xD0, 0x05, 0xF1, 0x80, 0x43, +0x03, 0xF5, 0xE0, 0x23, 0x41, 0xF2, 0x08, 0x09, 0xDF, 0xF8, 0x0C, 0xA1, 0x43, 0xF8, 0x09, 0xA0, 0x41, 0xF2, 0x0C, 0x05, +0x4F, 0xF0, 0x14, 0x0A, 0x43, 0xF8, 0x05, 0xA0, 0x41, 0xF2, 0x10, 0x0B, 0x41, 0xF2, 0x14, 0x0A, 0x00, 0x25, 0x43, 0xF8, +0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x18, 0x0B, 0x41, 0xF2, 0x1C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, +0x0A, 0x50, 0x03, 0xF5, 0x81, 0x5B, 0x41, 0xF2, 0x24, 0x0A, 0xCB, 0xF8, 0x00, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, +0x28, 0x0B, 0x41, 0xF2, 0x2C, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x34, 0x0B, 0x41, 0xF2, +0x38, 0x0A, 0x43, 0xF8, 0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x50, 0x41, 0xF2, 0x3C, 0x0B, 0x41, 0xF2, 0x30, 0x0A, 0x43, 0xF8, +0x0B, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xBD, 0x68, 0x45, 0xF4, 0x00, 0x25, 0xBD, 0x60, 0x53, 0xF8, 0x09, 0x50, 0x45, 0xF0, +0x01, 0x05, 0x43, 0xF8, 0x09, 0x50, 0x41, 0xF2, 0x04, 0x05, 0x53, 0x59, 0x43, 0xF0, 0x01, 0x03, 0x53, 0x51, 0x23, 0x68, +0x4E, 0xF8, 0x26, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0x14, 0x4B, 0x08, 0x60, +0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x41, 0xF2, 0x18, 0x02, 0x9D, 0x58, 0x2D, 0x03, +0x07, 0xD5, 0x9D, 0x58, 0x41, 0xF2, 0x30, 0x0A, 0x25, 0xF4, 0x00, 0x25, 0x9D, 0x50, 0x43, 0xF8, 0x0A, 0x80, 0xD9, 0xF8, +0x08, 0x30, 0x23, 0xF4, 0x00, 0x23, 0xC9, 0xF8, 0x08, 0x30, 0xC9, 0xF8, 0x20, 0x80, 0xD8, 0xE7, 0x0D, 0x2A, 0x7F, 0xF7, +0x55, 0xAF, 0x06, 0x49, 0x06, 0x48, 0x4E, 0x22, 0x1E, 0xF0, 0xBA, 0xFE, 0x4E, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0x7E, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, +0x10, 0x00, 0x01, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x01, 0x30, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x63, 0x70, 0x47, 0x00, 0xBF, +0x3F, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0x40, 0x70, 0xB4, 0x18, 0x4D, 0x18, 0x4C, 0x2E, 0x6B, 0xB1, 0xF5, 0x00, 0x6F, +0x46, 0xF0, 0x80, 0x56, 0x2E, 0x63, 0x60, 0x60, 0xEB, 0x63, 0x20, 0x60, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, +0x80, 0x07, 0x11, 0xD0, 0xC1, 0xF3, 0x10, 0x05, 0x10, 0x48, 0x43, 0xF0, 0x0C, 0x53, 0x21, 0xF0, 0x70, 0x41, 0xA3, 0x60, +0xE5, 0x60, 0x21, 0x61, 0x60, 0x61, 0x0B, 0x49, 0x00, 0x23, 0x23, 0x62, 0x08, 0x46, 0x70, 0xBC, 0xFF, 0xF7, 0x04, 0xBF, +0xC1, 0xF3, 0x10, 0x05, 0x43, 0xF0, 0x23, 0x43, 0x21, 0xF0, 0x70, 0x41, 0x4F, 0xF0, 0x04, 0x10, 0xA3, 0x60, 0xE5, 0x60, +0x21, 0x61, 0x60, 0x61, 0xEB, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x74, 0x25, 0x17, 0x00, 0x01, 0x00, 0x04, 0x00, +0x01, 0x23, 0x06, 0x4A, 0x03, 0xFA, 0x00, 0xF0, 0x93, 0x69, 0x03, 0x42, 0xFC, 0xD1, 0x13, 0x6B, 0x23, 0xF0, 0x80, 0x53, +0x13, 0x63, 0x10, 0x6C, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0x07, 0x40, 0x08, 0x4A, 0xD3, 0x68, 0x19, 0x04, 0x44, 0xBF, +0x4F, 0xF4, 0x00, 0x01, 0x91, 0x60, 0x5B, 0x05, 0x00, 0xD4, 0x70, 0x47, 0x03, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x9A, 0x60, +0x4F, 0xF0, 0x80, 0x40, 0x1D, 0xF0, 0x4E, 0xB9, 0x00, 0x10, 0x50, 0x40, 0x11, 0x4A, 0x13, 0x68, 0x13, 0xF0, 0x01, 0x01, +0x0A, 0xD1, 0x23, 0xF4, 0x40, 0x73, 0x43, 0xF4, 0x90, 0x73, 0x43, 0xF0, 0x01, 0x03, 0x11, 0x20, 0x11, 0x61, 0x51, 0x61, +0x50, 0x60, 0x13, 0x60, 0x5A, 0x04, 0x03, 0xD4, 0x08, 0x4A, 0x43, 0xF4, 0x80, 0x43, 0x13, 0x60, 0x07, 0x4B, 0x08, 0x49, +0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x49, +0x9A, 0x68, 0xD1, 0xF8, 0xD0, 0x10, 0xC2, 0xF8, 0xB4, 0x10, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF0, 0x00, 0x52, 0x1A, 0x60, +0x70, 0x47, 0x00, 0xBF, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x3E, 0x4B, 0x1A, 0x68, 0x00, 0x2A, 0x6F, 0xD1, +0x3D, 0x49, 0xD1, 0xF8, 0xA4, 0x10, 0x00, 0x29, 0xF0, 0xB4, 0x56, 0xDA, 0x3B, 0x48, 0x00, 0x68, 0x00, 0x28, 0x4E, 0xD0, +0x3A, 0x4D, 0x3B, 0x48, 0x3B, 0x4C, 0x2A, 0x60, 0x01, 0x25, 0x02, 0x60, 0x25, 0x60, 0xC2, 0x68, 0x39, 0x4D, 0x3A, 0x4C, +0x42, 0xF4, 0x80, 0x72, 0xC2, 0x60, 0x03, 0x22, 0x2A, 0x60, 0x62, 0x68, 0x92, 0x07, 0x21, 0xF0, 0x00, 0x41, 0x57, 0xD5, +0x35, 0x4A, 0x12, 0x68, 0x10, 0x09, 0x81, 0x42, 0x4D, 0xD2, 0xB2, 0xFB, 0xF1, 0xF1, 0xC1, 0xF3, 0x42, 0x04, 0x01, 0xF0, +0x0F, 0x02, 0x12, 0x1B, 0xC1, 0xF3, 0x07, 0x1C, 0x04, 0xEB, 0x02, 0x14, 0xC1, 0xF3, 0x07, 0x31, 0x2A, 0x4A, 0x28, 0x4D, +0x10, 0x68, 0x2C, 0x4E, 0x2C, 0x4F, 0x40, 0xF0, 0x80, 0x00, 0x10, 0x60, 0xC7, 0xF8, 0x00, 0xC0, 0x29, 0x60, 0x34, 0x60, +0x11, 0x68, 0x21, 0x4C, 0x22, 0x48, 0x28, 0x4E, 0x21, 0xF0, 0x80, 0x01, 0x11, 0x60, 0x07, 0x22, 0x22, 0x60, 0x02, 0x68, +0x25, 0x4C, 0x26, 0x49, 0xD4, 0xF8, 0xBC, 0x40, 0x22, 0xF4, 0xFF, 0x72, 0x22, 0xF0, 0x01, 0x02, 0x42, 0xF0, 0x01, 0x02, +0x02, 0x60, 0x01, 0x22, 0x2A, 0x60, 0xB0, 0x68, 0x4F, 0xF4, 0x80, 0x32, 0xC0, 0xF8, 0x80, 0x40, 0x0A, 0x60, 0x01, 0x22, +0xF0, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x10, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0xF7, 0xD0, 0x10, 0x48, 0x17, 0x4C, 0x16, 0x49, +0xD4, 0xF8, 0xBC, 0x40, 0x16, 0x4A, 0x01, 0x25, 0x05, 0x60, 0x88, 0x68, 0x4F, 0xF4, 0x80, 0x31, 0xC0, 0xF8, 0x80, 0x40, +0x11, 0x60, 0xE8, 0xE7, 0x70, 0x47, 0x00, 0x24, 0x21, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0xB9, 0xE7, 0x0F, 0x48, 0x10, 0x4A, +0xA7, 0xE7, 0x00, 0xBF, 0xA4, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x28, 0x17, 0x00, 0x08, 0x10, 0x04, 0x40, +0x04, 0x10, 0x04, 0x40, 0x24, 0x10, 0x04, 0x40, 0x0C, 0x10, 0x04, 0x40, 0x00, 0x00, 0x10, 0x40, 0x14, 0x13, 0x17, 0x00, +0x28, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, +0x50, 0x97, 0x31, 0x00, 0x00, 0x75, 0x19, 0x03, 0x03, 0x4A, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x02, 0x4B, 0x18, 0x60, +0x70, 0x47, 0x00, 0xBF, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0x03, 0x4A, 0x13, 0x68, 0xDB, 0x07, 0xFC, 0xD5, +0x02, 0x4B, 0x18, 0x68, 0xC0, 0xB2, 0x70, 0x47, 0x14, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, 0xF0, 0xB5, 0x03, 0x46, +0xC3, 0xB0, 0xEF, 0xF3, 0x05, 0x85, 0x73, 0x4C, 0x22, 0x68, 0x12, 0x78, 0x02, 0x2A, 0x04, 0xD1, 0x71, 0x4A, 0xB2, 0xF8, +0xAA, 0x20, 0x52, 0x04, 0x56, 0xD4, 0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x02, 0xA8, 0x1D, 0xF0, 0x46, 0xFE, +0x06, 0x46, 0x00, 0x2E, 0x31, 0xDD, 0x6B, 0x4B, 0x1B, 0x68, 0x1B, 0xB9, 0x6A, 0x4B, 0xD3, 0xF8, 0x28, 0x33, 0x98, 0x47, +0x1D, 0xB9, 0x69, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x68, 0x4B, 0x1B, 0x68, 0x33, 0xB9, 0x67, 0x4A, 0x13, 0x68, +0x1F, 0x03, 0xFC, 0xD4, 0x66, 0x4B, 0x5F, 0x22, 0x1A, 0x60, 0x5F, 0x4B, 0xB3, 0xF8, 0xAA, 0x30, 0x13, 0xF4, 0x80, 0x43, +0x18, 0xD1, 0x02, 0xA9, 0x60, 0x4A, 0x61, 0x48, 0x77, 0x18, 0x4F, 0xF0, 0x0D, 0x0C, 0x11, 0xF8, 0x01, 0x4B, 0x0A, 0x2C, +0x1C, 0xD0, 0x13, 0x68, 0x1B, 0x03, 0xFC, 0xD4, 0x04, 0x60, 0xB9, 0x42, 0x11, 0xF8, 0x01, 0x3C, 0xF3, 0xD1, 0x15, 0xB9, +0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x30, 0x46, 0x43, 0xB0, 0xF0, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1C, 0xD0, +0x02, 0x2B, 0xF2, 0xD1, 0x53, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xED, 0xD0, 0x00, 0x2D, 0xEF, 0xD1, 0x26, 0xE0, +0x0D, 0x2B, 0xE0, 0xD0, 0x13, 0x68, 0x1C, 0x03, 0xFC, 0xD4, 0xC0, 0xF8, 0x00, 0xC0, 0x11, 0xF8, 0x01, 0x4C, 0xD8, 0xE7, +0x00, 0x91, 0x00, 0x22, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0xA8, 0x1D, 0xF0, 0xEF, 0xFD, 0x06, 0x46, 0xA7, 0xE7, 0x46, 0x4F, +0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xD2, 0xD0, 0x00, 0x2D, 0xD4, 0xD1, 0x43, 0x48, 0x1D, 0xF0, 0x07, 0xF9, 0x04, 0x28, +0x62, 0xD8, 0x23, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xC8, 0xD1, 0x3B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0xC4, 0xD0, 0x3E, 0x48, +0x1D, 0xF0, 0xFA, 0xF8, 0x04, 0x28, 0xBF, 0xD9, 0x3B, 0x48, 0x3C, 0x4C, 0x1D, 0xF0, 0xB4, 0xF8, 0x42, 0xF2, 0x34, 0x03, +0x13, 0x25, 0xE2, 0x5A, 0x8D, 0xF8, 0x08, 0x60, 0x00, 0x23, 0xB2, 0xF5, 0xC3, 0x7F, 0x02, 0xAF, 0x01, 0x46, 0x7D, 0x80, +0x7B, 0x70, 0x4D, 0xD8, 0x55, 0x1C, 0xAD, 0xB2, 0xD3, 0x00, 0x33, 0x48, 0x8A, 0x81, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xEB, +0x03, 0x00, 0x32, 0x1D, 0x47, 0x60, 0x2C, 0xF8, 0x03, 0x20, 0xC3, 0x78, 0x03, 0xF0, 0x31, 0x03, 0x43, 0xF0, 0x04, 0x03, +0xC3, 0x70, 0x94, 0xF8, 0x02, 0x3C, 0x42, 0xF2, 0x34, 0x0C, 0x01, 0x33, 0x84, 0xF8, 0x02, 0x3C, 0x01, 0x27, 0x00, 0x23, +0x24, 0xF8, 0x0C, 0x50, 0xC1, 0xE9, 0x01, 0x02, 0x8F, 0x73, 0x0B, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, +0x72, 0xB6, 0x22, 0x4B, 0x1F, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1D, 0xF0, 0x32, 0xF8, +0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x23, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x76, 0xAF, 0x19, 0x4A, 0x01, 0x3B, +0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x6F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x6C, 0xAF, 0x62, 0xB6, 0x69, 0xE7, +0x7C, 0x2E, 0x32, 0x46, 0xA8, 0xBF, 0x7C, 0x22, 0x92, 0xB2, 0x02, 0xA9, 0x13, 0x20, 0x02, 0xF0, 0xF9, 0xFA, 0x5F, 0xE7, +0x1A, 0x46, 0x01, 0x25, 0xB1, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xA4, 0x25, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x40, 0x40, 0x04, 0x40, 0x68, 0x28, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x04, 0x40, +0x74, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x0F, 0xB4, 0x00, 0xB5, 0x83, 0xB0, 0x04, 0xA9, +0x05, 0x4B, 0x51, 0xF8, 0x04, 0x0B, 0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xEB, +0x04, 0xB0, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x01, 0x22, 0x90, 0x42, 0x10, 0xB4, 0x02, 0xFA, 0x00, 0xF4, 0x11, 0xDD, +0xA0, 0xF1, 0x08, 0x03, 0x93, 0x42, 0x0D, 0xD9, 0x0F, 0x28, 0x25, 0xDD, 0x1F, 0x28, 0x12, 0xDC, 0x15, 0x4A, 0x52, 0xF8, +0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x08, 0xE0, 0x10, 0x4A, 0x52, 0xF8, +0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x43, 0xF0, 0x01, 0x03, 0x42, 0xF8, 0x20, 0x30, 0x0D, 0x4B, 0x5A, 0x68, 0x22, 0x43, +0x5A, 0x60, 0x9A, 0x68, 0x29, 0xB9, 0x22, 0xEA, 0x04, 0x02, 0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x22, 0x43, +0x9A, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x03, 0x4A, 0x52, 0xF8, 0x20, 0x30, 0x23, 0xF0, 0x0F, 0x03, 0x42, 0xF8, +0x20, 0x30, 0xE6, 0xE7, 0x00, 0x30, 0x50, 0x40, 0x00, 0x40, 0x50, 0x40, 0x04, 0x49, 0x01, 0x22, 0x0B, 0x68, 0x02, 0xFA, +0x00, 0xF0, 0x23, 0xEA, 0x00, 0x03, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x40, 0x50, 0x40, 0x10, 0xB5, 0x01, 0x29, +0x82, 0xB0, 0x04, 0x46, 0x10, 0xD0, 0x20, 0xF0, 0x03, 0x03, 0x0F, 0x22, 0x9A, 0x40, 0x11, 0x46, 0x0D, 0x48, 0xFC, 0xF7, +0x51, 0xF8, 0x01, 0x22, 0xA2, 0x40, 0x0C, 0x48, 0x11, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x48, 0xB8, +0x01, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x07, 0x48, 0x01, 0x92, 0xFC, 0xF7, 0x41, 0xF8, 0x01, 0x9A, 0x05, 0x48, 0x11, 0x46, +0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFC, 0xF7, 0x39, 0xB8, 0x00, 0xBF, 0x2C, 0x10, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, +0x08, 0x10, 0x01, 0x50, 0x01, 0x23, 0x03, 0xFA, 0x00, 0xF2, 0x11, 0x46, 0x01, 0x48, 0xFC, 0xF7, 0x2B, 0xB8, 0x00, 0xBF, +0x00, 0x10, 0x01, 0x50, 0x01, 0x22, 0x82, 0x40, 0x00, 0x21, 0x01, 0x48, 0xFC, 0xF7, 0x22, 0xB8, 0x00, 0x10, 0x01, 0x50, +0x10, 0xB5, 0x04, 0x46, 0x03, 0x48, 0xFB, 0xF7, 0xCB, 0xFF, 0xE0, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x10, 0xBD, 0x00, 0xBF, +0x00, 0x10, 0x01, 0x50, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x0E, 0x48, 0x0F, 0x4A, +0x03, 0x68, 0x0F, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xC2, 0x03, 0x03, 0x60, 0x13, 0x68, 0x23, 0xF0, 0xFF, 0x03, +0x43, 0xF0, 0xC2, 0x03, 0x13, 0x60, 0x03, 0x68, 0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0x03, 0x60, 0x13, 0x68, +0x23, 0xF4, 0x7F, 0x23, 0x43, 0xF4, 0x3F, 0x23, 0xC2, 0x20, 0x13, 0x60, 0xC8, 0x71, 0x70, 0x47, 0xAC, 0xB3, 0x33, 0x40, +0xD4, 0xB3, 0x33, 0x40, 0x80, 0x35, 0x17, 0x00, 0x24, 0x4B, 0x25, 0x48, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0x24, 0x4D, +0x24, 0x4F, 0x6A, 0x79, 0x95, 0xF9, 0x07, 0x10, 0x3C, 0x68, 0x23, 0x4E, 0x03, 0xF0, 0x0F, 0x03, 0x1A, 0x44, 0x52, 0xB2, +0x89, 0x1A, 0x6F, 0xF0, 0x3D, 0x03, 0x99, 0x42, 0xB8, 0xBF, 0x19, 0x46, 0x5F, 0xFA, 0x81, 0xFC, 0x24, 0xF0, 0xFF, 0x04, +0x44, 0xEA, 0x0C, 0x04, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xEA, 0x0C, 0x03, 0x33, 0x60, 0x3C, 0x68, +0xCB, 0x1E, 0x5F, 0xFA, 0x83, 0xFC, 0x24, 0xF4, 0x7F, 0x24, 0x44, 0xEA, 0x0C, 0x34, 0x3C, 0x60, 0x33, 0x68, 0x23, 0xF4, +0x7F, 0x23, 0x4C, 0xB2, 0x43, 0xEA, 0x0C, 0x33, 0x33, 0x60, 0x21, 0x46, 0xEC, 0x71, 0x1E, 0xF0, 0xC3, 0xF8, 0x3D, 0x34, +0x0E, 0xDB, 0x0D, 0x4B, 0x29, 0x89, 0x1A, 0x69, 0x0C, 0x4B, 0x47, 0xF2, 0x30, 0x54, 0x05, 0xF1, 0x0C, 0x00, 0x04, 0xFB, +0x01, 0x21, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x1C, 0x01, 0x32, 0x40, +0xB8, 0x7E, 0x15, 0x00, 0x80, 0x35, 0x17, 0x00, 0xAC, 0xB3, 0x33, 0x40, 0xD4, 0xB3, 0x33, 0x40, 0x00, 0x10, 0x50, 0x40, +0x88, 0x1A, 0x17, 0x00, 0x12, 0x4A, 0x12, 0x68, 0xD2, 0xE9, 0x06, 0x01, 0x38, 0xB5, 0x11, 0x4B, 0x15, 0x6A, 0x18, 0x60, +0x59, 0x60, 0x50, 0x6A, 0x0F, 0x4C, 0xD2, 0xE9, 0x0A, 0x12, 0xC3, 0xE9, 0x02, 0x50, 0xC3, 0xE9, 0x04, 0x12, 0xD4, 0xF8, +0x2C, 0x33, 0x98, 0x47, 0xD4, 0xF8, 0xC0, 0x30, 0x98, 0x47, 0xFB, 0xF7, 0xAF, 0xFA, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x78, +0x03, 0x2B, 0x02, 0xD1, 0xD4, 0xF8, 0x20, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x38, 0x40, 0xFF, 0xF7, 0x79, 0xBB, 0x00, 0xBF, +0xC8, 0x35, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x30, 0xB4, 0x08, 0x4B, +0x08, 0x48, 0x18, 0x60, 0xC2, 0x25, 0x40, 0xF6, 0xEC, 0x20, 0x4F, 0xF4, 0x7A, 0x74, 0x06, 0x49, 0x06, 0x4A, 0xDD, 0x71, +0x98, 0x80, 0x1C, 0x81, 0x19, 0x61, 0x30, 0xBC, 0x1A, 0x62, 0x70, 0x47, 0x80, 0x35, 0x17, 0x00, 0x01, 0x00, 0x00, 0x14, +0x95, 0x64, 0x12, 0x00, 0x4D, 0x64, 0x12, 0x00, 0x90, 0xF8, 0x62, 0x30, 0xCB, 0xB9, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x03, 0xDB, 0x00, 0x23, 0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x90, 0xF8, +0xAC, 0x30, 0x01, 0x2B, 0xF7, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xE7, 0x12, 0x1E, 0xF0, 0xBB, 0xFA, 0x00, 0x23, +0x84, 0xF8, 0xAC, 0x30, 0x10, 0xBD, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xCC, 0x7E, 0x15, 0x00, +0x13, 0x4A, 0x90, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, +0x1B, 0xD1, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xDB, 0x94, 0xF8, +0x23, 0x10, 0x0B, 0x48, 0x1E, 0xF0, 0x1E, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x70, 0x32, 0x10, 0xBD, 0x90, 0xF8, 0x70, 0x32, +0x01, 0x2B, 0xF2, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x1E, 0xF0, 0x8A, 0xFA, 0xEB, 0xE7, 0x70, 0x47, +0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0x7F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x7E, 0x15, 0x00, +0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0x62, 0x40, 0x1C, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x06, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, +0xF0, 0x81, 0xD0, 0xE9, 0x24, 0x23, 0xD0, 0xF8, 0x98, 0x10, 0x42, 0x48, 0xDF, 0xF8, 0x30, 0x81, 0x1D, 0xF0, 0xF0, 0xFF, +0x45, 0x46, 0x06, 0xF5, 0xB2, 0x77, 0x28, 0x46, 0x06, 0x22, 0x39, 0x46, 0x30, 0xF0, 0xD8, 0xFC, 0x14, 0x35, 0x40, 0xB1, +0x01, 0x34, 0x05, 0x2C, 0xF5, 0xD1, 0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5B, 0xDB, 0x04, 0xEB, +0x84, 0x03, 0x08, 0xEB, 0x83, 0x03, 0xA2, 0x00, 0xD9, 0x79, 0x00, 0x29, 0xD9, 0xD1, 0x1B, 0x7A, 0x03, 0xBB, 0xD6, 0xF8, +0x90, 0x30, 0x31, 0x2B, 0x29, 0xD9, 0xD6, 0xF8, 0x94, 0x10, 0xB1, 0xEB, 0x53, 0x0F, 0x3B, 0xD8, 0x14, 0x44, 0x08, 0xEB, +0x84, 0x08, 0x98, 0xF8, 0x06, 0x30, 0x00, 0x2B, 0x48, 0xD1, 0x00, 0x23, 0xC6, 0xE9, 0x24, 0x33, 0x29, 0x4A, 0xC6, 0xF8, +0x98, 0x30, 0x12, 0x69, 0x28, 0x49, 0x29, 0x4B, 0x06, 0xF1, 0x9C, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, +0x11, 0x44, 0x18, 0x47, 0xD6, 0xF8, 0x98, 0x30, 0x53, 0xB3, 0xD6, 0xF8, 0x90, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x11, 0x19, +0x08, 0xEB, 0x81, 0x01, 0x00, 0x20, 0x08, 0x72, 0xD3, 0xE7, 0x0B, 0x2B, 0x12, 0xD8, 0xD6, 0xF8, 0x98, 0x20, 0x14, 0x2A, +0xDB, 0xD9, 0x00, 0x2B, 0xD9, 0xD1, 0x1B, 0x48, 0x1D, 0xF0, 0x9A, 0xFF, 0x18, 0x4B, 0x01, 0x22, 0x88, 0xF8, 0x06, 0x20, +0x30, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD6, 0xF8, 0x94, 0x10, 0x14, 0x4A, 0xA2, 0xFB, +0x03, 0x02, 0x22, 0xF0, 0x03, 0x00, 0x00, 0xEB, 0x92, 0x02, 0x8A, 0x42, 0xE1, 0xD8, 0xE6, 0xE7, 0xD6, 0xF8, 0x90, 0x30, +0xD5, 0xE7, 0x0F, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0x13, 0x22, 0x1E, 0xF0, 0xF5, 0xF9, 0x9C, 0xE7, 0x00, 0x23, 0x0D, 0x48, +0x88, 0xF8, 0x06, 0x30, 0x1D, 0xF0, 0x74, 0xFF, 0xAF, 0xE7, 0x0B, 0x48, 0xD4, 0xE7, 0x00, 0xBF, 0x1C, 0x7F, 0x15, 0x00, +0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0xC3, 0xC9, 0x01, 0x88, 0x1A, 0x17, 0x00, 0x44, 0x7F, 0x15, 0x00, +0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3C, 0x7F, 0x15, 0x00, 0x30, 0x7F, 0x15, 0x00, +0xCC, 0x35, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, +0xEF, 0xBC, 0x03, 0xF0, 0xD5, 0xBF, 0x00, 0xF0, 0xD7, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, +0x00, 0xF0, 0x6C, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x30, 0x4C, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x1E, 0xD0, +0x02, 0x2B, 0x14, 0xD1, 0x2D, 0x4B, 0x2E, 0x49, 0x2E, 0x4A, 0xC3, 0xE9, 0x06, 0x12, 0x2E, 0x4D, 0xD5, 0xF8, 0x14, 0x31, +0x98, 0x47, 0xD5, 0xF8, 0x18, 0x31, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0x1D, 0xD0, +0x03, 0x2B, 0x0E, 0xD0, 0x70, 0xBD, 0x03, 0x2B, 0xED, 0xD1, 0x22, 0x4B, 0x25, 0x49, 0x26, 0x4A, 0xC3, 0xE9, 0x08, 0x12, +0xE7, 0xE7, 0x1F, 0x4B, 0x24, 0x49, 0x25, 0x4A, 0xC3, 0xE9, 0x02, 0x12, 0xE1, 0xE7, 0x24, 0x4B, 0x1B, 0x4C, 0x24, 0x4A, +0x1A, 0x60, 0x04, 0xF0, 0x87, 0xFC, 0x23, 0x6A, 0x22, 0x48, 0x98, 0x47, 0x63, 0x6A, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, +0x1D, 0x4B, 0x20, 0x49, 0x20, 0x4A, 0x19, 0x60, 0x13, 0x4D, 0x42, 0xF2, 0x34, 0x03, 0x00, 0x21, 0xD1, 0x52, 0x04, 0xF0, +0x1B, 0xF8, 0x03, 0xF0, 0x35, 0xFF, 0xAB, 0x69, 0x18, 0x48, 0x98, 0x47, 0xEB, 0x69, 0x98, 0x47, 0x04, 0xF0, 0x1A, 0xFC, +0x23, 0x68, 0x1B, 0x78, 0xCA, 0xE7, 0x12, 0x4B, 0x09, 0x4D, 0x16, 0x4A, 0x1A, 0x60, 0x00, 0xF0, 0xCB, 0xFE, 0x00, 0xF0, +0xE9, 0xFE, 0x00, 0xF0, 0x13, 0xFF, 0xAB, 0x68, 0x0E, 0x48, 0x98, 0x47, 0xEB, 0x68, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, +0xB6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x28, 0x58, 0x17, 0x00, 0xA1, 0xA9, 0x12, 0x00, 0x85, 0xA9, 0x12, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x3D, 0xB2, 0x12, 0x00, 0x29, 0xB2, 0x12, 0x00, 0x0D, 0x7A, 0x12, 0x00, 0xF9, 0x79, 0x12, 0x00, +0x1C, 0x58, 0x17, 0x00, 0xBC, 0x60, 0x17, 0x00, 0xB8, 0x7F, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, +0x28, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x0B, 0x4C, 0x50, 0x22, 0x51, 0x23, 0x04, 0xF2, 0x14, 0x50, 0xA4, 0xF8, 0x10, 0x25, +0x84, 0xF8, 0x12, 0x35, 0x1C, 0xF0, 0xD8, 0xFC, 0x27, 0x22, 0x28, 0x23, 0x04, 0xF5, 0xF4, 0x60, 0xA4, 0xF8, 0x9C, 0x27, +0x84, 0xF8, 0x9E, 0x37, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0xF0, 0xCC, 0xBC, 0x58, 0x58, 0x17, 0x00, 0x70, 0xB5, 0x41, 0xF6, +0x10, 0x02, 0x25, 0x4D, 0x25, 0x4C, 0x4C, 0xF2, 0xBF, 0x03, 0x41, 0xF6, 0x12, 0x00, 0x00, 0x26, 0xAB, 0x52, 0x41, 0xF6, +0x14, 0x01, 0x05, 0xF5, 0xC1, 0x52, 0xA5, 0xF8, 0x00, 0x3C, 0x2E, 0x54, 0x05, 0xF6, 0x08, 0x40, 0x6E, 0x50, 0x16, 0x70, +0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0x1C, 0xF0, 0xAE, 0xFC, 0xA4, 0xF1, 0x0C, 0x00, 0x1C, 0xF0, 0xAA, 0xFC, +0x04, 0xF5, 0x00, 0x60, 0x1C, 0xF0, 0xA6, 0xFC, 0x04, 0xF6, 0x08, 0x00, 0x1C, 0xF0, 0xA2, 0xFC, 0x42, 0xF2, 0x34, 0x03, +0x31, 0x46, 0x4F, 0xF4, 0x00, 0x62, 0x20, 0x46, 0xEE, 0x52, 0x85, 0xF8, 0x02, 0x6C, 0xC5, 0xF8, 0x04, 0x6C, 0xF9, 0xF7, +0x05, 0xFC, 0x04, 0xF5, 0x00, 0x65, 0x2E, 0x46, 0x21, 0x46, 0x30, 0x46, 0x10, 0x34, 0x1C, 0xF0, 0x91, 0xFC, 0xAC, 0x42, +0xF8, 0xD1, 0x09, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, +0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x82, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x7C, 0x36, 0x17, 0x00, 0xA0, 0x4E, 0x17, 0x00, +0xD8, 0x56, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x40, 0x20, 0x85, 0xB0, 0x1C, 0xF0, 0xF6, 0xFB, 0xA7, 0x4B, 0x9B, 0x68, +0x03, 0x93, 0x00, 0x2B, 0x00, 0xF0, 0x80, 0x81, 0xDF, 0xF8, 0xB0, 0x92, 0xDF, 0xF8, 0xB0, 0xB2, 0x09, 0xE0, 0x94, 0xF8, +0x64, 0x30, 0x63, 0xB1, 0x03, 0x9B, 0x1B, 0x68, 0x03, 0x93, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x71, 0x81, 0x03, 0x9C, +0x20, 0x46, 0x07, 0xF0, 0x33, 0xFF, 0x00, 0x28, 0xEF, 0xD0, 0x03, 0x9B, 0x9A, 0x4C, 0x03, 0xF5, 0xA3, 0x65, 0x01, 0x26, +0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x60, 0x23, 0x68, 0x28, 0x46, 0x01, 0x33, +0x23, 0x60, 0x1C, 0xF0, 0x8B, 0xFC, 0x23, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x60, 0x0A, 0xB9, +0x03, 0xB1, 0x62, 0xB6, 0x05, 0x21, 0x38, 0xB1, 0xDB, 0xF8, 0x24, 0x34, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, +0xE7, 0xD4, 0xE3, 0xE7, 0x89, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0xC8, 0xD1, 0xDD, 0xF8, 0x0C, 0xA0, 0x87, 0x4E, +0x04, 0x23, 0x01, 0x93, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x9D, 0xF8, 0x04, 0x70, 0x0A, 0xF5, +0xA2, 0x68, 0x40, 0x46, 0x1C, 0xF0, 0x62, 0xFC, 0x80, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, +0x43, 0x7F, 0x7F, 0xDB, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x25, 0x10, 0x19, 0xB9, 0xE9, 0x8B, +0x08, 0x07, 0x40, 0xF1, 0x07, 0x81, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x62, 0x92, 0xF8, 0x24, 0x20, 0x01, 0x2A, +0x00, 0xF0, 0x9E, 0x80, 0xDB, 0xF8, 0x24, 0x34, 0x28, 0x46, 0x39, 0x46, 0x98, 0x47, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, +0xD7, 0xD1, 0x0A, 0xF5, 0x9D, 0x65, 0xA8, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, +0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0xDA, 0xF8, 0xE8, 0x14, 0x5A, 0x1C, 0x22, 0x60, 0x2A, 0xB1, 0xD9, 0xF8, 0x00, 0x20, +0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x29, 0x34, 0xD0, 0x4A, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x02, 0x63, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x87, 0x80, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x46, 0xD0, +0xC9, 0x7E, 0xDB, 0xF8, 0x34, 0x31, 0x10, 0x46, 0x98, 0x47, 0x00, 0x28, 0x00, 0xF0, 0xD7, 0x80, 0xEF, 0xF3, 0x10, 0x83, +0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, +0x1C, 0xF0, 0x00, 0xFC, 0x23, 0x68, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x24, 0x34, 0x39, 0x46, 0x28, 0x46, 0x98, 0x47, 0x00, 0x2D, 0xB4, 0xD1, 0x01, 0x9B, +0x01, 0x3B, 0x1D, 0x46, 0x38, 0x46, 0x01, 0x93, 0x0B, 0xF0, 0x26, 0xFA, 0x2B, 0x46, 0x01, 0x33, 0xAA, 0xF1, 0x08, 0x0A, +0x3F, 0xF4, 0x38, 0xAF, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, 0x7F, 0xF4, 0x74, 0xAF, 0x9D, 0xF8, 0x04, 0x70, 0x9C, 0xE7, +0x09, 0x2B, 0x7F, 0xF6, 0x7D, 0xAF, 0x3C, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0x96, 0x72, 0x1D, 0xF0, 0xE1, 0xFF, 0x6B, 0x7F, +0x74, 0xE7, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x02, 0x92, +0x01, 0x33, 0x40, 0x46, 0x23, 0x60, 0x1C, 0xF0, 0xC1, 0xFB, 0x23, 0x68, 0x02, 0x9A, 0x05, 0x46, 0x33, 0xB1, 0x01, 0x3B, +0xD9, 0xF8, 0x00, 0x10, 0x23, 0x60, 0x0B, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x01, 0x9B, 0x4F, 0x20, 0x00, 0xFB, 0x02, 0x30, +0x41, 0x30, 0x06, 0xEB, 0xC0, 0x00, 0x29, 0x46, 0x1C, 0xF0, 0x68, 0xFB, 0x00, 0x2D, 0x7F, 0xF4, 0x6F, 0xAF, 0xB8, 0xE7, +0x23, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x4D, 0xDB, 0xEA, 0x8B, 0xD2, 0x07, 0x7F, 0xF5, 0x5D, 0xAF, +0x01, 0x9A, 0x4F, 0x20, 0x46, 0x32, 0x10, 0xFB, 0x03, 0x20, 0x29, 0x46, 0x06, 0xEB, 0xC0, 0x00, 0x1C, 0xF0, 0x50, 0xFB, +0x51, 0xE7, 0x93, 0xF8, 0x23, 0x10, 0x1B, 0x48, 0x1D, 0xF0, 0x24, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x01, 0x23, 0xC9, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x40, 0x46, 0x01, 0x33, 0x23, 0x60, 0x1C, 0xF0, 0x80, 0xFB, +0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x05, 0x46, 0x28, 0xF0, 0x2A, 0xFE, 0x23, 0x68, 0x00, 0x2B, 0x85, 0xD0, 0x01, 0x3B, +0xD9, 0xF8, 0x00, 0x20, 0x23, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0x7F, 0xAF, 0x00, 0x2A, 0x3F, 0xF4, 0x7C, 0xAF, 0x62, 0xB6, +0x00, 0x2D, 0x7F, 0xF4, 0x2F, 0xAF, 0x78, 0xE7, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, +0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xEA, 0x8B, 0xD1, 0x07, 0xB2, 0xD4, 0x11, 0x49, 0x11, 0x48, 0x02, 0x93, +0x40, 0xF2, 0x35, 0x12, 0x1D, 0xF0, 0x5A, 0xFF, 0x02, 0x9B, 0xA5, 0xE7, 0x92, 0xF8, 0x23, 0x10, 0x0D, 0x48, 0x1D, 0xF0, +0xD9, 0xFC, 0x28, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0x39, 0x46, 0x28, 0xF0, 0xED, 0xFD, 0xDA, 0xF8, 0x10, 0x35, 0x00, 0x2B, +0x7F, 0xF4, 0xD3, 0xAE, 0xF9, 0xE6, 0x07, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x00, 0x32, 0x42, 0xE7, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0x8C, 0x7F, 0x15, 0x00, 0x7C, 0x7F, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, +0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, 0x07, 0xD0, 0x06, 0x4B, 0xD3, 0xF8, 0x30, 0x31, +0x18, 0x47, 0x04, 0x4B, 0xD3, 0xF8, 0x08, 0x33, 0x18, 0x47, 0x03, 0xF0, 0x8F, 0xBF, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x03, 0xD1, 0x06, 0x4B, +0xD3, 0xF8, 0x34, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x93, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x00, 0x33, 0x18, 0x47, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x07, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0x2B, +0x01, 0xD0, 0x04, 0xF0, 0x83, 0xBB, 0x04, 0xF0, 0x7B, 0xB8, 0x03, 0x4B, 0xD3, 0xF8, 0x0C, 0x33, 0x18, 0x47, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, +0x03, 0xD1, 0x06, 0x4B, 0xD3, 0xF8, 0x38, 0x34, 0x18, 0x47, 0x04, 0xF0, 0x6D, 0xBB, 0x03, 0x4B, 0xD3, 0xF8, 0x04, 0x33, +0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, +0x05, 0xD0, 0x02, 0x2B, 0x01, 0xD0, 0x04, 0xF0, 0x5D, 0xBB, 0x04, 0xF0, 0xAD, 0xB9, 0x01, 0xF0, 0x6B, 0xB9, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0x08, 0xB5, 0x0C, 0x22, 0x08, 0x23, 0x01, 0x21, 0x40, 0xF2, 0x0D, 0x40, 0x1B, 0xF0, 0xE6, 0xFD, +0xBD, 0xE8, 0x08, 0x40, 0x1B, 0xF0, 0x12, 0xBE, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x82, 0x46, 0x00, 0x68, 0x05, 0x91, +0x03, 0x90, 0x07, 0x92, 0x62, 0xB1, 0xB0, 0xFB, 0xF2, 0xF3, 0x11, 0x46, 0x02, 0xFB, 0x13, 0x02, 0x0B, 0x46, 0x00, 0x2A, +0x40, 0xF0, 0xDE, 0x80, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, 0x9A, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0x00, 0xF0, +0xD2, 0x80, 0x00, 0x23, 0xDF, 0xF8, 0xC0, 0x81, 0xDF, 0xF8, 0xC0, 0x91, 0x00, 0x93, 0x1F, 0x46, 0xD3, 0x46, 0x08, 0xE0, +0x00, 0x9B, 0x9B, 0xF8, 0x08, 0x20, 0x01, 0x33, 0xDF, 0xB2, 0xBA, 0x42, 0x00, 0x93, 0x40, 0xF2, 0xC0, 0x80, 0x05, 0x9B, +0xDB, 0xF8, 0x0C, 0x10, 0x33, 0xF8, 0x27, 0x00, 0x03, 0xEB, 0x87, 0x02, 0x00, 0x24, 0x55, 0x88, 0x07, 0xEB, 0x47, 0x02, +0x01, 0xEB, 0x82, 0x06, 0x41, 0xF8, 0x22, 0x40, 0xB4, 0x80, 0x00, 0x2D, 0xE4, 0xD0, 0x03, 0x1D, 0x01, 0x93, 0x03, 0x9B, +0x75, 0x80, 0x03, 0xF1, 0x04, 0x0A, 0x02, 0x95, 0xB0, 0x80, 0x55, 0x46, 0xCD, 0xF8, 0x18, 0xB0, 0xA2, 0x46, 0x04, 0x97, +0x34, 0xE0, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x37, 0xD3, 0x04, 0x9B, 0x05, 0xF8, 0x04, 0x3C, 0xD8, 0xF8, +0x00, 0x30, 0xAB, 0x42, 0x41, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x3C, 0xD3, 0x55, 0x23, 0x05, 0xF8, +0x03, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x46, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0x41, 0xD3, +0x00, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x4B, 0xD8, 0xD8, 0xF8, 0x04, 0x20, 0x13, 0x44, +0xAB, 0x42, 0x46, 0xD3, 0xCB, 0xF8, 0x04, 0x70, 0x33, 0x88, 0x01, 0x99, 0x01, 0x33, 0x01, 0x34, 0x33, 0x80, 0x02, 0x9B, +0xA2, 0xB2, 0x93, 0x42, 0x0D, 0x44, 0x48, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x57, 0x46, 0xA5, 0xF1, 0x04, 0x0B, +0xAA, 0x46, 0xC2, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, +0xBE, 0xD2, 0x31, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xE9, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xBD, 0xD9, 0xD9, 0xF8, +0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB9, 0xD2, 0x29, 0x48, 0x29, 0x46, +0xFF, 0xF7, 0xD8, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0xB8, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, +0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, 0xAB, 0x42, 0xB4, 0xD2, 0x22, 0x48, 0x29, 0x46, 0xFF, 0xF7, 0xC7, 0xF9, 0xD8, 0xF8, +0x00, 0x30, 0xAB, 0x42, 0xB3, 0xD9, 0xD9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x04, 0xD8, 0xD9, 0xF8, 0x04, 0x20, 0x13, 0x44, +0xAB, 0x42, 0xAF, 0xD2, 0x29, 0x46, 0x1A, 0x48, 0xFF, 0xF7, 0xB6, 0xF9, 0xAC, 0xE7, 0x0A, 0x46, 0x5D, 0x1E, 0x03, 0x99, +0xDD, 0xF8, 0x18, 0xB0, 0xAD, 0xB2, 0x05, 0xFB, 0x02, 0x13, 0x05, 0xFB, 0x02, 0x25, 0x48, 0x19, 0x07, 0x99, 0x03, 0x90, +0x04, 0x33, 0xB3, 0x60, 0x00, 0x29, 0x3F, 0xF4, 0x47, 0xAF, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, 0x13, 0x02, 0x0B, 0x46, +0x22, 0xB1, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x03, 0x9A, 0x04, 0x3B, 0x1A, 0x44, 0x03, 0x92, +0x36, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x8B, 0x1A, 0x03, 0x2B, 0x9C, 0xBF, 0x0A, 0x46, 0x9B, 0x18, 0x1B, 0xE7, +0xE0, 0x7F, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0xC8, 0x25, 0x17, 0x00, +0xE4, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x06, 0x7A, 0x00, 0x2E, 0x00, 0xF0, 0xBC, 0x80, 0xC5, 0x68, 0x00, 0x2D, 0x00, 0xF0, +0x82, 0x80, 0x2C, 0x46, 0x01, 0x23, 0x09, 0xE0, 0x22, 0x88, 0xA2, 0xB9, 0x9E, 0x42, 0x0F, 0xD9, 0x03, 0xEB, 0x43, 0x04, +0x05, 0xEB, 0x84, 0x04, 0x01, 0x33, 0xDB, 0xB2, 0xA0, 0x88, 0x88, 0x42, 0x03, 0xEB, 0x43, 0x02, 0xF0, 0xD2, 0x9E, 0x42, +0x02, 0xD9, 0x05, 0xEB, 0x82, 0x04, 0xF3, 0xE7, 0x9E, 0x42, 0x00, 0xF0, 0x9E, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x4E, 0x4E, 0x23, 0x88, 0x35, 0x68, 0x6A, 0x1C, 0x32, 0x60, +0x00, 0x2B, 0x5D, 0xD0, 0x4B, 0x4F, 0xA5, 0x68, 0x3A, 0x68, 0xAA, 0x42, 0x28, 0xD8, 0x79, 0x68, 0x11, 0x44, 0x8D, 0x42, +0x24, 0xD8, 0x29, 0x68, 0xA1, 0x60, 0x01, 0x3B, 0xAA, 0x42, 0x23, 0x80, 0x32, 0xD8, 0x7B, 0x68, 0x13, 0x44, 0xAB, 0x42, +0x2E, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x53, 0xD1, 0xAA, 0x23, 0x05, 0xF8, 0x03, 0x3C, 0x3B, 0x68, 0x9D, 0x42, +0x5D, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9D, 0x42, 0x59, 0xD8, 0x01, 0x23, 0x05, 0xF8, 0x02, 0x3C, 0x33, 0x68, 0x00, 0x2B, +0x34, 0xD0, 0x36, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x7B, 0xBB, 0x72, 0xB3, 0x35, 0xE0, 0x35, 0x48, 0x01, 0x68, +0x8D, 0x42, 0x03, 0xD3, 0x40, 0x68, 0x01, 0x44, 0x8D, 0x42, 0xD2, 0xD9, 0x29, 0x46, 0x32, 0x48, 0xFF, 0xF7, 0x12, 0xF9, +0x23, 0x88, 0x3A, 0x68, 0x00, 0x21, 0x01, 0x3B, 0xAA, 0x42, 0xA1, 0x60, 0x23, 0x80, 0xCC, 0xD9, 0x2B, 0x48, 0x03, 0x68, +0xAB, 0x42, 0x1F, 0xD8, 0x41, 0x68, 0x19, 0x44, 0xA9, 0x42, 0x1B, 0xD3, 0x15, 0xF8, 0x03, 0x1C, 0x55, 0x29, 0x1C, 0xD1, +0xAA, 0x42, 0x37, 0xD9, 0x42, 0x68, 0x13, 0x44, 0x9D, 0x42, 0xC2, 0xD9, 0x29, 0x46, 0x24, 0x48, 0xFF, 0xF7, 0xF4, 0xF8, +0xC0, 0xE7, 0x23, 0x48, 0xFF, 0xF7, 0xF0, 0xF8, 0x28, 0x46, 0xF8, 0xBD, 0xC2, 0xB1, 0x1A, 0x4B, 0x35, 0x60, 0x1B, 0x68, +0xA5, 0xB9, 0x9B, 0xB1, 0x62, 0xB6, 0xF5, 0xE7, 0x29, 0x46, 0x1D, 0x48, 0xFF, 0xF7, 0xE2, 0xF8, 0x00, 0x21, 0x33, 0x68, +0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x48, 0x2A, 0x46, +0xFF, 0xF7, 0xD4, 0xF8, 0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x0F, 0x4A, 0x13, 0x68, 0x9D, 0x42, 0x03, 0xD3, 0x52, 0x68, +0x13, 0x44, 0x9D, 0x42, 0x9D, 0xD9, 0x29, 0x46, 0x10, 0x48, 0xFF, 0xF7, 0xC5, 0xF8, 0x9B, 0xE7, 0x79, 0x68, 0x0A, 0x44, +0x95, 0x42, 0x8A, 0xD9, 0x9D, 0x42, 0xC5, 0xD3, 0xC0, 0xE7, 0x0C, 0x48, 0xFF, 0xF7, 0xBA, 0xF8, 0x00, 0x25, 0xC7, 0xE7, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xCC, 0x80, 0x15, 0x00, +0x10, 0x80, 0x15, 0x00, 0x98, 0x80, 0x15, 0x00, 0x00, 0x81, 0x15, 0x00, 0x28, 0x81, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, +0xB4, 0x80, 0x15, 0x00, 0x00, 0x29, 0x00, 0xF0, 0x0F, 0x81, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x68, 0x8B, 0x42, 0x05, 0x46, +0x0C, 0x46, 0x59, 0xD8, 0x42, 0x68, 0x13, 0x44, 0x99, 0x42, 0x55, 0xD8, 0x83, 0x4F, 0x3B, 0x68, 0x99, 0x42, 0x55, 0xD3, +0x7A, 0x68, 0x13, 0x44, 0x99, 0x42, 0x51, 0xD8, 0x14, 0xF8, 0x04, 0x6C, 0x2B, 0x7A, 0xB3, 0x42, 0x48, 0xD9, 0xD5, 0xF8, +0x0C, 0x80, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x7A, 0x4D, +0x38, 0x68, 0x2B, 0x68, 0x84, 0x42, 0x03, 0xF1, 0x01, 0x03, 0x2B, 0x60, 0x25, 0xD3, 0x7B, 0x68, 0x03, 0x44, 0x9C, 0x42, +0x21, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x00, 0xF0, 0xAB, 0x80, 0xB9, 0xF1, 0xFF, 0x0F, 0x20, 0xD1, +0x7B, 0x68, 0x18, 0x44, 0x84, 0x42, 0x00, 0xF2, 0xA1, 0x80, 0x14, 0xF8, 0x02, 0x0C, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, +0x02, 0x0C, 0x00, 0x28, 0x47, 0xD0, 0x2B, 0x68, 0x33, 0xB1, 0x67, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x40, 0xB2, 0xBD, 0xE8, 0xF8, 0x83, 0x64, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x1E, 0xD2, 0x63, 0x48, +0x21, 0x46, 0xFF, 0xF7, 0x47, 0xF8, 0x2B, 0x68, 0x33, 0xB1, 0x5D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF0, 0xFF, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0x59, 0x4B, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, +0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, 0xA5, 0xD9, 0x57, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x26, 0xA1, 0xE7, +0x59, 0x68, 0x11, 0x44, 0x8C, 0x42, 0xDC, 0xD8, 0x14, 0xF8, 0x03, 0x9C, 0xB9, 0xF1, 0xAA, 0x0F, 0x6C, 0xD0, 0xB9, 0xF1, +0xFF, 0x0F, 0xD8, 0xD1, 0x84, 0x42, 0xB5, 0xD2, 0x1A, 0x68, 0x94, 0x42, 0x03, 0xD3, 0x5B, 0x68, 0x1A, 0x44, 0x94, 0x42, +0xB3, 0xD9, 0x4B, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0x13, 0xF8, 0xB9, 0xF1, 0xFF, 0x0F, 0x5D, 0xD0, 0x06, 0xEB, 0x46, 0x06, +0x08, 0xEB, 0x86, 0x09, 0x38, 0xF8, 0x26, 0x20, 0xB9, 0xF8, 0x02, 0x30, 0x9A, 0x42, 0x4F, 0xEA, 0x86, 0x06, 0xBC, 0xD2, +0x3B, 0x68, 0x9C, 0x42, 0x31, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x2D, 0xD8, 0x55, 0x23, 0x04, 0xF8, 0x03, 0x3C, +0x3B, 0x68, 0x9C, 0x42, 0x1A, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x16, 0xD8, 0xD9, 0xF8, 0x08, 0x30, 0x23, 0x60, +0x38, 0xF8, 0x06, 0x30, 0x28, 0x68, 0xC9, 0xF8, 0x08, 0x40, 0x01, 0x33, 0x28, 0xF8, 0x06, 0x30, 0x38, 0xB1, 0x2E, 0x4B, +0x01, 0x38, 0x1B, 0x68, 0x28, 0x60, 0x10, 0xB9, 0x0B, 0xB1, 0x62, 0xB6, 0xA2, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, +0x2A, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, 0xE0, 0xD9, 0x21, 0x46, 0x2A, 0x48, +0xFE, 0xF7, 0xD0, 0xFF, 0xDE, 0xE7, 0x24, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, +0xC9, 0xD9, 0x21, 0x46, 0x24, 0x48, 0xFE, 0xF7, 0xC3, 0xFF, 0xC7, 0xE7, 0x1D, 0x4B, 0xA1, 0xE7, 0x14, 0xF8, 0x02, 0x0C, +0x01, 0x38, 0xC0, 0xB2, 0x04, 0xF8, 0x02, 0x0C, 0x00, 0x28, 0x7F, 0xF4, 0x5C, 0xAF, 0xA5, 0xE7, 0x84, 0x42, 0xBF, 0xF4, +0x4B, 0xAF, 0x96, 0xE7, 0x3B, 0x68, 0x9C, 0x42, 0x11, 0xD3, 0x7A, 0x68, 0x13, 0x44, 0x9C, 0x42, 0x0D, 0xD8, 0x01, 0x23, +0x04, 0xF8, 0x02, 0x3C, 0x2B, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x01, 0x20, 0x60, 0xE7, 0x0B, 0x4A, 0x13, 0x68, 0x9C, 0x42, 0x03, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x9C, 0x42, +0xE9, 0xD9, 0x21, 0x46, 0x0C, 0x48, 0xFE, 0xF7, 0x91, 0xFF, 0xE7, 0xE7, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x00, 0xBF, +0xC8, 0x25, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x81, 0x15, 0x00, +0x50, 0x81, 0x15, 0x00, 0x80, 0x81, 0x15, 0x00, 0x64, 0x80, 0x15, 0x00, 0x10, 0x80, 0x15, 0x00, 0x38, 0x80, 0x15, 0x00, +0x0B, 0x4A, 0x13, 0x68, 0x83, 0x42, 0x05, 0xD8, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x01, 0xD8, 0x01, 0x20, 0x70, 0x47, +0x07, 0x4A, 0x13, 0x68, 0x98, 0x42, 0x06, 0xD3, 0x52, 0x68, 0x13, 0x44, 0x98, 0x42, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, +0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0xC8, 0x25, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0x4B, 0x70, 0xB5, +0x10, 0x4C, 0xDC, 0x60, 0x15, 0x46, 0x0E, 0x46, 0x03, 0x24, 0x01, 0x46, 0x20, 0x22, 0x18, 0x46, 0x5D, 0x60, 0x1C, 0x72, +0x1E, 0x60, 0xFF, 0xF7, 0xCD, 0xFC, 0x0B, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x01, 0x21, 0x4F, 0xF0, 0x02, 0x15, 0x04, 0x24, +0x4F, 0xF4, 0x80, 0x20, 0x5A, 0x60, 0x00, 0x22, 0xC3, 0xE9, 0x05, 0x40, 0xDD, 0x60, 0x19, 0x60, 0x99, 0x60, 0x1A, 0x61, +0x9A, 0x83, 0x70, 0xBD, 0xE4, 0x25, 0x17, 0x00, 0xF4, 0x25, 0x17, 0x00, 0xA8, 0x25, 0x17, 0x00, 0x38, 0xB5, 0x0F, 0x4B, +0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0x46, 0x0D, 0xD0, 0x0D, 0x48, 0x7C, 0x21, 0xFF, 0xF7, 0xAB, 0xFD, 0x04, 0x46, +0x2C, 0xB1, 0x20, 0x46, 0xFF, 0xF7, 0xAC, 0xFF, 0x38, 0xB1, 0x04, 0xF8, 0x01, 0x5C, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xF0, +0xC3, 0xF9, 0x04, 0x46, 0xF2, 0xE7, 0x21, 0x46, 0x04, 0x48, 0xFE, 0xF7, 0x17, 0xFF, 0x20, 0x46, 0x38, 0xBD, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xAC, 0x81, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0x92, 0xFF, +0x98, 0xB1, 0x31, 0x4B, 0x14, 0xF8, 0x04, 0x2C, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x23, 0xD0, 0x02, 0x2B, 0x2A, 0xD0, +0x03, 0x2B, 0x15, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x30, 0xDB, 0x02, 0x2A, 0x30, 0xD0, +0x10, 0xBD, 0x29, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0xF1, 0xFE, 0x25, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x11, 0xD0, +0x02, 0x2B, 0x18, 0xD0, 0x03, 0x2B, 0x29, 0xD0, 0x20, 0x46, 0xFF, 0xF7, 0x6D, 0xFF, 0x90, 0xB3, 0x21, 0x46, 0x21, 0x48, +0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x3C, 0xBE, 0x02, 0x2A, 0x0F, 0xD0, 0x00, 0x2A, 0xE3, 0xD1, 0x20, 0x46, 0xBD, 0xE8, +0x10, 0x40, 0x00, 0xF0, 0x9B, 0xB9, 0x02, 0x2A, 0x26, 0xD0, 0x00, 0x2A, 0xDA, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, +0x03, 0xF0, 0xF2, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x45, 0xB9, 0x02, 0x2A, 0x0C, 0xD1, 0x13, 0x4B, +0x20, 0x46, 0xD3, 0xF8, 0xE8, 0x34, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xC1, 0xDA, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x0D, 0x48, 0xBE, 0x22, 0x1D, 0xF0, 0xF5, 0xBA, 0x21, 0x46, +0x0B, 0x48, 0xFE, 0xF7, 0xAD, 0xFE, 0xC7, 0xE7, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x03, 0xF0, 0x21, 0xB9, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x50, 0x81, 0x15, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xD4, 0x81, 0x15, 0x00, 0xE4, 0x81, 0x15, 0x00, 0x30, 0xB5, 0x1A, 0x4C, 0x1A, 0x4A, 0x23, 0x68, +0x1A, 0x48, 0x5D, 0x88, 0x99, 0x88, 0xB2, 0xF8, 0xD4, 0x20, 0x85, 0xB0, 0x04, 0x3A, 0xAD, 0xF8, 0x02, 0x50, 0xDD, 0x88, +0xAD, 0xF8, 0x06, 0x10, 0x19, 0x89, 0xAD, 0xF8, 0x0A, 0x50, 0xD3, 0xE9, 0x05, 0x35, 0xAD, 0xF8, 0x0E, 0x10, 0x01, 0x21, +0x03, 0x60, 0x01, 0x72, 0x10, 0x4B, 0x45, 0x60, 0x0C, 0x21, 0xC3, 0x60, 0xAD, 0xF8, 0x0C, 0x20, 0x40, 0xF2, 0x3C, 0x63, +0xAD, 0xF8, 0x00, 0x10, 0x7C, 0x25, 0x69, 0x46, 0x20, 0x22, 0xAD, 0xF8, 0x08, 0x30, 0xAD, 0xF8, 0x04, 0x50, 0xFF, 0xF7, +0xE9, 0xFB, 0x23, 0x68, 0x01, 0xA8, 0xD3, 0xE9, 0x07, 0x12, 0xFF, 0xF7, 0x07, 0xFF, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, 0xD8, 0x25, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, +0x0C, 0x48, 0x1B, 0xF0, 0x3F, 0xFE, 0x2B, 0x68, 0x5B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x0C, 0x21, +0x38, 0x46, 0xFF, 0xF7, 0xCB, 0xFC, 0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x35, 0xFE, 0x2B, 0x68, 0x01, 0x34, 0x5A, 0x88, +0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0xC8, 0x25, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x4C, 0x80, 0x0F, 0x48, 0x1B, 0xF0, 0x1D, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x89, +0xB3, 0xB1, 0x0D, 0x4D, 0x0D, 0x4F, 0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x38, 0x46, 0xFF, 0xF7, 0xA6, 0xFC, +0x01, 0x46, 0x30, 0x46, 0x1B, 0xF0, 0x10, 0xFE, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x68, 0x11, 0x89, 0x01, 0x34, 0xA2, 0xB2, +0x01, 0x33, 0x91, 0x42, 0x2B, 0x60, 0xEC, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x60, 0x17, 0x00, 0x18, 0x26, 0x17, 0x00, +0xE4, 0x25, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x1B, 0xF0, 0xF3, 0xFD, 0x2B, 0x68, +0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, 0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFF, 0xF7, 0x7F, 0xFC, 0x01, 0x46, +0x30, 0x46, 0x1B, 0xF0, 0xE9, 0xFD, 0x2B, 0x68, 0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, +0x78, 0x36, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, +0x1B, 0xF0, 0x10, 0xFE, 0x23, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, +0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, +0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xAB, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, +0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x08, 0x60, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0xCE, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, +0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, +0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x61, 0xFD, 0x0A, 0x49, +0x23, 0x68, 0x0A, 0x68, 0x01, 0x32, 0x0A, 0x60, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x60, 0x17, 0x00, +0x18, 0x26, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, 0x7E, 0xFD, 0x23, 0x68, 0x33, 0xB1, +0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x1B, 0xF0, +0x19, 0xFD, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, +0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x60, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, +0x41, 0x4B, 0xDF, 0xF8, 0x20, 0xB1, 0x1B, 0x68, 0x40, 0x4D, 0x1F, 0x8E, 0xDF, 0xF8, 0x18, 0x91, 0xDF, 0xF8, 0x18, 0x81, +0x8B, 0x89, 0x0C, 0x46, 0x06, 0x46, 0x9F, 0x42, 0x6A, 0xD9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x2B, 0x63, 0xD9, 0xD6, 0xE9, +0x01, 0x03, 0x1B, 0x69, 0x98, 0x47, 0x82, 0x46, 0x00, 0x28, 0x62, 0xD0, 0xFF, 0xF7, 0x0E, 0xFF, 0x00, 0x28, 0x4A, 0xD0, +0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, 0x42, 0x60, 0x53, 0x44, 0x82, 0x60, 0x03, 0x60, 0xEF, 0xF3, 0x10, 0x83, +0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0xDB, 0xF8, 0x00, 0x30, 0xD2, 0xF8, +0x00, 0xC0, 0x43, 0xF0, 0x01, 0x03, 0x0C, 0xF1, 0x01, 0x01, 0x11, 0x60, 0xCB, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x30, +0x9B, 0x07, 0xFB, 0xD4, 0x2B, 0x68, 0x1B, 0xBB, 0xD9, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x00, 0x2B, 0x68, 0xB4, 0xF8, +0x0C, 0xE0, 0x60, 0x60, 0x0E, 0xF1, 0x01, 0x0E, 0x98, 0xB2, 0x01, 0x30, 0x1F, 0xFA, 0x8E, 0xF3, 0xA3, 0x81, 0x28, 0x60, +0xDB, 0xF8, 0x00, 0x00, 0x20, 0xF0, 0x01, 0x00, 0xCB, 0xF8, 0x00, 0x00, 0x00, 0x29, 0xB4, 0xD0, 0x18, 0x49, 0xC2, 0xF8, +0x00, 0xC0, 0x0A, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0xAD, 0xD1, 0x00, 0x2A, 0xAB, 0xD0, 0x62, 0xB6, 0xA3, 0x89, 0xA8, 0xE7, +0x63, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x58, 0x60, 0xDA, 0xE7, 0x12, 0x48, 0xFE, 0xF7, 0xAA, 0xFC, 0xD6, 0xE9, 0x01, 0x03, +0x51, 0x46, 0x5B, 0x69, 0x98, 0x47, 0x09, 0x4B, 0xA2, 0x89, 0x1B, 0x68, 0x5B, 0x8E, 0x9A, 0x42, 0x02, 0xD2, 0x04, 0x20, +0x1B, 0xF0, 0xEA, 0xFB, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0xD8, 0xF8, 0x00, 0x10, 0x08, 0x48, 0xFE, 0xF7, 0x94, 0xFC, +0xED, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x64, 0x00, 0x24, 0x40, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x24, 0x82, 0x15, 0x00, 0x0C, 0x82, 0x15, 0x00, 0x60, 0x00, 0x24, 0x40, 0x68, 0x00, 0x24, 0x40, +0x18, 0x26, 0x17, 0x00, 0x08, 0xB5, 0x03, 0x4B, 0xD3, 0xF8, 0xF8, 0x32, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, +0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x4A, 0x0A, 0x49, 0x0B, 0x4C, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, +0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0xC1, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x8B, 0x60, 0x8B, 0x73, 0x10, 0x46, 0xD4, 0xF8, +0x10, 0x31, 0x98, 0x47, 0x01, 0x20, 0x10, 0xBD, 0x28, 0x60, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0xB9, 0x4B, 0xD3, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, 0x30, 0x81, 0xEF, 0xF3, +0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0xB4, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDF, 0xF8, 0x04, 0x93, 0xB1, 0x4B, +0xD9, 0xF8, 0x00, 0x20, 0xD3, 0xF8, 0x14, 0x35, 0x51, 0x1C, 0xC9, 0xF8, 0x00, 0x10, 0x31, 0xB1, 0xAD, 0x49, 0xC9, 0xF8, +0x00, 0x20, 0x09, 0x68, 0x0A, 0xB9, 0x01, 0xB1, 0x62, 0xB6, 0x93, 0xF8, 0x0C, 0xB0, 0x5A, 0x7B, 0x5C, 0x68, 0x05, 0x92, +0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x38, 0x81, 0x00, 0x2C, 0x00, 0xF0, 0x35, 0x81, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xF0, +0x31, 0x81, 0xA3, 0x4B, 0x07, 0x93, 0x9B, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0xC0, 0xF0, 0x5C, 0x81, +0xDF, 0xF8, 0xB0, 0xA2, 0x00, 0x26, 0xAA, 0xE0, 0xD4, 0xE9, 0x00, 0x53, 0x03, 0x93, 0x6B, 0x1E, 0xB3, 0xF5, 0xE8, 0x1F, +0x27, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x95, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x03, 0x9B, +0xD9, 0xF8, 0x00, 0x70, 0x01, 0x93, 0x23, 0x68, 0x93, 0x48, 0x00, 0x93, 0x5A, 0x46, 0x23, 0x46, 0x31, 0x46, 0x01, 0x37, +0xC9, 0xF8, 0x00, 0x70, 0x1C, 0xF0, 0xC4, 0xFD, 0x4F, 0xF4, 0x80, 0x71, 0xA4, 0xF1, 0x80, 0x00, 0x1D, 0xF0, 0x9C, 0xF9, +0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x88, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x20, 0x46, 0xFF, 0xF7, 0x1A, 0xFE, 0x6B, 0x7E, 0x2F, 0x7E, 0x09, 0x2B, 0x09, 0xD8, 0x83, 0x4A, 0x4F, 0xF4, +0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x6B, 0x8B, 0x13, 0xF0, +0x08, 0x0F, 0x7E, 0x4B, 0x40, 0xF0, 0xBC, 0x80, 0x1A, 0x46, 0x04, 0x93, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, +0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xCC, 0x80, 0x95, 0xF8, 0x16, 0x80, 0xB8, 0xF1, 0x05, 0x0F, 0x00, 0xF2, +0x09, 0x81, 0x75, 0x4C, 0x75, 0x48, 0x1B, 0xF0, 0xF1, 0xFB, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, +0xC0, 0xF2, 0xA5, 0x80, 0xE1, 0x8B, 0x71, 0x4B, 0xE2, 0x6C, 0x13, 0xF8, 0x08, 0xC0, 0x21, 0xF0, 0x01, 0x01, 0x00, 0x23, +0xE1, 0x83, 0x63, 0x64, 0x13, 0x61, 0xE3, 0x62, 0x6B, 0x4B, 0x29, 0x46, 0x0C, 0xF1, 0x01, 0x0C, 0x1C, 0x22, 0x20, 0x1D, +0x03, 0xF8, 0x08, 0xC0, 0x2F, 0xF0, 0x8A, 0xFA, 0xE1, 0x8B, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x23, 0x21, 0xF4, 0x00, 0x42, +0x84, 0xF8, 0x42, 0x30, 0x22, 0xF0, 0x02, 0x02, 0x2D, 0x1A, 0x63, 0x62, 0x23, 0x65, 0x0B, 0x07, 0xE2, 0x83, 0xA5, 0x64, +0x00, 0xF1, 0x87, 0x80, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, +0x13, 0x44, 0x5A, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, +0xA4, 0x20, 0x04, 0x9B, 0x00, 0xFB, 0x07, 0x80, 0x99, 0x30, 0x21, 0x46, 0x03, 0xEB, 0xC0, 0x00, 0x03, 0x9C, 0x1B, 0xF0, +0x61, 0xFB, 0x01, 0x36, 0xF3, 0xB2, 0x9B, 0x45, 0x16, 0xD9, 0x05, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x51, 0xAF, 0x4D, 0x49, +0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x7E, 0xFD, 0x20, 0x46, 0xD4, 0xE9, 0x00, 0x54, 0xFF, 0xF7, 0x93, 0xFD, 0xDA, 0xF8, +0x00, 0x00, 0x01, 0x36, 0x28, 0x1A, 0xFF, 0xF7, 0x4B, 0xFC, 0xF3, 0xB2, 0x9B, 0x45, 0xE8, 0xD8, 0x07, 0x9A, 0x06, 0x99, +0x93, 0x89, 0x5B, 0x1A, 0x93, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4A, 0x01, 0x23, +0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x3D, 0x48, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x75, 0xFB, 0x2F, 0x49, +0x91, 0xF8, 0x11, 0x35, 0xD1, 0xF8, 0x14, 0x25, 0x01, 0x3B, 0x81, 0xF8, 0x11, 0x35, 0x00, 0x2A, 0x00, 0xF0, 0x94, 0x80, +0xD9, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0xDC, 0xAE, 0x28, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, +0x00, 0x2B, 0x7F, 0xF4, 0xD4, 0xAE, 0x00, 0x2A, 0x3F, 0xF4, 0xD1, 0xAE, 0x62, 0xB6, 0x21, 0x4B, 0xD3, 0xF8, 0x14, 0x35, +0x00, 0x2B, 0x7F, 0xF4, 0xD0, 0xAE, 0x40, 0x20, 0x1B, 0xF0, 0x6A, 0xFA, 0x04, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, +0x1B, 0xF0, 0x64, 0xBA, 0x1F, 0x4C, 0x04, 0x93, 0x4F, 0xF0, 0x05, 0x08, 0x50, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x58, 0xAF, +0x21, 0x49, 0x22, 0x48, 0x4F, 0xF4, 0xE5, 0x72, 0x1C, 0xF0, 0x4C, 0xFF, 0x50, 0xE7, 0x04, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, +0x00, 0xFB, 0x07, 0x30, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0x03, 0x9C, 0x1B, 0xF0, 0xEC, 0xFA, 0x89, 0xE7, 0xDA, 0xF8, +0x00, 0x00, 0x03, 0x9C, 0x28, 0x1A, 0xFF, 0xF7, 0xE7, 0xFB, 0x82, 0xE7, 0x0A, 0x4B, 0x16, 0x48, 0x07, 0x93, 0x1D, 0x46, +0xFE, 0xF7, 0xEE, 0xFA, 0xAB, 0x89, 0x1F, 0xFA, 0x8B, 0xF2, 0x5B, 0x45, 0x06, 0x92, 0x27, 0xD3, 0xBB, 0xF1, 0x00, 0x0F, +0x7F, 0xF4, 0xC8, 0xAE, 0x8C, 0xE7, 0x00, 0xBF, 0x58, 0x58, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, +0x50, 0x82, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, +0x74, 0x28, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xB4, 0x82, 0x15, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x9C, 0x82, 0x15, 0x00, 0x34, 0x82, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x10, 0x48, 0xFE, 0xF7, +0xBD, 0xFA, 0xBB, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x9D, 0xAE, 0x61, 0xE7, 0x0D, 0x48, 0x0E, 0x4C, 0x1C, 0xF0, 0x7E, 0xFC, +0x80, 0x21, 0xA5, 0xF1, 0x40, 0x00, 0x1D, 0xF0, 0x57, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, +0xE9, 0xAE, 0x08, 0x49, 0x08, 0x48, 0x4F, 0xF4, 0xE3, 0x72, 0x1C, 0xF0, 0xE7, 0xFE, 0xE1, 0xE6, 0x20, 0x20, 0x1B, 0xF0, +0x11, 0xFA, 0x67, 0xE7, 0x44, 0x82, 0x15, 0x00, 0x74, 0x82, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x88, 0x82, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x24, 0x91, 0xDF, 0xF8, 0x24, 0x81, 0x42, 0x4F, 0x43, 0x4B, +0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0x5E, 0xD0, 0x15, 0x7B, 0xD2, 0xF8, 0x04, 0xA0, 0x56, 0x7B, 0x65, 0xB3, 0x4F, 0xF0, +0x00, 0x0B, 0x11, 0xE0, 0xDA, 0xE9, 0x00, 0x4A, 0xFF, 0xF7, 0xB0, 0xFC, 0x20, 0x46, 0xFD, 0xF7, 0x03, 0xFB, 0xD8, 0xF8, +0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x64, 0xFB, 0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0x17, 0xD2, +0x50, 0x46, 0x39, 0x46, 0x00, 0x2E, 0xE9, 0xD0, 0x4F, 0xF4, 0x80, 0x60, 0x1C, 0xF0, 0x80, 0xFC, 0x50, 0x46, 0xDA, 0xE9, +0x00, 0x4A, 0xFF, 0xF7, 0x95, 0xFC, 0xD8, 0xF8, 0x00, 0x00, 0x0B, 0xF1, 0x01, 0x0B, 0x20, 0x1A, 0xFF, 0xF7, 0x4C, 0xFB, +0x5F, 0xFA, 0x8B, 0xF1, 0xA9, 0x42, 0xE7, 0xD3, 0x28, 0x4A, 0x93, 0x89, 0x5D, 0x1B, 0x95, 0x81, 0xEF, 0xF3, 0x10, 0x83, +0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x25, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x23, 0x48, 0x01, 0x33, +0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x76, 0xFA, 0x1D, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x91, 0xF8, 0x9D, 0x37, 0x01, 0x3B, +0x81, 0xF8, 0x9D, 0x37, 0x00, 0x2A, 0xAA, 0xD0, 0x1A, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, +0xA3, 0xD1, 0x00, 0x2B, 0xA1, 0xD0, 0x62, 0xB6, 0x13, 0x4B, 0xD3, 0xF8, 0xA0, 0x27, 0x00, 0x2A, 0xA0, 0xD1, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, +0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x8A, 0xF9, 0x04, 0x20, 0x1B, 0xF0, 0x63, 0xF9, 0xD9, 0xF8, +0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, +0xBD, 0xE8, 0xF8, 0x8F, 0xB0, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0xF8, 0x5F, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xD8, 0x80, +0xDF, 0xF8, 0xD8, 0x90, 0xDF, 0xF8, 0xD8, 0xA0, 0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x41, 0xD0, 0x1F, 0x89, 0x5D, 0x68, +0xBF, 0xB1, 0x00, 0x24, 0x26, 0x46, 0x23, 0x46, 0xB3, 0x42, 0xAB, 0x46, 0x04, 0xF1, 0x01, 0x04, 0x6D, 0x68, 0x08, 0xD1, +0xDA, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x9B, 0xF8, 0x0B, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x1E, 0x44, 0xB6, 0xB2, 0x58, 0x46, +0xFF, 0xF7, 0x0A, 0xFC, 0xA3, 0xB2, 0xBB, 0x42, 0xEA, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x1F, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x1E, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, +0xF7, 0xF9, 0x99, 0xF8, 0x02, 0x3C, 0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x02, 0x3C, 0x00, 0x2A, 0xC7, 0xD0, +0x15, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xD1, 0x00, 0x2B, 0xBE, 0xD0, 0x62, 0xB6, +0xD9, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0xBD, 0xD1, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x10, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x1B, 0xF0, 0x0E, 0xF9, +0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x84, 0x42, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x7C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0xB4, 0x80, 0x2A, 0x4E, 0xC1, 0x46, +0xA8, 0xF1, 0x06, 0x07, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0x1D, 0x89, 0x5C, 0x68, 0x7D, 0xB1, 0x4F, 0xF0, +0x00, 0x0B, 0x20, 0x68, 0xA2, 0x46, 0x0B, 0xF1, 0x01, 0x0B, 0x64, 0x68, 0xFF, 0xF7, 0x5E, 0xFA, 0x50, 0x46, 0xFF, 0xF7, +0x9D, 0xFB, 0x1F, 0xFA, 0x8B, 0xF2, 0xAA, 0x42, 0xF1, 0xD3, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x48, 0x46, 0x01, 0x33, 0x33, 0x60, 0x1B, 0xF0, 0x8B, 0xF9, 0x3B, 0x78, +0x32, 0x68, 0x01, 0x3B, 0x3B, 0x70, 0x00, 0x2A, 0xD4, 0xD0, 0x14, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x32, 0x60, 0x00, 0x2A, +0xCE, 0xD1, 0x00, 0x2B, 0xCC, 0xD0, 0x62, 0xB6, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xD1, 0xEF, 0xF3, 0x10, 0x83, +0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x08, 0x20, 0x01, 0x33, 0x33, 0x60, +0x1B, 0xF0, 0xA8, 0xF8, 0x33, 0x68, 0x33, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x94, 0x4E, 0x17, 0x00, +0x10, 0xB5, 0x04, 0x20, 0x1B, 0xF0, 0x92, 0xF8, 0x03, 0x4B, 0x04, 0x49, 0xD3, 0xF8, 0x10, 0x31, 0x03, 0x48, 0xBD, 0xE8, +0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x60, 0x17, 0x00, 0x28, 0x60, 0x17, 0x00, 0xF8, 0xB5, 0xA8, 0x4B, +0xA8, 0x4A, 0x1B, 0x68, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x65, 0x05, 0x18, 0xD5, +0xA4, 0x4A, 0x13, 0x68, 0x98, 0x00, 0xFC, 0xD4, 0xA3, 0x4B, 0xA2, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x13, 0xF0, 0x00, 0x53, +0xFB, 0xD1, 0xA1, 0x49, 0xA1, 0x48, 0x0A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x0A, 0x60, 0x02, 0x78, 0x02, 0xB1, 0x03, 0x70, +0x9E, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0xE0, 0x81, 0x21, 0x05, 0x09, 0xD5, 0x97, 0x4A, 0x13, 0x68, 0x9B, 0x00, +0xFC, 0xD4, 0x9A, 0x4B, 0x94, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xE2, 0x04, 0x05, 0xD5, 0x94, 0x49, +0x96, 0x4B, 0x97, 0x4A, 0x01, 0x20, 0x08, 0x70, 0x1A, 0x60, 0x66, 0x06, 0x04, 0xD5, 0x95, 0x4B, 0x95, 0x48, 0x19, 0x68, +0x1C, 0xF0, 0x9C, 0xFA, 0x14, 0xF4, 0x9B, 0x7F, 0x40, 0xF0, 0x89, 0x81, 0xA5, 0x05, 0x00, 0xF1, 0x8D, 0x81, 0x20, 0x06, +0x00, 0xF1, 0x94, 0x81, 0x21, 0x04, 0x00, 0xF1, 0x9F, 0x81, 0xE2, 0x02, 0x00, 0xF1, 0xA6, 0x81, 0xA3, 0x02, 0x03, 0xD5, +0x8B, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x1A, 0x60, 0xE7, 0x03, 0x41, 0xD5, 0x89, 0x4B, 0x93, 0xF8, 0x11, 0x15, 0x93, 0xF8, +0x12, 0x25, 0x91, 0x42, 0x80, 0xF0, 0xB1, 0x81, 0x93, 0xF8, 0x10, 0x05, 0x85, 0x4A, 0x86, 0x4D, 0x86, 0x4E, 0x01, 0x30, +0xA2, 0xFB, 0x00, 0x72, 0x92, 0x09, 0x02, 0xEB, 0xC2, 0x02, 0x02, 0xEB, 0xC2, 0x02, 0x82, 0x1A, 0x01, 0x31, 0x83, 0xF8, +0x11, 0x15, 0x83, 0xF8, 0x10, 0x25, 0x03, 0xEB, 0x02, 0x11, 0x30, 0x68, 0x2E, 0x68, 0x4E, 0x60, 0x6E, 0x68, 0x8E, 0x60, +0x28, 0x3D, 0xC0, 0xF3, 0x00, 0x26, 0x08, 0x73, 0x4E, 0x73, 0x28, 0x68, 0x40, 0xF0, 0x10, 0x00, 0x11, 0x01, 0x28, 0x60, +0x28, 0x68, 0x86, 0x06, 0xFC, 0xD4, 0x19, 0x44, 0x75, 0x4B, 0x8A, 0x68, 0x75, 0x48, 0x52, 0x68, 0x1A, 0x60, 0x2B, 0x68, +0x23, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x1B, 0xF0, 0x6F, 0xF8, 0x20, 0x20, 0x1A, 0xF0, 0xCA, 0xFF, 0x69, 0x4B, 0x4F, 0xF4, +0x80, 0x32, 0x1A, 0x60, 0x65, 0x03, 0x4E, 0xD5, 0x67, 0x4B, 0x93, 0xF8, 0x9D, 0x17, 0x93, 0xF8, 0x9E, 0x27, 0x91, 0x42, +0x80, 0xF0, 0x7B, 0x81, 0x93, 0xF8, 0x9C, 0x07, 0x68, 0x4A, 0x69, 0x4F, 0x69, 0x4D, 0xDF, 0xF8, 0xE0, 0xC1, 0x01, 0x30, +0xA2, 0xFB, 0x00, 0x62, 0x56, 0x09, 0x06, 0xEB, 0x86, 0x06, 0xA0, 0xEB, 0xC6, 0x06, 0x4A, 0x1C, 0x83, 0xF8, 0x9D, 0x27, +0x83, 0xF8, 0x9C, 0x67, 0x03, 0xEB, 0x06, 0x11, 0x3A, 0x68, 0x28, 0x68, 0xC1, 0xF8, 0x20, 0x05, 0x06, 0xF1, 0x52, 0x07, +0x03, 0xEB, 0x07, 0x15, 0xDC, 0xF8, 0x00, 0x10, 0x5C, 0x48, 0x69, 0x60, 0xC2, 0xF3, 0x00, 0x21, 0x69, 0x72, 0x2A, 0x72, +0x05, 0x68, 0x45, 0xF0, 0x04, 0x05, 0x05, 0x60, 0x31, 0x01, 0x05, 0x46, 0x2A, 0x68, 0x10, 0x07, 0xFC, 0xD4, 0x03, 0xEB, +0x07, 0x12, 0x01, 0xF2, 0x1C, 0x51, 0x50, 0x68, 0x53, 0x4A, 0x40, 0x68, 0x10, 0x60, 0x2A, 0x68, 0x52, 0x48, 0x22, 0xF0, +0x04, 0x02, 0x19, 0x44, 0x2A, 0x60, 0x1B, 0xF0, 0x1F, 0xF8, 0x4F, 0xF4, 0x00, 0x00, 0x1A, 0xF0, 0x79, 0xFF, 0x41, 0x4B, +0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xA2, 0x03, 0x1B, 0xD5, 0x4B, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x35, 0x81, +0x49, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, 0xC0, 0xF0, 0xA2, 0x80, 0x46, 0x48, 0x1C, 0xF0, +0xDF, 0xF9, 0x36, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x44, 0x4B, 0x1B, 0x68, 0x23, 0xB9, 0x43, 0x4A, 0x13, 0x78, +0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0x23, 0x03, 0x1D, 0xD5, 0x3C, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x40, 0xF0, 0x09, 0x81, +0x3A, 0x48, 0x41, 0xF6, 0x12, 0x04, 0x41, 0xF6, 0x11, 0x03, 0x02, 0x5D, 0xC3, 0x5C, 0x93, 0x42, 0x10, 0xD8, 0x11, 0x46, +0x39, 0x48, 0x1C, 0xF0, 0xBF, 0xF9, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0xB9, +0x33, 0x4A, 0x13, 0x78, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x70, 0xF8, 0xBD, 0x41, 0xF6, 0x10, 0x05, 0x32, 0x4B, 0x41, 0x5D, +0x01, 0x31, 0xA3, 0xFB, 0x01, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA1, 0xEB, 0x83, 0x13, 0x43, 0x55, 0x03, 0xF1, +0xC1, 0x01, 0x2D, 0x4E, 0x00, 0xEB, 0x01, 0x11, 0x35, 0x68, 0x4D, 0x60, 0x2B, 0x4D, 0x00, 0xEB, 0x03, 0x13, 0x01, 0x32, +0x2D, 0x68, 0xA3, 0xF8, 0x18, 0x5C, 0x02, 0x55, 0x28, 0x48, 0x1A, 0xF0, 0xB9, 0xFF, 0x08, 0x20, 0x1A, 0xF0, 0x14, 0xFF, +0x0E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0xCF, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x00, 0x24, 0x40, +0x40, 0x00, 0x24, 0x40, 0x01, 0x09, 0x00, 0x32, 0x44, 0x00, 0x24, 0x40, 0x1C, 0x26, 0x17, 0x00, 0x3C, 0x36, 0x17, 0x00, +0x02, 0x09, 0x00, 0x32, 0x2C, 0x00, 0x24, 0x40, 0x09, 0x70, 0x00, 0xCF, 0x08, 0x00, 0x24, 0x40, 0xDC, 0x82, 0x15, 0x00, +0x28, 0x00, 0x24, 0x40, 0x58, 0x58, 0x17, 0x00, 0xE7, 0x87, 0x45, 0xCA, 0x88, 0x00, 0x24, 0x40, 0x90, 0x00, 0x24, 0x40, +0x74, 0x00, 0x24, 0x40, 0x6C, 0x5D, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, 0x84, 0x00, 0x24, 0x40, 0x7C, 0x00, 0x24, 0x40, +0x60, 0x00, 0x24, 0x40, 0x6C, 0x00, 0x24, 0x40, 0xF8, 0x5F, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, +0x80, 0x83, 0x15, 0x00, 0xA0, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x98, 0x83, 0x15, 0x00, 0x98, 0x00, 0x24, 0x40, +0xAB, 0xAA, 0xAA, 0xAA, 0xA4, 0x00, 0x24, 0x40, 0xA8, 0x00, 0x24, 0x40, 0x94, 0x4E, 0x17, 0x00, 0x80, 0x00, 0x24, 0x40, +0x90, 0xF8, 0x00, 0x2C, 0x4B, 0x4B, 0x4C, 0x4D, 0x01, 0x32, 0xA3, 0xFB, 0x02, 0x63, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, +0xA2, 0xEB, 0x83, 0x13, 0x00, 0xEB, 0x03, 0x12, 0x2D, 0x68, 0x55, 0x60, 0x46, 0x4D, 0x80, 0xF8, 0x00, 0x3C, 0x2B, 0x68, +0x13, 0x81, 0x01, 0x31, 0x80, 0xF8, 0x02, 0x1C, 0x11, 0x46, 0x00, 0xF6, 0x08, 0x40, 0x1A, 0xF0, 0x49, 0xFF, 0x10, 0x20, +0x1A, 0xF0, 0xA4, 0xFE, 0x3F, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x1A, 0x60, 0x3F, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x46, 0xAE, +0x3C, 0x49, 0x3D, 0x48, 0x26, 0x22, 0x1C, 0xF0, 0x8D, 0xFB, 0x14, 0xF4, 0x9B, 0x7F, 0x3F, 0xF4, 0x77, 0xAE, 0x3A, 0x48, +0x21, 0x46, 0x1C, 0xF0, 0x0B, 0xF9, 0xA5, 0x05, 0x7F, 0xF5, 0x73, 0xAE, 0x37, 0x48, 0x1C, 0xF0, 0x05, 0xF9, 0x32, 0x4B, +0x4F, 0xF4, 0x00, 0x72, 0x20, 0x06, 0x1A, 0x60, 0x7F, 0xF5, 0x6C, 0xAE, 0x33, 0x48, 0x1C, 0xF0, 0xFB, 0xF8, 0x33, 0x4A, +0x2C, 0x49, 0x13, 0x68, 0x80, 0x20, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x08, 0x60, 0x21, 0x04, 0x7F, 0xF5, 0x61, 0xAE, +0x2E, 0x48, 0x1C, 0xF0, 0xED, 0xF8, 0x26, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0xE2, 0x02, 0x7F, 0xF5, 0x5A, 0xAE, +0x2A, 0x4A, 0x2B, 0x4B, 0x15, 0x68, 0x2B, 0x48, 0x1A, 0x78, 0x29, 0x46, 0xFD, 0xF7, 0x14, 0xFF, 0x29, 0x4A, 0x1E, 0x4B, +0x15, 0x60, 0x4F, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x4A, 0xE6, 0x27, 0x4A, 0x01, 0x21, 0x59, 0x70, 0x13, 0x68, 0x26, 0x49, +0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0x20, 0x1C, 0xF0, 0x1C, 0xF9, 0x13, 0xE6, 0x23, 0x48, 0x1C, 0xF0, 0xC8, 0xF8, +0x13, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x1A, 0x60, 0x80, 0xE6, 0x00, 0x22, 0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x86, 0xFF, +0xF0, 0xE6, 0x1D, 0x48, 0x1C, 0xF0, 0xBA, 0xF8, 0x0C, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x1A, 0x60, 0xC3, 0xE6, 0x00, 0x22, +0x02, 0x20, 0x1A, 0x70, 0xFD, 0xF7, 0x78, 0xFF, 0x17, 0x48, 0x90, 0xF8, 0x02, 0x1C, 0x90, 0xF8, 0x01, 0x2C, 0x91, 0x42, +0xBF, 0xF4, 0xC6, 0xAE, 0x66, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, 0xAC, 0x00, 0x24, 0x40, 0xB0, 0x00, 0x24, 0x40, +0x28, 0x00, 0x24, 0x40, 0x70, 0x79, 0x15, 0x00, 0xC0, 0x82, 0x15, 0x00, 0xEC, 0x82, 0x15, 0x00, 0x08, 0x83, 0x15, 0x00, +0x1C, 0x83, 0x15, 0x00, 0x4C, 0x00, 0x24, 0x40, 0x30, 0x83, 0x15, 0x00, 0x30, 0x00, 0x24, 0x40, 0x45, 0x00, 0x24, 0x40, +0x48, 0x83, 0x15, 0x00, 0x34, 0x00, 0x24, 0x40, 0x10, 0x00, 0x58, 0x40, 0xD0, 0x82, 0x15, 0x00, 0xCC, 0x7C, 0x15, 0x00, +0x64, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, 0xF8, 0xB5, 0x47, 0x4B, 0x1A, 0x68, 0x42, 0xF0, 0x10, 0x02, 0x1A, 0x60, +0x1B, 0x68, 0x5A, 0x07, 0x7F, 0xD4, 0x44, 0x49, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x43, 0x4B, 0x41, 0x4A, 0x0B, 0x60, +0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0x13, 0x68, 0x9E, 0x07, 0x03, 0xD4, 0x3C, 0x4A, 0x13, 0x68, 0xDD, 0x07, 0xFC, 0xD5, +0x3A, 0x4A, 0x3D, 0x4D, 0x13, 0x68, 0x3D, 0x48, 0x3D, 0x49, 0x3E, 0x4C, 0x3E, 0x4F, 0x3F, 0x4E, 0x43, 0xF0, 0x02, 0x03, +0x13, 0x60, 0x2B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, +0x2B, 0x60, 0x0B, 0x68, 0x03, 0x40, 0x43, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x0B, 0x68, 0x9B, 0xB2, 0x43, 0xF4, 0x80, 0x13, +0x0B, 0x60, 0x4F, 0xF6, 0xFF, 0x73, 0x23, 0x60, 0x52, 0xF8, 0x34, 0x3C, 0x03, 0x40, 0x43, 0xF4, 0x88, 0x53, 0x43, 0xF0, +0x11, 0x03, 0x42, 0xF8, 0x34, 0x3C, 0x03, 0x23, 0xAB, 0x64, 0x4F, 0xF4, 0xFC, 0x53, 0x3B, 0x60, 0x4F, 0xF0, 0xFF, 0x33, +0x33, 0x60, 0x2A, 0x48, 0x2A, 0x4B, 0x23, 0x62, 0x00, 0x24, 0x20, 0x23, 0x04, 0x60, 0x41, 0xF8, 0xAC, 0x3C, 0x52, 0xF8, +0x34, 0x3C, 0x27, 0x4C, 0x27, 0x48, 0x23, 0xF4, 0x7F, 0x03, 0x43, 0xF4, 0x80, 0x33, 0x42, 0xF8, 0x34, 0x3C, 0x41, 0xF8, +0x84, 0x4C, 0x1C, 0xF0, 0x1B, 0xF8, 0x17, 0x4B, 0x17, 0x49, 0x1A, 0x68, 0x94, 0x00, 0xFC, 0xD4, 0x19, 0x60, 0x1A, 0x68, +0x90, 0x00, 0xFC, 0xD4, 0x1A, 0x68, 0x12, 0xF0, 0x06, 0x0F, 0xF4, 0xD0, 0x10, 0x4A, 0x13, 0x68, 0x99, 0x00, 0xFC, 0xD4, +0x1A, 0x4B, 0x0E, 0x49, 0x13, 0x60, 0x0B, 0x68, 0x9B, 0x00, 0xFC, 0xD4, 0x18, 0x48, 0x1C, 0xF0, 0x01, 0xF8, 0x18, 0x4B, +0x18, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0xFC, 0x12, 0x91, 0x67, 0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, +0xF8, 0xBD, 0x14, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, 0xFE, 0xF7, 0x9A, 0xFB, 0xED, 0xE7, 0x00, 0xBF, 0x44, 0x00, 0x24, 0x40, +0x40, 0x00, 0x24, 0x40, 0x00, 0x02, 0x00, 0x20, 0x04, 0x00, 0x24, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x24, 0x40, +0x0C, 0x00, 0x24, 0x40, 0xB4, 0x00, 0x24, 0x40, 0x28, 0x00, 0x24, 0x40, 0x38, 0x00, 0x24, 0x40, 0x09, 0x60, 0x00, 0xCF, +0x00, 0x00, 0x20, 0x4E, 0xB8, 0x83, 0x15, 0x00, 0x06, 0x03, 0x00, 0x30, 0xCC, 0x83, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, +0x88, 0x1A, 0x17, 0x00, 0x2C, 0x00, 0x24, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x46, 0x82, 0xB0, 0xEF, 0xF3, 0x10, 0x83, +0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x23, 0x4E, 0x24, 0x4B, 0x35, 0x68, 0x1B, 0x68, +0x01, 0x35, 0x35, 0x60, 0x1C, 0x78, 0x01, 0x2C, 0x2B, 0xD0, 0x21, 0x4C, 0x23, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x23, 0x60, +0x23, 0x68, 0x9B, 0x05, 0xFC, 0xD4, 0x1E, 0x4B, 0x18, 0x68, 0xC8, 0xB1, 0x1D, 0x4B, 0x1E, 0x4C, 0xD3, 0xF8, 0x04, 0x0C, +0x47, 0x60, 0x20, 0x68, 0x01, 0x44, 0x21, 0x60, 0x17, 0x49, 0xC3, 0xF8, 0x04, 0x2C, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x73, +0x0B, 0x60, 0x35, 0xB1, 0x10, 0x4B, 0x01, 0x3D, 0x1B, 0x68, 0x35, 0x60, 0x0D, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x02, 0xB0, +0xBD, 0xE8, 0xF0, 0x81, 0x11, 0x48, 0x1F, 0x60, 0x04, 0x68, 0x0F, 0x4B, 0x21, 0x44, 0x01, 0x60, 0xE6, 0xE7, 0xDF, 0xF8, +0x3C, 0x80, 0x98, 0xF8, 0x00, 0x30, 0x00, 0x2B, 0xCD, 0xD1, 0x02, 0x20, 0xCD, 0xE9, 0x00, 0x12, 0xFD, 0xF7, 0x3C, 0xFE, +0xDD, 0xE9, 0x00, 0x12, 0x35, 0x68, 0x88, 0xF8, 0x00, 0x40, 0xC2, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0xA0, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, 0x9C, 0x00, 0x24, 0x40, +0x1D, 0x26, 0x17, 0x00, 0x30, 0xB4, 0x85, 0x68, 0x06, 0x4C, 0xC3, 0xF3, 0x0B, 0x03, 0x2C, 0x40, 0x02, 0x9D, 0x1C, 0x43, +0x44, 0xEA, 0xC5, 0x74, 0x84, 0x60, 0xC0, 0xE9, 0x00, 0x12, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, +0xF8, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0x22, 0x4D, 0x23, 0x4B, 0x29, 0x68, 0x1B, 0x68, 0x01, 0x31, 0x29, 0x60, 0x1E, 0x78, 0x01, 0x2E, 0x30, 0xD0, 0x20, 0x4A, +0x13, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x06, 0xFC, 0xD4, 0x1D, 0x4B, 0x1A, 0x68, 0xF2, 0xB1, +0x1C, 0x4B, 0x1D, 0x48, 0x41, 0xF6, 0x14, 0x02, 0x9A, 0x58, 0x54, 0x60, 0x02, 0x68, 0x01, 0x32, 0x02, 0x60, 0x41, 0xF6, +0x14, 0x02, 0x15, 0x4E, 0x9C, 0x50, 0x18, 0x48, 0x32, 0x68, 0x03, 0x78, 0x22, 0xF0, 0x40, 0x02, 0x43, 0xF0, 0x02, 0x03, +0x32, 0x60, 0x03, 0x70, 0x31, 0xB1, 0x0C, 0x4B, 0x01, 0x39, 0x1B, 0x68, 0x29, 0x60, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, +0xF8, 0xBD, 0x0E, 0x48, 0x1C, 0x60, 0x02, 0x68, 0x0B, 0x4B, 0x01, 0x32, 0x02, 0x60, 0xE2, 0xE7, 0x0C, 0x4F, 0x3B, 0x78, +0x00, 0x2B, 0xCA, 0xD1, 0x02, 0x20, 0xFD, 0xF7, 0xC9, 0xFD, 0x29, 0x68, 0x3E, 0x70, 0xC4, 0xE7, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x98, 0x00, 0x24, 0x40, 0x7C, 0x36, 0x17, 0x00, +0x94, 0x00, 0x24, 0x40, 0x9C, 0x4E, 0x17, 0x00, 0x1D, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x80, 0x46, 0x04, 0x20, +0x0F, 0x46, 0x15, 0x46, 0xFE, 0xF7, 0xF0, 0xFD, 0x68, 0xB3, 0x04, 0x46, 0xFE, 0xF7, 0x34, 0xFF, 0x06, 0x46, 0x00, 0xB3, +0xC5, 0xF3, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x09, 0x25, 0x70, 0x63, 0x70, 0x2A, 0x46, 0x84, 0xF8, 0x02, 0x80, 0x39, 0x46, +0x84, 0xF8, 0x03, 0x90, 0x20, 0x1D, 0x2E, 0xF0, 0xF9, 0xFB, 0xB2, 0x68, 0x0E, 0x4B, 0xC6, 0xF8, 0x04, 0x90, 0x04, 0x35, +0x13, 0x40, 0xC5, 0xF3, 0x0B, 0x05, 0x1D, 0x43, 0x45, 0xF0, 0x00, 0x45, 0x34, 0x60, 0xB5, 0x60, 0x30, 0x46, 0xBD, 0xE8, +0xF8, 0x43, 0xFF, 0xF7, 0x71, 0xBF, 0x07, 0x48, 0x1C, 0xF0, 0xCC, 0xFF, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFE, 0xF7, +0xE7, 0xBD, 0xBD, 0xE8, 0xF8, 0x43, 0x03, 0x48, 0x1C, 0xF0, 0xC2, 0xBF, 0x00, 0xF0, 0xFF, 0x7F, 0xEC, 0x83, 0x15, 0x00, +0xD8, 0x83, 0x15, 0x00, 0x05, 0x4B, 0x1B, 0x78, 0x33, 0xB9, 0x05, 0x4B, 0x18, 0x68, 0x6F, 0xEA, 0x10, 0x10, 0x00, 0xF0, +0x01, 0x00, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x1C, 0x26, 0x17, 0x00, 0x44, 0x00, 0x24, 0x40, 0x44, 0x4A, 0x13, 0x69, +0x43, 0xF0, 0x01, 0x03, 0x30, 0xB4, 0x13, 0x61, 0x13, 0x69, 0xD9, 0x07, 0xFC, 0xD4, 0x40, 0x4A, 0x13, 0x69, 0x00, 0x2B, +0xFC, 0xDA, 0xD3, 0x68, 0x3E, 0x48, 0x3D, 0x49, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x07, 0x03, 0xD3, 0x60, 0xD3, 0x68, +0x18, 0x43, 0xD0, 0x60, 0xD3, 0x68, 0x23, 0xF4, 0x71, 0x53, 0x23, 0xF0, 0x28, 0x03, 0xD3, 0x60, 0x13, 0x69, 0x43, 0xF0, +0x01, 0x03, 0x13, 0x61, 0x0B, 0x69, 0xDA, 0x07, 0xFC, 0xD4, 0x32, 0x4B, 0x1A, 0x69, 0x00, 0x2A, 0xFC, 0xDA, 0xDA, 0x68, +0x30, 0x48, 0x2F, 0x49, 0x42, 0xF0, 0x80, 0x42, 0x42, 0xF0, 0x07, 0x02, 0xDA, 0x60, 0xDA, 0x68, 0x10, 0x43, 0xD8, 0x60, +0xDA, 0x68, 0x22, 0xF4, 0x71, 0x52, 0x22, 0xF0, 0x28, 0x02, 0xDA, 0x60, 0xD3, 0xF8, 0x00, 0x28, 0x22, 0xF4, 0xC0, 0x52, +0x22, 0xF0, 0x03, 0x02, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x00, 0x28, 0x42, 0xF4, 0x00, 0x02, 0x42, 0xF0, 0x04, 0x02, +0xC3, 0xF8, 0x00, 0x28, 0x00, 0x24, 0x4F, 0xF0, 0xFF, 0x35, 0x01, 0x22, 0x9C, 0x61, 0x01, 0x2A, 0x5D, 0x61, 0xC3, 0xF8, +0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x48, 0xC3, 0xF8, 0x10, 0x48, 0xA2, 0xF1, 0x02, 0x03, 0x28, 0x46, 0x01, 0xEB, 0x43, 0x13, +0x0B, 0xD0, 0x05, 0x2A, 0xC3, 0xF8, 0x28, 0x0B, 0xC3, 0xF8, 0x28, 0x09, 0x0A, 0xD0, 0x01, 0x32, 0x93, 0x1E, 0x01, 0x2A, +0x01, 0xEB, 0x43, 0x13, 0xF3, 0xD1, 0xC1, 0xF8, 0x08, 0x0B, 0xC1, 0xF8, 0x08, 0x09, 0xF4, 0xE7, 0x0F, 0x48, 0x10, 0x4B, +0x0C, 0x4A, 0x88, 0x61, 0x4B, 0x63, 0x53, 0x6B, 0x1B, 0x01, 0xFC, 0xD5, 0xD2, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x02, 0x03, +0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x2E, 0x21, 0x43, 0xF4, 0x00, 0x43, 0xC2, 0xF8, 0x04, 0x38, 0x91, 0x60, +0x93, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x20, 0x40, 0x10, 0x00, 0x06, 0x40, +0x00, 0x38, 0x00, 0x80, 0x41, 0x00, 0x44, 0x02, 0x0A, 0x4B, 0x0B, 0x49, 0x1A, 0x68, 0x08, 0x68, 0x0A, 0x49, 0x0B, 0x4B, +0xC2, 0xE9, 0x00, 0x10, 0xC3, 0xF8, 0x14, 0x2B, 0xD3, 0xF8, 0x08, 0x2B, 0xC3, 0xF8, 0x08, 0x2B, 0xD3, 0xF8, 0x00, 0x2B, +0x42, 0xF0, 0x04, 0x42, 0xC3, 0xF8, 0x00, 0x2B, 0x70, 0x47, 0x00, 0xBF, 0x5C, 0x60, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, +0x40, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x20, 0x40, 0x12, 0x4A, 0x13, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x12, 0x4B, 0x30, 0xB4, +0x12, 0x4C, 0x4F, 0xF0, 0x20, 0x62, 0x00, 0x25, 0x65, 0x81, 0xC1, 0xE9, 0x00, 0x20, 0x1A, 0x69, 0x22, 0xF4, 0xFC, 0x62, +0x42, 0xF0, 0x20, 0x02, 0x1A, 0x61, 0x18, 0x69, 0x10, 0xF0, 0x20, 0x00, 0xFB, 0xD1, 0xD3, 0xF8, 0x08, 0x29, 0xC3, 0xF8, +0x08, 0x29, 0xC3, 0xF8, 0x14, 0x19, 0xD3, 0xF8, 0x00, 0x29, 0x42, 0xF0, 0x04, 0x42, 0x30, 0xBC, 0xC3, 0xF8, 0x00, 0x29, +0x70, 0x47, 0x00, 0xBF, 0x40, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, +0x70, 0xB5, 0x0B, 0x4B, 0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0x05, 0x7A, 0x00, 0x21, 0xF7, 0xF7, +0x4D, 0xFB, 0x55, 0xB1, 0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6A, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, +0x08, 0x46, 0x01, 0x22, 0x18, 0x47, 0x70, 0xBD, 0x08, 0x28, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x70, 0xB5, 0x0B, 0x4B, +0x04, 0x46, 0x01, 0x38, 0x03, 0xEB, 0x00, 0x10, 0x10, 0x22, 0xC5, 0x7A, 0x00, 0x21, 0xF7, 0xF7, 0x31, 0xFB, 0x55, 0xB1, +0x06, 0x48, 0x00, 0xEB, 0x84, 0x04, 0x23, 0x6B, 0x2B, 0xB1, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x08, 0x46, 0x01, 0x22, +0x18, 0x47, 0x70, 0xBD, 0xC8, 0x27, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x24, 0x82, 0xB0, 0xE0, 0xB2, +0x01, 0x90, 0x01, 0x34, 0xFF, 0xF7, 0xC0, 0xFF, 0x01, 0x98, 0xFF, 0xF7, 0xD9, 0xFF, 0x05, 0x2C, 0xF5, 0xD1, 0x02, 0xB0, +0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x0C, 0x46, 0x00, 0x28, 0x39, 0xD0, 0x09, 0xBB, 0x1D, 0x4B, 0x1D, 0x4A, 0x1B, 0x68, +0x51, 0x81, 0x1D, 0x4D, 0x4F, 0xF0, 0x42, 0x42, 0x1A, 0x60, 0xDA, 0x78, 0x42, 0xF0, 0x04, 0x02, 0xDA, 0x70, 0xD9, 0x78, +0x28, 0x68, 0x19, 0x4A, 0x58, 0x60, 0x01, 0xF0, 0x07, 0x01, 0x41, 0xF0, 0x08, 0x01, 0xD9, 0x70, 0xD2, 0xF8, 0x08, 0x19, +0xC2, 0xF8, 0x08, 0x19, 0xC2, 0xF8, 0x14, 0x39, 0xD2, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC2, 0xF8, 0x00, 0x39, +0x38, 0xBD, 0x0E, 0x4D, 0x01, 0x46, 0x22, 0x46, 0x28, 0x68, 0x2E, 0xF0, 0x71, 0xFA, 0x09, 0x4B, 0x09, 0x4A, 0x1B, 0x68, +0x54, 0x81, 0x4F, 0xF0, 0x40, 0x41, 0xC2, 0x22, 0x40, 0x2C, 0x19, 0x60, 0x1C, 0x80, 0xDA, 0x70, 0xD3, 0xD1, 0xD2, 0xB2, +0x6F, 0xF3, 0x82, 0x02, 0xDA, 0x70, 0xD2, 0xE7, 0x02, 0x4D, 0xEC, 0xE7, 0x40, 0x60, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, +0x58, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0xB4, 0x80, 0xB3, 0x27, 0x4D, 0x43, 0x1E, 0x05, 0xEB, 0x43, 0x16, +0x08, 0x36, 0x05, 0xEB, 0x43, 0x15, 0x2F, 0x68, 0x17, 0xF0, 0x80, 0x2F, 0x22, 0xD0, 0x23, 0x4B, 0x3B, 0x40, 0xB3, 0xF5, +0x00, 0x3F, 0x2C, 0xD0, 0x21, 0x4C, 0xD4, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x00, 0x73, 0xC4, 0xF8, 0x04, 0x38, 0x63, 0x69, +0x1B, 0x06, 0xFC, 0xD5, 0x2B, 0x68, 0x19, 0x43, 0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x29, 0x60, 0x1A, 0xB1, +0x2B, 0x68, 0x23, 0xEA, 0x02, 0x02, 0x2A, 0x60, 0x60, 0xB9, 0x16, 0x4A, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, +0xC2, 0xF8, 0x04, 0x38, 0xF0, 0xBC, 0xFF, 0xF7, 0x3D, 0xBF, 0x12, 0x4E, 0x12, 0x4D, 0xD2, 0xE7, 0x00, 0x2F, 0x0C, 0xDB, +0x3B, 0x04, 0xEE, 0xD4, 0x2B, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x2B, 0x60, 0xE9, 0xE7, 0xB1, 0xF1, 0x00, 0x6F, 0xCF, 0xD1, +0x00, 0x2A, 0xCD, 0xD1, 0xEA, 0xE7, 0x02, 0x23, 0x33, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x2B, 0x60, 0x33, 0x68, +0x9A, 0x07, 0xFC, 0xD5, 0x3B, 0x04, 0xD8, 0xD4, 0xE8, 0xE7, 0x00, 0xBF, 0x20, 0x0B, 0x20, 0x40, 0x00, 0x00, 0x02, 0x80, +0x00, 0x00, 0x20, 0x40, 0x08, 0x0B, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x70, 0xB4, 0x70, 0xB3, 0x44, 0x1E, 0x36, 0x4B, +0x66, 0x01, 0x03, 0xEB, 0x44, 0x14, 0xF5, 0x58, 0x15, 0xF0, 0x80, 0x2F, 0x4D, 0xD0, 0x08, 0x36, 0x33, 0x44, 0x32, 0x4E, +0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0x29, 0xD1, 0xB1, 0xF1, 0x00, 0x6F, 0x46, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x23, 0x68, +0x0B, 0x43, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x00, 0x2A, 0x45, 0xD1, 0x29, 0x4A, 0x83, 0x01, +0x43, 0xF0, 0x20, 0x03, 0x13, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, 0x2B, 0x04, 0x03, 0xD4, 0x23, 0x68, 0x23, 0xF4, +0x00, 0x43, 0x23, 0x60, 0x48, 0xBB, 0x70, 0xBC, 0x70, 0x47, 0x22, 0x4C, 0x25, 0x68, 0x15, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, +0x1D, 0x4E, 0x20, 0x4B, 0x2E, 0x40, 0xB6, 0xF5, 0x00, 0x3F, 0xD5, 0xD0, 0x40, 0x26, 0x1E, 0x60, 0x26, 0x68, 0x31, 0x43, +0x41, 0xF0, 0x00, 0x61, 0x41, 0xF4, 0x00, 0x41, 0x00, 0x2D, 0x21, 0x60, 0xD6, 0xDA, 0xAE, 0x03, 0x04, 0xD4, 0x19, 0x68, +0x49, 0x06, 0xFC, 0xD5, 0x40, 0x21, 0x19, 0x60, 0xDA, 0xB9, 0x02, 0x22, 0x1A, 0x60, 0x22, 0x68, 0x42, 0xF0, 0x80, 0x42, +0x22, 0x60, 0x1A, 0x68, 0x96, 0x07, 0xFC, 0xD5, 0xC6, 0xE7, 0x70, 0xBC, 0xFF, 0xF7, 0xD4, 0xBE, 0x00, 0x2A, 0xCF, 0xD0, +0x40, 0x21, 0x19, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x23, 0x60, 0x23, 0x68, 0x23, 0xEA, +0x02, 0x02, 0x22, 0x60, 0xB4, 0xE7, 0x21, 0x68, 0x21, 0xEA, 0x02, 0x02, 0x22, 0x60, 0xDE, 0xE7, 0x20, 0x09, 0x20, 0x40, +0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0x08, 0x09, 0x20, 0x40, 0x49, 0xB9, 0x0A, 0x4B, +0x0A, 0x4A, 0x01, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x10, 0x46, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x01, 0x28, +0x0C, 0xBF, 0x04, 0x48, 0x04, 0x48, 0x49, 0x01, 0x08, 0x44, 0x00, 0x68, 0xC0, 0xF3, 0x40, 0x50, 0x70, 0x47, 0x00, 0xBF, +0x00, 0x09, 0x20, 0x40, 0x00, 0x0B, 0x20, 0x40, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF0, +0x00, 0x61, 0xFF, 0xF7, 0x07, 0xBF, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, +0x5B, 0xBF, 0x70, 0x47, 0x38, 0xB9, 0x04, 0x29, 0x0D, 0xD8, 0x02, 0x46, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, +0xF5, 0xBE, 0x04, 0x29, 0x05, 0xD8, 0x08, 0x46, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x11, 0xFF, 0xF7, 0x49, 0xBF, 0x70, 0x47, +0x40, 0xB9, 0x04, 0x29, 0x0F, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0xE2, 0xBE, +0x04, 0x29, 0x06, 0xD8, 0x08, 0x46, 0x4F, 0xF4, 0x00, 0x12, 0x4F, 0xF0, 0x00, 0x61, 0xFF, 0xF7, 0x35, 0xBF, 0x70, 0x47, +0xFF, 0xF7, 0xC6, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x04, 0x46, 0x0D, 0x46, 0x57, 0x48, 0x00, 0x21, 0x1B, 0xF0, 0x04, 0xFC, +0x00, 0x2C, 0x00, 0xF0, 0x95, 0x80, 0x23, 0x68, 0x00, 0x2B, 0x7B, 0xD0, 0x63, 0x68, 0x00, 0x2B, 0x78, 0xD0, 0xA3, 0x68, +0x00, 0x2B, 0x75, 0xD0, 0x63, 0x69, 0x00, 0x2B, 0x72, 0xD0, 0x4F, 0x4E, 0x33, 0x78, 0x03, 0xF0, 0xFF, 0x07, 0x00, 0x2B, +0x6F, 0xD1, 0xDF, 0xF8, 0x68, 0x81, 0x21, 0x46, 0x40, 0x46, 0x01, 0x24, 0x48, 0x22, 0x34, 0x70, 0x2E, 0xF0, 0x06, 0xF9, +0x48, 0x4B, 0xD3, 0xF8, 0x94, 0x30, 0x00, 0x2B, 0x77, 0xD0, 0x47, 0x48, 0x1B, 0xF0, 0xDE, 0xFB, 0x46, 0x4B, 0xD3, 0xF8, +0x00, 0x28, 0x12, 0xF4, 0xFE, 0x6F, 0x5B, 0xD0, 0x44, 0x49, 0x45, 0x4A, 0xD1, 0xF8, 0x00, 0xC0, 0x44, 0x49, 0x12, 0x68, +0xDF, 0xF8, 0x30, 0x91, 0x09, 0x68, 0xC9, 0xF8, 0x04, 0x70, 0x04, 0x20, 0xC9, 0xF8, 0x08, 0x70, 0x89, 0xF8, 0x00, 0x70, +0xC2, 0xF8, 0x04, 0xC0, 0x30, 0x70, 0xC3, 0xF8, 0x14, 0x2B, 0xC8, 0x78, 0x3C, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0xD2, 0xF8, +0x00, 0xC0, 0xC8, 0x70, 0x9C, 0xF8, 0x03, 0x00, 0x39, 0x4A, 0x40, 0xF0, 0xC0, 0x00, 0x17, 0x68, 0x8C, 0xF8, 0x03, 0x00, +0xF8, 0x78, 0xD2, 0xF8, 0x04, 0xE0, 0x40, 0xF0, 0xC0, 0x00, 0xF8, 0x70, 0x9E, 0xF8, 0x03, 0x00, 0xD2, 0xE9, 0x02, 0xC7, +0x40, 0xF0, 0xC0, 0x02, 0x8E, 0xF8, 0x03, 0x20, 0x9C, 0xF8, 0x03, 0x20, 0x42, 0xF0, 0xC0, 0x02, 0x8C, 0xF8, 0x03, 0x20, +0xFA, 0x78, 0x42, 0xF0, 0xC0, 0x02, 0xFA, 0x70, 0xC3, 0xF8, 0x14, 0x19, 0xFF, 0xF7, 0x86, 0xFD, 0xD8, 0xF8, 0x44, 0x30, +0x89, 0xF8, 0x00, 0x40, 0x03, 0xB1, 0x98, 0x47, 0x26, 0x4B, 0x27, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x04, 0x11, 0xD1, 0x67, +0xA3, 0xF5, 0x40, 0x63, 0x4F, 0xF4, 0x00, 0x42, 0x01, 0x2D, 0x1A, 0x60, 0x23, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, +0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x03, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x9A, 0x68, 0xD2, 0x07, 0x14, 0xD5, 0x9A, 0x68, +0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0xFF, 0xF7, +0xC9, 0xFC, 0xD9, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x14, 0x48, 0xFD, 0xF7, 0x9C, 0xF9, 0x04, 0x20, 0xE2, 0xE7, +0xFF, 0xF7, 0xBE, 0xFC, 0xCE, 0xE7, 0x11, 0x4B, 0x11, 0x48, 0x1B, 0x69, 0x1B, 0xF0, 0x5C, 0xFB, 0x33, 0x78, 0x04, 0x2B, +0xFC, 0xD1, 0xD2, 0xE7, 0xFC, 0x83, 0x15, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x10, 0x40, 0x08, 0x84, 0x15, 0x00, +0x00, 0x00, 0x20, 0x40, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, +0x44, 0x60, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x84, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, +0x34, 0x84, 0x15, 0x00, 0x20, 0x26, 0x17, 0x00, 0xB4, 0x27, 0x17, 0x00, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0xC3, 0xF8, +0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0x11, 0x4A, 0x11, 0x4B, 0x12, 0x48, 0x00, 0x21, 0x11, 0x70, +0x9A, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x9A, 0x60, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, +0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF0, 0x02, 0x02, 0xC3, 0xF8, 0x04, 0x28, +0x1A, 0x69, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x61, 0x48, 0x22, 0xF7, 0xF7, 0x9F, 0xB8, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, +0x6F, 0x26, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4E, 0x1E, 0xF7, 0xB2, +0x03, 0x2F, 0x41, 0xD8, 0x14, 0x46, 0x0D, 0x46, 0x9B, 0x46, 0x02, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x04, 0xF0, 0xFD, 0x01, +0x01, 0x29, 0x5B, 0xD0, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, 0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0x4F, 0xEA, +0x45, 0x18, 0x08, 0xF1, 0x80, 0x48, 0x08, 0xF5, 0x00, 0x18, 0xD8, 0xF8, 0x00, 0x19, 0x11, 0xF0, 0x80, 0x2F, 0x68, 0xD1, +0xA2, 0x04, 0x02, 0xF4, 0x40, 0x22, 0xCB, 0xF3, 0x0A, 0x03, 0x3B, 0x4C, 0x13, 0x43, 0x43, 0xEA, 0x85, 0x53, 0x21, 0x88, +0x43, 0xF0, 0xC0, 0x53, 0x43, 0xF4, 0x00, 0x43, 0xC8, 0xF8, 0x00, 0x39, 0x01, 0xEB, 0x0A, 0x03, 0xB3, 0xF5, 0xC0, 0x6F, +0x5E, 0xDC, 0x34, 0x4A, 0x40, 0x36, 0x02, 0xEB, 0x86, 0x06, 0x41, 0xEA, 0x09, 0x03, 0x73, 0x60, 0xD2, 0xF8, 0x1C, 0x38, +0x0F, 0x44, 0x01, 0x21, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, 0x27, 0x80, 0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, +0x4E, 0x01, 0x06, 0xF1, 0x80, 0x46, 0x06, 0xF5, 0x00, 0x16, 0xD6, 0xF8, 0x00, 0x2B, 0x12, 0xF0, 0x80, 0x2F, 0x33, 0xD1, +0xA4, 0x04, 0x04, 0xF4, 0x40, 0x24, 0xCB, 0xF3, 0x0A, 0x03, 0x23, 0x43, 0x43, 0xF0, 0xC0, 0x53, 0x21, 0x4A, 0x43, 0xF4, +0x00, 0x43, 0xC6, 0xF8, 0x00, 0x3B, 0xD2, 0xF8, 0x1C, 0x38, 0x4F, 0xF4, 0x80, 0x31, 0x01, 0xFA, 0x05, 0xF5, 0x1D, 0x43, +0xC2, 0xF8, 0x1C, 0x58, 0xBD, 0xE8, 0xF8, 0x8F, 0xB3, 0xF5, 0x48, 0x7F, 0x20, 0xD8, 0xDF, 0x1C, 0xBF, 0x10, 0x7F, 0x00, +0xBF, 0xB2, 0xBA, 0x46, 0x4F, 0xEA, 0x07, 0x49, 0xBB, 0xF5, 0x80, 0x6F, 0x9D, 0xD9, 0x6F, 0xF4, 0x80, 0x63, 0x0B, 0xEB, +0x03, 0x01, 0xB1, 0xF5, 0x80, 0x6F, 0x25, 0xBF, 0x10, 0x4B, 0xA3, 0xFB, 0x0B, 0x13, 0x4F, 0xEA, 0x5B, 0x0B, 0xC3, 0xF3, +0x4F, 0x0B, 0x8E, 0xE7, 0xFF, 0xF7, 0x34, 0xFE, 0xC8, 0xE7, 0x10, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0x2F, 0xFE, 0x91, 0xE7, +0x4F, 0xF4, 0xC8, 0x7A, 0x57, 0x46, 0x4F, 0xF0, 0xC8, 0x79, 0xDF, 0xE7, 0x06, 0x48, 0x52, 0x46, 0x4F, 0xF4, 0xC0, 0x63, +0xFD, 0xF7, 0x9E, 0xF8, 0x21, 0x88, 0x98, 0xE7, 0x48, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0xAB, 0xAA, 0xAA, 0xAA, +0x40, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x27, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3C, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, +0x04, 0x2B, 0x39, 0xD8, 0x8D, 0x07, 0x3D, 0xD1, 0x22, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, +0x0E, 0x50, 0x8D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, +0x2A, 0xD5, 0x1B, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x19, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, +0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, +0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, +0xD3, 0xF8, 0x00, 0x2B, 0x42, 0xF0, 0x04, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, +0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFD, 0xF7, 0x47, 0xF8, 0x03, 0x20, +0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0xFF, 0xFF, 0x07, 0x00, +0x80, 0x84, 0x15, 0x00, 0xF8, 0xB5, 0x28, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x3E, 0xD1, 0x44, 0x1E, 0xDF, 0xB2, 0xE3, 0xB2, +0x04, 0x2B, 0x3B, 0xD8, 0x8D, 0x07, 0x3F, 0xD1, 0x23, 0x4E, 0x4F, 0xEA, 0x04, 0x1E, 0x06, 0xEB, 0x04, 0x1C, 0x56, 0xF8, +0x0E, 0x50, 0x9D, 0xBB, 0x43, 0x01, 0x03, 0xF1, 0x80, 0x43, 0x03, 0xF5, 0x00, 0x13, 0xD3, 0xF8, 0x00, 0x0B, 0x00, 0x04, +0x2C, 0xD5, 0x1C, 0x48, 0x46, 0xF8, 0x0E, 0x10, 0x50, 0xF8, 0x24, 0x00, 0x1A, 0x4F, 0x01, 0x26, 0x8C, 0xF8, 0x08, 0x60, +0xC6, 0x78, 0x64, 0x01, 0x04, 0xF1, 0x80, 0x44, 0xBA, 0x42, 0x04, 0xF5, 0x00, 0x14, 0x06, 0xF0, 0x31, 0x06, 0x28, 0xBF, +0x3A, 0x46, 0x46, 0xF0, 0x0E, 0x06, 0xCC, 0xF8, 0x04, 0x20, 0x02, 0x80, 0x41, 0x60, 0xC6, 0x70, 0xC4, 0xF8, 0x34, 0x0B, +0xD3, 0xF8, 0x00, 0x2B, 0x22, 0xF0, 0x04, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x28, 0x46, 0xC3, 0xF8, 0x00, 0x2B, 0xF8, 0xBD, +0x01, 0x20, 0xF8, 0xBD, 0x02, 0x20, 0xF8, 0xBD, 0x38, 0x46, 0xF8, 0xBD, 0x05, 0x20, 0xF8, 0xBD, 0x06, 0x48, 0xFC, 0xF7, +0xEB, 0xFF, 0x03, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x6F, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, +0xFF, 0xFF, 0x07, 0x00, 0x80, 0x84, 0x15, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x0C, 0x4B, 0xE0, 0x89, 0x18, 0x80, 0x20, 0xB9, +0x0B, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x0A, 0x4B, 0x5B, 0x69, 0x4B, 0xB1, 0xC0, 0xB2, 0x98, 0x47, +0x30, 0xB1, 0x06, 0x4A, 0x04, 0x21, 0x07, 0x23, 0x11, 0x70, 0x23, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, +0xB4, 0x27, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x20, 0x26, 0x17, 0x00, 0xF8, 0xB5, 0x0C, 0x46, +0x00, 0x28, 0x70, 0xD1, 0x01, 0xF0, 0x21, 0x03, 0x21, 0x2B, 0x7F, 0xD0, 0xE1, 0x07, 0x76, 0xD5, 0x14, 0xF0, 0x08, 0x01, +0x00, 0xF0, 0x8B, 0x80, 0xB5, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x76, 0x82, 0x63, 0x06, 0x40, 0xF1, 0x15, 0x81, +0xB2, 0x4B, 0xD3, 0xF8, 0x14, 0x3B, 0x08, 0x3B, 0x00, 0x22, 0xC5, 0xE9, 0x01, 0x22, 0x02, 0x20, 0x28, 0x70, 0x1A, 0x78, +0x29, 0x7B, 0xD2, 0x09, 0x62, 0xF3, 0xC7, 0x11, 0x29, 0x73, 0x19, 0x78, 0x2A, 0x7B, 0x49, 0x11, 0x61, 0xF3, 0x46, 0x12, +0x2A, 0x73, 0x19, 0x78, 0x61, 0xF3, 0x04, 0x02, 0x2A, 0x73, 0x5A, 0x78, 0x6A, 0x73, 0xD9, 0x78, 0x9A, 0x78, 0x42, 0xEA, +0x01, 0x22, 0xEA, 0x81, 0x59, 0x79, 0x1A, 0x79, 0x42, 0xEA, 0x01, 0x22, 0x2A, 0x82, 0xDA, 0x79, 0x9B, 0x79, 0x43, 0xEA, +0x02, 0x23, 0x6B, 0x82, 0x23, 0xB9, 0x95, 0xF9, 0x0C, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x73, 0x82, 0x9A, 0x4B, 0x9B, 0x4C, +0xD3, 0xF8, 0x14, 0x28, 0xE1, 0x68, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, +0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x21, 0xB1, 0x91, 0x48, 0x88, 0x47, 0x00, 0x28, 0x40, 0xF0, 0xB5, 0x80, 0x92, 0x4F, +0x2B, 0x7B, 0x3A, 0x78, 0x13, 0xF0, 0x60, 0x0F, 0xD6, 0xB2, 0x40, 0xF0, 0xCF, 0x80, 0x68, 0x7B, 0x0B, 0x28, 0x00, 0xF2, +0xDA, 0x80, 0xDF, 0xE8, 0x10, 0xF0, 0xDE, 0x00, 0x27, 0x01, 0xD8, 0x00, 0xFA, 0x00, 0xD8, 0x00, 0x8C, 0x00, 0x5D, 0x01, +0xD8, 0x00, 0x4F, 0x01, 0x44, 0x01, 0x98, 0x01, 0x85, 0x01, 0x82, 0x4D, 0x2B, 0x78, 0x02, 0x2B, 0x53, 0xD0, 0xCA, 0x07, +0x55, 0xD4, 0xA1, 0x06, 0x02, 0xD5, 0x2B, 0x78, 0x06, 0x2B, 0x3D, 0xD0, 0xF8, 0xBD, 0x7C, 0x4D, 0x22, 0x07, 0x2B, 0x78, +0x35, 0xD5, 0x01, 0x2B, 0x8B, 0xD0, 0xF8, 0xBD, 0x79, 0x4A, 0xD2, 0xF8, 0x10, 0x3B, 0x03, 0xF0, 0x7F, 0x03, 0x40, 0x2B, +0x7F, 0xF4, 0x78, 0xAF, 0xD2, 0xF8, 0x10, 0x3B, 0x18, 0x03, 0x7F, 0xF5, 0x73, 0xAF, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, +0xDB, 0xBA, 0x74, 0x4B, 0x6F, 0x4D, 0x1E, 0x68, 0xF3, 0x78, 0x13, 0xF0, 0x01, 0x03, 0x40, 0xF0, 0xE2, 0x81, 0x2A, 0x78, +0x02, 0x2A, 0x3F, 0xF4, 0x6E, 0xAF, 0x03, 0x2A, 0x00, 0xF0, 0xE6, 0x81, 0x05, 0x2A, 0x0D, 0xD1, 0x68, 0x4A, 0x2B, 0x70, +0xD2, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xD2, 0xF8, 0x10, 0x38, 0x23, 0xF0, 0x10, 0x03, +0xC2, 0xF8, 0x10, 0x38, 0xFF, 0xF7, 0xBA, 0xFA, 0xBF, 0xE7, 0x02, 0x2B, 0xBD, 0xD1, 0x54, 0xE7, 0xFF, 0xF7, 0xB4, 0xFA, +0x5D, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xBD, 0xE8, +0xF8, 0x40, 0xFF, 0xF7, 0xC5, 0xBA, 0x5B, 0x48, 0xFC, 0xF7, 0xEC, 0xFE, 0x41, 0xE7, 0x04, 0x2B, 0x00, 0xF0, 0xDD, 0x81, +0x07, 0x2B, 0xA4, 0xD1, 0x52, 0x4B, 0x57, 0x49, 0x00, 0x20, 0x28, 0x70, 0xD3, 0xF8, 0x14, 0x28, 0x22, 0xF0, 0x10, 0x02, +0xC3, 0xF8, 0x14, 0x28, 0xD3, 0xF8, 0x10, 0x28, 0x22, 0xF0, 0x10, 0x02, 0xC3, 0xF8, 0x10, 0x28, 0x0A, 0x78, 0x00, 0x2A, +0x96, 0xD0, 0xD3, 0xF8, 0x04, 0x48, 0x12, 0x01, 0x02, 0xF0, 0x70, 0x02, 0x24, 0xF0, 0x70, 0x04, 0x22, 0x43, 0xC3, 0xF8, +0x04, 0x28, 0x08, 0x70, 0xF8, 0xBD, 0x43, 0x48, 0xE9, 0x89, 0xD0, 0xF8, 0x00, 0x28, 0x0B, 0x01, 0x22, 0xF4, 0xFE, 0x62, +0x03, 0xF4, 0xFE, 0x63, 0x13, 0x43, 0x07, 0x22, 0xC0, 0xF8, 0x00, 0x38, 0x2A, 0x70, 0x00, 0x29, 0x40, 0xF0, 0xF2, 0x81, +0x02, 0x23, 0x3B, 0x70, 0x04, 0x2E, 0x40, 0xF0, 0x9F, 0x80, 0x3B, 0x78, 0x04, 0x2B, 0x01, 0xD0, 0xFF, 0xF7, 0xE8, 0xFA, +0x2B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x04, 0x2B, 0x00, 0xF0, 0xAB, 0x80, 0x07, 0x2B, 0x00, 0xF0, 0x91, 0x80, 0x00, 0x24, +0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x2C, 0x70, 0xFF, 0xF7, 0x2F, 0xFB, 0x22, 0x46, 0x20, 0x46, 0x4F, 0xF4, +0x00, 0x11, 0xFF, 0xF7, 0x85, 0xFB, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x49, 0xBA, 0x2B, 0x4B, 0x1B, 0x68, 0x5B, 0x68, +0xEA, 0xE6, 0x2C, 0x48, 0xFC, 0xF7, 0x8A, 0xFE, 0x04, 0x2E, 0xE4, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xE1, 0xD0, 0xFF, 0xF7, +0xBF, 0xFA, 0xDE, 0xE7, 0x6B, 0x68, 0x00, 0x2B, 0x7F, 0xF4, 0x57, 0xAF, 0x25, 0x4B, 0x6B, 0x60, 0x53, 0xE7, 0x04, 0x2E, +0xD5, 0xD1, 0x3B, 0x78, 0x04, 0x2B, 0xF0, 0xD1, 0xD1, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0xCB, 0x81, 0x2B, 0x8A, +0x00, 0x2B, 0xE3, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x01, 0x2B, 0x00, 0xF0, 0xCF, 0x81, 0x02, 0x2B, 0x00, 0xF0, +0xC1, 0x80, 0x00, 0x2B, 0xE7, 0xD1, 0x19, 0x4A, 0x19, 0x4B, 0x12, 0x78, 0x1A, 0x80, 0x02, 0x21, 0x04, 0x22, 0x6B, 0x60, +0x29, 0x81, 0x2A, 0x70, 0x5A, 0xE0, 0x3B, 0x78, 0x04, 0x2B, 0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0xC8, 0xD1, 0x2B, 0x7B, +0x13, 0xF0, 0x1F, 0x03, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2B, 0x03, 0xD1, 0xEB, 0x89, 0x00, 0x2B, 0x00, 0xF0, 0xBF, 0x81, +0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0xA0, 0xD1, 0xC9, 0xE7, 0x00, 0xBF, 0xB4, 0x27, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, +0x20, 0x26, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x98, 0x84, 0x15, 0x00, 0x70, 0x26, 0x17, 0x00, +0xD8, 0x84, 0x15, 0x00, 0x74, 0x26, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x3B, 0x78, 0x04, 0x2B, +0x02, 0xD0, 0x2B, 0x8A, 0x00, 0x2B, 0x9B, 0xD1, 0x2B, 0x7B, 0x03, 0xF0, 0x1F, 0x03, 0x02, 0x2B, 0xD8, 0xD1, 0xEB, 0x89, +0x00, 0x2B, 0xD5, 0xD1, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0xBF, 0xFB, 0x07, 0x23, +0x04, 0x2E, 0x2B, 0x70, 0x00, 0xF0, 0x95, 0x81, 0xFF, 0xF7, 0xE6, 0xF9, 0xE7, 0xE6, 0xA9, 0x4B, 0xD3, 0xF8, 0xE0, 0x34, +0x98, 0x47, 0x04, 0x46, 0x04, 0x2E, 0x5A, 0xD0, 0x00, 0x2C, 0x7F, 0xF4, 0x59, 0xAF, 0x60, 0xE7, 0xA4, 0x4B, 0x6B, 0x60, +0x02, 0x22, 0x04, 0x23, 0x2A, 0x81, 0x2B, 0x70, 0x04, 0x2E, 0x3F, 0xF4, 0x4A, 0xAF, 0x29, 0x89, 0x68, 0x68, 0xFF, 0xF7, +0x43, 0xFA, 0xCE, 0xE6, 0xE8, 0x89, 0x03, 0x0A, 0x01, 0x3B, 0x01, 0x0A, 0x0E, 0x2B, 0x3F, 0xF6, 0x62, 0xAF, 0x01, 0xA2, +0x52, 0xF8, 0x23, 0xF0, 0xC1, 0x97, 0x12, 0x00, 0x05, 0x98, 0x12, 0x00, 0xF1, 0x97, 0x12, 0x00, 0xFF, 0x95, 0x12, 0x00, +0xFF, 0x95, 0x12, 0x00, 0x65, 0x98, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, +0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, 0xDB, 0x95, 0x12, 0x00, +0x45, 0x98, 0x12, 0x00, 0xA3, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x40, 0xAF, 0xE9, 0x89, 0x28, 0x8A, 0x98, 0x47, 0x00, 0x28, +0x3F, 0xF4, 0x3A, 0xAF, 0x85, 0x4A, 0x86, 0x4B, 0x29, 0x8A, 0x11, 0x80, 0xEA, 0x89, 0x1A, 0x70, 0x07, 0x23, 0x2B, 0x70, +0x06, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xDA, 0xB2, 0x7F, 0xF4, 0x2C, 0xAF, 0x7E, 0x4B, 0x7F, 0x49, 0x18, 0x88, 0x2A, 0x70, +0x01, 0x23, 0x28, 0x82, 0x69, 0x60, 0x2B, 0x81, 0xAE, 0xE7, 0x3B, 0x78, 0x04, 0x2B, 0xA1, 0xD0, 0xFF, 0xF7, 0xE4, 0xF9, +0x00, 0x2C, 0x7F, 0xF4, 0xF9, 0xAE, 0x00, 0xE7, 0x01, 0x46, 0xFF, 0xF7, 0x0B, 0xFB, 0x00, 0x28, 0x00, 0xF0, 0x05, 0x81, +0x74, 0x4B, 0x01, 0x22, 0x1A, 0x80, 0x3A, 0xE7, 0x23, 0x68, 0x01, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0x0A, 0xAF, +0x03, 0x78, 0x12, 0x2B, 0x7F, 0xF4, 0x06, 0xAF, 0x42, 0x78, 0x01, 0x2A, 0x7F, 0xF4, 0x02, 0xAF, 0x2B, 0x81, 0x68, 0x60, +0x6B, 0x8A, 0x2A, 0x89, 0x9A, 0x42, 0x88, 0xBF, 0x2B, 0x81, 0x04, 0x23, 0x2B, 0x70, 0x83, 0xE7, 0xA3, 0x68, 0xC0, 0xB2, +0x98, 0x47, 0x68, 0x60, 0x00, 0x28, 0x3F, 0xF4, 0xF1, 0xAE, 0x03, 0x78, 0x2B, 0x81, 0xED, 0xE7, 0x63, 0x68, 0x00, 0x20, +0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xE8, 0xAE, 0x03, 0x78, 0x09, 0x2B, 0x7F, 0xF4, 0xE4, 0xAE, 0x43, 0x78, 0x02, 0x2B, +0x7F, 0xF4, 0xE0, 0xAE, 0xC2, 0x78, 0x83, 0x78, 0x68, 0x60, 0x43, 0xEA, 0x02, 0x23, 0x2B, 0x81, 0xC3, 0x79, 0x58, 0x4A, +0x13, 0xF0, 0x40, 0x0F, 0x13, 0x78, 0x14, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x70, 0xCD, 0xE7, +0x23, 0x68, 0x0F, 0x20, 0x98, 0x47, 0x00, 0x28, 0x3F, 0xF4, 0xC8, 0xAE, 0x03, 0x78, 0x05, 0x2B, 0x7F, 0xF4, 0xC4, 0xAE, +0x43, 0x78, 0x0F, 0x2B, 0x7F, 0xF4, 0xC0, 0xAE, 0x83, 0x78, 0xBB, 0xE7, 0x23, 0x68, 0x06, 0x20, 0x98, 0x47, 0x00, 0x28, +0x3F, 0xF4, 0xB8, 0xAE, 0x03, 0x78, 0x0A, 0x2B, 0x7F, 0xF4, 0xB4, 0xAE, 0x42, 0x78, 0x06, 0x2A, 0x7F, 0xF4, 0xB0, 0xAE, +0xAC, 0xE7, 0x2B, 0x78, 0x00, 0x2B, 0x51, 0xD1, 0x01, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x00, 0x21, 0x01, 0x20, 0xFF, 0xF7, +0xB3, 0xFA, 0x84, 0xE5, 0x68, 0x89, 0x2B, 0x89, 0x36, 0x88, 0x6A, 0x68, 0x3C, 0x49, 0x1B, 0x1A, 0xC6, 0xF1, 0x40, 0x06, +0x9B, 0xB2, 0x9E, 0x42, 0xA8, 0xBF, 0x1E, 0x46, 0x10, 0x44, 0x09, 0x68, 0xB2, 0xB2, 0x2D, 0xF0, 0x07, 0xFC, 0x6A, 0x89, +0x2B, 0x89, 0x16, 0x44, 0xB6, 0xB2, 0xB3, 0x42, 0x6E, 0x81, 0x7F, 0xF4, 0x11, 0xAE, 0x33, 0x4B, 0x1B, 0x69, 0x0B, 0xB1, +0x28, 0x46, 0x98, 0x47, 0xA0, 0x06, 0x35, 0xD4, 0x06, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x29, 0x89, 0x6A, 0x89, 0x88, 0x1A, +0x80, 0xB2, 0x30, 0xB9, 0x05, 0x23, 0x2B, 0x70, 0xF8, 0xBD, 0x2B, 0x48, 0xFC, 0xF7, 0x00, 0xFD, 0x88, 0xE5, 0x40, 0x28, +0x22, 0xD0, 0x40, 0x28, 0x28, 0xBF, 0x40, 0x20, 0x00, 0x26, 0x02, 0x44, 0x92, 0xB2, 0x91, 0x42, 0x6A, 0x81, 0x29, 0xD3, +0x89, 0x1A, 0x89, 0xB2, 0x40, 0x29, 0x0F, 0xD8, 0x79, 0xB9, 0x66, 0xBB, 0x21, 0x4A, 0x05, 0x23, 0x2B, 0x70, 0xD2, 0xF8, +0x10, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x10, 0x38, 0xF8, 0xBD, 0x01, 0x20, 0xFF, 0xF7, 0x65, 0xFA, 0xA9, 0xE7, +0x40, 0x21, 0x68, 0x68, 0x10, 0x44, 0xFF, 0xF7, 0x27, 0xF9, 0x98, 0xE5, 0x01, 0x26, 0xDE, 0xE7, 0xFF, 0xF7, 0x8E, 0xF8, +0x15, 0x4A, 0x07, 0x23, 0x2B, 0x70, 0xD2, 0xF8, 0x14, 0x38, 0x43, 0xF0, 0x10, 0x03, 0xC2, 0xF8, 0x14, 0x38, 0xFF, 0xF7, +0xA1, 0xF8, 0x8A, 0xE5, 0x10, 0x48, 0xFC, 0xF7, 0xC7, 0xFC, 0x29, 0x89, 0x6A, 0x89, 0xCF, 0xE7, 0x03, 0x23, 0x3B, 0x70, +0x0C, 0xE6, 0x08, 0x46, 0xFF, 0xF7, 0x0A, 0xF9, 0x7B, 0xE5, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x26, 0x17, 0x00, +0x6A, 0x26, 0x17, 0x00, 0x68, 0x26, 0x17, 0x00, 0x50, 0x28, 0x17, 0x00, 0x6E, 0x26, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, +0x20, 0x26, 0x17, 0x00, 0xB4, 0x84, 0x15, 0x00, 0x00, 0x00, 0x20, 0x40, 0xF0, 0x84, 0x15, 0x00, 0x2B, 0x7B, 0x03, 0xF0, +0x1F, 0x03, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x7F, 0xF4, 0x39, 0xAE, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, 0x04, 0x29, +0x2A, 0xD9, 0x17, 0x4B, 0x00, 0x22, 0x1A, 0x80, 0x35, 0xE6, 0xE8, 0x89, 0x02, 0x28, 0x19, 0xD0, 0x00, 0xF1, 0xFF, 0x3C, +0x07, 0x23, 0xDC, 0xF1, 0x00, 0x04, 0x44, 0xEB, 0x0C, 0x04, 0x2B, 0x70, 0x7E, 0xE6, 0x28, 0x8A, 0x00, 0xF0, 0x0F, 0x01, +0xC0, 0xF3, 0xC0, 0x10, 0xFF, 0xF7, 0x18, 0xFA, 0x07, 0x23, 0x04, 0x2E, 0x2B, 0x70, 0x7F, 0xF4, 0x6B, 0xAE, 0x3B, 0x78, +0x04, 0x2B, 0x3F, 0xF4, 0x67, 0xAE, 0xC9, 0xE5, 0x2B, 0x8A, 0x07, 0x49, 0x1B, 0x0A, 0x07, 0x22, 0x04, 0x2E, 0x0B, 0x70, +0x2A, 0x70, 0x7F, 0xF4, 0x5D, 0xAE, 0xF0, 0xE7, 0xC0, 0xF3, 0xC0, 0x10, 0xC7, 0xE6, 0x00, 0xBF, 0x50, 0x28, 0x17, 0x00, +0x70, 0x26, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xB4, 0x4B, 0xB5, 0x4D, 0xD3, 0xF8, 0x00, 0x38, 0x13, 0xF4, 0xFE, 0x6F, +0x03, 0xD0, 0x2B, 0x78, 0x04, 0x2B, 0x00, 0xF0, 0x8F, 0x81, 0xAF, 0x4C, 0xB0, 0x4A, 0xB1, 0x48, 0x00, 0x21, 0x02, 0x23, +0x2B, 0x70, 0x11, 0x70, 0x1A, 0xF0, 0x1A, 0xFE, 0xD4, 0xF8, 0x00, 0x3E, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x00, 0x3E, +0xD4, 0xF8, 0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC4, 0xF8, 0x04, 0x38, 0xFF, 0xF7, 0x7E, 0xF8, 0xA3, 0x69, 0x1D, 0x06, +0x03, 0xD5, 0xA3, 0x69, 0x23, 0xF0, 0x80, 0x03, 0xA3, 0x61, 0xA0, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x00, 0x72, +0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x14, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x9E, 0x4C, 0x9E, 0x4D, 0x9F, 0x4A, +0x9F, 0x4F, 0x4F, 0xF0, 0x02, 0x0C, 0x1C, 0xD0, 0x4F, 0xEA, 0x43, 0x1E, 0x5E, 0xF8, 0x02, 0x10, 0x11, 0xF0, 0x80, 0x2F, +0x10, 0xD0, 0x5E, 0xF8, 0x02, 0x00, 0x00, 0x29, 0x40, 0xEA, 0x05, 0x00, 0x4E, 0xF8, 0x02, 0x00, 0xC0, 0xF2, 0x0F, 0x81, +0x08, 0x04, 0x05, 0xD4, 0x5E, 0xF8, 0x02, 0x10, 0x21, 0xF4, 0x00, 0x41, 0x4E, 0xF8, 0x02, 0x10, 0x05, 0x2B, 0x0A, 0xD0, +0x01, 0x33, 0x01, 0x2B, 0xE2, 0xD1, 0x21, 0x68, 0x11, 0xF0, 0x80, 0x2F, 0xF8, 0xD0, 0x21, 0x68, 0x29, 0x43, 0x21, 0x60, +0xF4, 0xE7, 0x84, 0x4B, 0xD3, 0xF8, 0x04, 0x28, 0x42, 0xF4, 0x80, 0x62, 0xC3, 0xF8, 0x04, 0x28, 0xD3, 0xF8, 0x04, 0x28, +0x42, 0xF0, 0x80, 0x02, 0xC3, 0xF8, 0x04, 0x28, 0x5A, 0x69, 0x51, 0x06, 0xFC, 0xD5, 0x01, 0x23, 0x01, 0x2B, 0x83, 0x4F, +0xDF, 0xF8, 0x40, 0x82, 0xDF, 0xF8, 0xF8, 0xC1, 0x81, 0x4D, 0xDF, 0xF8, 0x3C, 0xE2, 0x4F, 0xF0, 0x40, 0x06, 0x4F, 0xF0, +0x02, 0x09, 0x19, 0xD0, 0x5A, 0x01, 0x05, 0xEB, 0x43, 0x10, 0x51, 0x59, 0x11, 0xF0, 0x80, 0x2F, 0x0D, 0xD0, 0x72, 0x44, +0x16, 0x60, 0x04, 0x68, 0x00, 0x29, 0x44, 0xEA, 0x0C, 0x04, 0x04, 0x60, 0x11, 0xDB, 0x0A, 0x04, 0x03, 0xD4, 0x02, 0x68, +0x22, 0xF4, 0x00, 0x42, 0x02, 0x60, 0x05, 0x2B, 0x1A, 0xD0, 0x01, 0x33, 0x01, 0x2B, 0xE5, 0xD1, 0x39, 0x68, 0x11, 0xF0, +0x80, 0x2F, 0xF8, 0xD0, 0x42, 0x46, 0x38, 0x46, 0xE6, 0xE7, 0x8C, 0x03, 0x09, 0xD5, 0xC2, 0xF8, 0x00, 0x90, 0x04, 0x68, +0x44, 0xF0, 0x80, 0x44, 0x04, 0x60, 0x14, 0x68, 0xA4, 0x07, 0xFC, 0xD5, 0xE1, 0xE7, 0x14, 0x68, 0x64, 0x06, 0xFC, 0xD5, +0x16, 0x60, 0xF0, 0xE7, 0x5B, 0x4B, 0x4F, 0xF4, 0x86, 0x62, 0x1A, 0x61, 0x1A, 0x69, 0x12, 0xF0, 0x30, 0x0F, 0xFB, 0xD1, +0xD3, 0xF8, 0x04, 0x28, 0x4F, 0xF0, 0x01, 0x14, 0x42, 0xF4, 0x80, 0x72, 0x29, 0x20, 0x09, 0x21, 0xC3, 0xF8, 0x04, 0x28, +0xC3, 0xF8, 0x1C, 0x48, 0xC3, 0xF8, 0x14, 0x08, 0xC3, 0xF8, 0x10, 0x18, 0x9A, 0x69, 0x42, 0xF4, 0x40, 0x22, 0x9A, 0x61, +0x9A, 0x6C, 0x14, 0x03, 0x4C, 0xD4, 0x4C, 0x4D, 0x55, 0x4B, 0xD5, 0xF8, 0x00, 0x28, 0x55, 0x48, 0x00, 0x24, 0x22, 0xF4, +0xFE, 0x62, 0xC5, 0xF8, 0x00, 0x28, 0x21, 0x46, 0xC3, 0xE9, 0x01, 0x44, 0x40, 0x22, 0x1C, 0x70, 0xF6, 0xF7, 0xDE, 0xFA, +0x21, 0x46, 0x40, 0x22, 0x4E, 0x48, 0xF6, 0xF7, 0xD9, 0xFA, 0x4E, 0x4A, 0x4E, 0x4B, 0x11, 0x68, 0x4E, 0x4A, 0x1B, 0x68, +0x12, 0x68, 0x59, 0x60, 0xC5, 0xF8, 0x14, 0x3B, 0xD1, 0x78, 0x4C, 0x4B, 0x4C, 0x48, 0x1F, 0x68, 0x4C, 0x4B, 0x06, 0x6A, +0x18, 0x68, 0xD3, 0xF8, 0x04, 0xC0, 0x41, 0xF0, 0xC0, 0x01, 0xD1, 0x70, 0xF9, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xF9, 0x70, +0xC1, 0x78, 0x41, 0xF0, 0xC0, 0x01, 0xC1, 0x70, 0x9C, 0xF8, 0x03, 0x10, 0xD3, 0xE9, 0x02, 0x70, 0x41, 0xF0, 0xC0, 0x03, +0x8C, 0xF8, 0x03, 0x30, 0xFB, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xFB, 0x70, 0xC3, 0x78, 0x43, 0xF0, 0xC0, 0x03, 0xC3, 0x70, +0xC5, 0xF8, 0x14, 0x29, 0x0E, 0xB1, 0x20, 0x46, 0xB0, 0x47, 0xBD, 0xE8, 0xF8, 0x43, 0x3A, 0x48, 0x1A, 0xF0, 0x10, 0xBD, +0x39, 0x49, 0x3A, 0x4C, 0x24, 0x4A, 0x40, 0xF2, 0x17, 0x15, 0x5D, 0x62, 0x4F, 0xF4, 0x9C, 0x70, 0x9C, 0x62, 0x08, 0x80, +0xD3, 0xF8, 0x04, 0x18, 0x41, 0xF0, 0x80, 0x01, 0xC3, 0xF8, 0x04, 0x18, 0x53, 0x69, 0x58, 0x06, 0xFC, 0xD5, 0x1C, 0x49, +0x0B, 0x69, 0x00, 0x2B, 0xFC, 0xDA, 0x4F, 0xF4, 0x84, 0x63, 0x19, 0x4A, 0x0B, 0x61, 0x13, 0x69, 0x99, 0x06, 0xFC, 0xD4, +0xD2, 0xF8, 0x04, 0x38, 0x15, 0x49, 0x43, 0xF4, 0x80, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, +0x00, 0x73, 0xC2, 0xF8, 0x04, 0x38, 0x4B, 0x69, 0x1A, 0x06, 0xFC, 0xD5, 0x0B, 0x69, 0x0E, 0x4A, 0x43, 0xF0, 0x10, 0x03, +0x0B, 0x61, 0x13, 0x69, 0xDB, 0x06, 0xFC, 0xD4, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF4, 0x80, 0x63, 0xC2, 0xF8, 0x04, 0x38, +0x75, 0xE7, 0x4E, 0xF8, 0x07, 0xC0, 0x5E, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x80, 0x40, 0x4E, 0xF8, 0x02, 0x00, 0x0E, 0xEB, +0x07, 0x06, 0x30, 0x68, 0x80, 0x07, 0xFC, 0xD5, 0xE2, 0xE6, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x6F, 0x26, 0x17, 0x00, +0x6E, 0x26, 0x17, 0x00, 0x20, 0x85, 0x15, 0x00, 0x00, 0x0B, 0x20, 0x40, 0x00, 0x80, 0x00, 0x08, 0xE0, 0x0A, 0x20, 0x40, +0xE8, 0x0A, 0x20, 0x40, 0x00, 0x09, 0x20, 0x40, 0xE0, 0x08, 0x20, 0x40, 0xB4, 0x27, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, +0xC8, 0x27, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, +0x20, 0x26, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, 0x28, 0x85, 0x15, 0x00, 0x48, 0x28, 0x17, 0x00, 0x17, 0x01, 0x21, 0x00, +0x08, 0x09, 0x20, 0x40, 0xE8, 0x08, 0x20, 0x40, 0x05, 0x48, 0x1E, 0x21, 0x1A, 0xF0, 0x90, 0xFC, 0x4F, 0xF4, 0xF0, 0x42, +0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x7F, 0xFC, 0x64, 0xE6, 0x0C, 0x85, 0x15, 0x00, 0x08, 0xB5, 0x04, 0x49, +0x04, 0x48, 0x1A, 0xF0, 0x81, 0xFC, 0x04, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x08, 0xBD, 0x00, 0xBF, 0x54, 0x85, 0x15, 0x00, +0xCC, 0xB5, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, 0x01, 0x4B, 0x18, 0x78, 0x70, 0x47, 0x00, 0xBF, 0x52, 0x28, 0x17, 0x00, +0x08, 0xB5, 0x07, 0x48, 0x1A, 0xF0, 0x6C, 0xFC, 0x06, 0x4B, 0x07, 0x4A, 0x00, 0x21, 0x19, 0x70, 0xD2, 0xF8, 0x00, 0x3E, +0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x00, 0x3E, 0x08, 0xBD, 0x00, 0xBF, 0x30, 0x85, 0x15, 0x00, 0x52, 0x28, 0x17, 0x00, +0x00, 0x00, 0x20, 0x40, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x1A, 0x4C, 0x1A, 0x4D, 0x23, 0x68, 0x2A, 0x78, 0x01, 0x33, 0x23, 0x60, 0x1A, 0xB1, 0x18, 0x4A, 0x12, 0x78, +0x04, 0x2A, 0x08, 0xD0, 0x33, 0xB1, 0x13, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, +0x38, 0xBD, 0x13, 0x4A, 0x13, 0x49, 0xD2, 0xF8, 0x04, 0x38, 0x43, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x0A, 0x69, +0x02, 0xF5, 0x0C, 0x52, 0x28, 0x32, 0x0B, 0x69, 0xD3, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x0B, 0x4A, 0x0C, 0x48, 0xD2, 0xF8, +0x04, 0x38, 0x23, 0xF0, 0x01, 0x03, 0xC2, 0xF8, 0x04, 0x38, 0x1A, 0xF0, 0x23, 0xFC, 0x00, 0x22, 0x23, 0x68, 0x2A, 0x70, +0xD8, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x52, 0x28, 0x17, 0x00, 0x6F, 0x26, 0x17, 0x00, +0x00, 0x00, 0x20, 0x40, 0x00, 0x10, 0x50, 0x40, 0x3C, 0x85, 0x15, 0x00, 0x38, 0xB5, 0x04, 0x46, 0x0D, 0x46, 0xFF, 0xF7, +0xB1, 0xFF, 0x15, 0x4B, 0x1B, 0x78, 0x04, 0x2B, 0x20, 0xD1, 0x62, 0x1E, 0xD3, 0xB2, 0x04, 0x2B, 0x1E, 0xD8, 0x60, 0x01, +0x00, 0xF1, 0x80, 0x40, 0x00, 0xF5, 0x00, 0x10, 0xD0, 0xF8, 0x00, 0x39, 0x1B, 0x04, 0x17, 0xD5, 0x0D, 0x49, 0x53, 0x01, +0x03, 0xF1, 0x80, 0x43, 0x01, 0xEB, 0x02, 0x12, 0x03, 0xF5, 0x00, 0x13, 0x01, 0x21, 0xD1, 0x72, 0xC3, 0xF8, 0x34, 0x59, +0xD0, 0xF8, 0x00, 0x39, 0x43, 0xF0, 0x04, 0x43, 0xC0, 0xF8, 0x00, 0x39, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, +0x02, 0x20, 0x38, 0xBD, 0x05, 0x20, 0x38, 0xBD, 0x6F, 0x26, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, 0x93, 0x4B, 0x5A, 0x69, +0x2D, 0xE9, 0xF0, 0x4F, 0x5A, 0x61, 0x9C, 0x69, 0x14, 0x40, 0xE1, 0x04, 0x85, 0xB0, 0x0A, 0xD5, 0x8F, 0x4B, 0xD3, 0xF8, +0xDC, 0x34, 0x98, 0x47, 0x14, 0xF4, 0x00, 0x5A, 0x40, 0xF0, 0xAB, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, +0x44, 0xA2, 0xA2, 0x04, 0x04, 0xEA, 0x0A, 0x0A, 0x04, 0xF4, 0x80, 0x25, 0x04, 0xF4, 0x00, 0x29, 0x04, 0xF4, 0x00, 0x6B, +0x00, 0xF1, 0x9F, 0x80, 0x00, 0x2D, 0x42, 0xD0, 0x81, 0x4D, 0x83, 0x4E, 0xD5, 0xF8, 0x18, 0x28, 0xD5, 0xF8, 0x1C, 0x38, +0x00, 0x24, 0x02, 0xEA, 0x03, 0x08, 0x01, 0x20, 0x00, 0xFA, 0x04, 0xF3, 0x13, 0xEA, 0x08, 0x0F, 0xE7, 0xB2, 0x2D, 0xD0, +0x00, 0x2C, 0x00, 0xF0, 0xA0, 0x80, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x29, 0xC3, 0xF8, 0x28, 0x29, +0xD5, 0xF8, 0x10, 0x18, 0x11, 0x40, 0x11, 0xF0, 0x09, 0x0F, 0x74, 0xD0, 0x16, 0xF8, 0x05, 0x3C, 0xD3, 0xB1, 0x56, 0xF8, +0x0C, 0x3C, 0x01, 0x93, 0xD2, 0x43, 0x56, 0xF8, 0x10, 0x3C, 0x02, 0x93, 0x12, 0xF0, 0x01, 0x03, 0x00, 0x93, 0x40, 0xF0, +0xB6, 0x80, 0x10, 0x22, 0x00, 0x21, 0xA6, 0xF1, 0x10, 0x00, 0xF6, 0xF7, 0x15, 0xF9, 0x6A, 0x4B, 0x03, 0xEB, 0x84, 0x03, +0x1B, 0x6B, 0x1B, 0xB1, 0xDD, 0xE9, 0x00, 0x21, 0x02, 0x98, 0x98, 0x47, 0x04, 0x2F, 0x02, 0xD0, 0x01, 0x34, 0x10, 0x36, +0xC5, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, 0x3C, 0xD0, 0x5E, 0x4D, 0x62, 0x4E, 0xD5, 0xF8, 0x18, 0x78, 0xD5, 0xF8, 0x1C, 0x38, +0xDF, 0xF8, 0x90, 0x81, 0xDF, 0xF8, 0x74, 0x91, 0x1F, 0x40, 0x00, 0x24, 0x4F, 0xF4, 0x80, 0x33, 0xA3, 0x40, 0x3B, 0x42, +0x0C, 0xD0, 0xC4, 0xB1, 0x63, 0x1E, 0x05, 0xEB, 0x43, 0x13, 0xD3, 0xF8, 0x28, 0x2B, 0xC3, 0xF8, 0x28, 0x2B, 0xD5, 0xF8, +0x14, 0x38, 0x13, 0x40, 0xDB, 0x07, 0x5F, 0xD4, 0xE3, 0xB2, 0x04, 0x2B, 0x1B, 0xD0, 0x01, 0x34, 0x4F, 0xF4, 0x80, 0x33, +0xA3, 0x40, 0x3B, 0x42, 0x06, 0xF1, 0x10, 0x06, 0xF4, 0xD0, 0x00, 0x2C, 0xE6, 0xD1, 0xD5, 0xF8, 0x08, 0x1B, 0xC5, 0xF8, +0x08, 0x1B, 0xD5, 0xF8, 0x14, 0x38, 0x0B, 0x40, 0xDA, 0x06, 0x7B, 0xD4, 0x13, 0xF0, 0x29, 0x0F, 0xE9, 0xD0, 0x44, 0x4B, +0x20, 0x46, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x3F, 0x4B, 0xD3, 0xF8, +0x8C, 0x34, 0x98, 0x47, 0xBA, 0xF1, 0x00, 0x0F, 0xBF, 0xF6, 0x60, 0xAF, 0x3B, 0x4B, 0xD3, 0xF8, 0x90, 0x34, 0x05, 0xB0, +0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x3C, 0x48, 0xFC, 0xF7, 0x56, 0xF9, 0xA4, 0xE7, 0x4F, 0xF0, 0x00, 0x0B, 0xD9, 0x46, +0x5D, 0x46, 0x33, 0x4B, 0xD3, 0xF8, 0x08, 0x38, 0x13, 0xF0, 0x06, 0x0F, 0xC3, 0xF3, 0x47, 0x02, 0x04, 0xD0, 0xD3, 0x07, +0x02, 0xD5, 0x34, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2C, 0x4B, 0x33, 0x4A, 0xC3, 0xF8, 0x00, 0x29, 0xC3, 0xF8, 0x00, 0x2B, +0xFE, 0xF7, 0xF4, 0xFC, 0x4A, 0xE7, 0xD5, 0xF8, 0x08, 0x19, 0xC5, 0xF8, 0x08, 0x19, 0xD5, 0xF8, 0x10, 0x38, 0x0B, 0x40, +0x13, 0xF0, 0x18, 0x0F, 0x2B, 0xD1, 0xDF, 0x07, 0x80, 0xD5, 0x23, 0x4B, 0xD3, 0xF8, 0x00, 0x31, 0x98, 0x47, 0x7B, 0xE7, +0x16, 0xF8, 0x08, 0x3C, 0x00, 0x2B, 0x9B, 0xD0, 0x58, 0xF8, 0x24, 0x30, 0x56, 0xF8, 0x0C, 0x1C, 0x1B, 0x88, 0x02, 0x93, +0x30, 0x46, 0xA3, 0x00, 0x50, 0xF8, 0x10, 0x2D, 0x03, 0x92, 0x01, 0x91, 0x10, 0x22, 0x00, 0x21, 0x00, 0x93, 0xF6, 0xF7, +0x71, 0xF8, 0x00, 0x9B, 0x4B, 0x44, 0x1B, 0x6A, 0x00, 0x2B, 0x85, 0xD0, 0xDD, 0xE9, 0x01, 0x01, 0x00, 0x22, 0x41, 0x1A, +0x03, 0x98, 0x98, 0x47, 0x7E, 0xE7, 0x39, 0x46, 0xFE, 0xF7, 0x8A, 0xFE, 0x45, 0xE7, 0xD5, 0xF8, 0x10, 0x38, 0x23, 0xF0, +0x10, 0x03, 0xC5, 0xF8, 0x10, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, 0xFE, 0xF7, 0xE9, 0xFD, 0x49, 0xE7, +0xD5, 0xF8, 0x14, 0x38, 0x23, 0xF0, 0x10, 0x03, 0xC5, 0xF8, 0x14, 0x38, 0x22, 0x46, 0x4F, 0xF4, 0x00, 0x11, 0x20, 0x46, +0xFE, 0xF7, 0x80, 0xFD, 0x63, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x20, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x27, 0x17, 0x00, +0x20, 0x26, 0x17, 0x00, 0x08, 0x28, 0x17, 0x00, 0x48, 0x85, 0x15, 0x00, 0x4C, 0x28, 0x17, 0x00, 0x00, 0x80, 0x00, 0x08, +0x00, 0x3C, 0x0C, 0x88, 0x40, 0x60, 0x17, 0x00, 0x38, 0xB9, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0x70, 0x18, 0x70, 0x0C, 0x4B, +0x1B, 0x68, 0x5B, 0xB1, 0x18, 0x47, 0x01, 0x28, 0x09, 0xD0, 0x09, 0x4B, 0x02, 0x38, 0x1B, 0x68, 0x01, 0x28, 0x94, 0xBF, +0x02, 0x20, 0x03, 0x20, 0x00, 0x2B, 0xF3, 0xD1, 0x70, 0x47, 0x05, 0x4A, 0x05, 0x4B, 0x10, 0x70, 0x18, 0x70, 0xEA, 0xE7, +0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x60, 0x28, 0x17, 0x00, 0x5B, 0x28, 0x17, 0x00, 0x5C, 0x28, 0x17, 0x00, +0x00, 0x48, 0x70, 0x47, 0x54, 0x86, 0x15, 0x00, 0x01, 0x28, 0x15, 0xD1, 0x08, 0xB5, 0x0B, 0x4B, 0x1B, 0x68, 0x0B, 0xB1, +0x04, 0x20, 0x98, 0x47, 0x02, 0x22, 0x11, 0x46, 0x4F, 0xF4, 0x00, 0x73, 0x01, 0x20, 0xFE, 0xF7, 0x65, 0xFF, 0x4F, 0xF4, +0x00, 0x73, 0x02, 0x22, 0x01, 0x21, 0x00, 0x20, 0xFE, 0xF7, 0x5E, 0xFF, 0x01, 0x20, 0x08, 0xBD, 0x00, 0x20, 0x70, 0x47, +0x60, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x58, 0x4E, 0xDF, 0xF8, 0x9C, 0xE1, 0x33, 0x88, 0x57, 0x4C, 0x00, 0x2A, +0x03, 0xF1, 0x01, 0x03, 0x0C, 0xBF, 0x02, 0x25, 0x03, 0x25, 0x9B, 0xB2, 0x00, 0x27, 0x33, 0x80, 0x8E, 0xF8, 0x00, 0x50, +0x27, 0x70, 0x9E, 0xF8, 0x00, 0xC0, 0xBC, 0xF1, 0x02, 0x0F, 0x4C, 0xD1, 0x03, 0x29, 0x04, 0x46, 0x0D, 0x46, 0x8E, 0xF8, +0x00, 0x70, 0x55, 0xD9, 0x43, 0x78, 0x4C, 0x4A, 0x07, 0x78, 0x12, 0x78, 0x90, 0xF8, 0x02, 0x80, 0x1B, 0x02, 0x03, 0xF4, +0x70, 0x63, 0x1F, 0x43, 0x00, 0x2A, 0x78, 0xD1, 0xB8, 0xF1, 0x01, 0x0F, 0x64, 0xD0, 0xB8, 0xF1, 0x11, 0x0F, 0x55, 0xD1, +0xDF, 0xF8, 0x44, 0x81, 0x98, 0xF8, 0x9D, 0x27, 0x98, 0xF8, 0x9E, 0x37, 0x9A, 0x42, 0x77, 0xD2, 0x3B, 0x1D, 0xAB, 0x42, +0x02, 0xD0, 0x7B, 0x1D, 0x9D, 0x42, 0x6E, 0xD1, 0x3D, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x98, 0xF8, 0x9C, 0x37, +0x3B, 0x49, 0x98, 0xF8, 0x9D, 0x27, 0x01, 0x33, 0xA1, 0xFB, 0x03, 0x01, 0x49, 0x09, 0x01, 0xEB, 0x81, 0x01, 0xA3, 0xEB, +0xC1, 0x01, 0x08, 0xEB, 0x01, 0x15, 0x04, 0x34, 0x53, 0x1C, 0x88, 0xF8, 0x9C, 0x17, 0x34, 0x48, 0xC5, 0xF8, 0x20, 0x45, +0x05, 0xF2, 0x1C, 0x51, 0xC5, 0xF8, 0x24, 0x75, 0x88, 0xF8, 0x9D, 0x37, 0x19, 0xF0, 0x22, 0xF8, 0x4F, 0xF4, 0x00, 0x00, +0x18, 0xF0, 0x7C, 0xFF, 0x0B, 0xE0, 0x9E, 0xF8, 0x00, 0x10, 0x2C, 0x48, 0xFC, 0xF7, 0x28, 0xF8, 0x47, 0xF2, 0x30, 0x52, +0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0xE1, 0xF9, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x31, 0x88, 0x26, 0x48, +0x89, 0xB2, 0x2A, 0x46, 0xFC, 0xF7, 0x18, 0xF8, 0x24, 0x4B, 0x18, 0x68, 0x20, 0x1A, 0xFD, 0xF7, 0x05, 0xF9, 0x1D, 0x4B, +0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x41, 0x46, 0x1F, 0x48, 0xFC, 0xF7, 0x08, 0xF8, +0x31, 0x88, 0x1E, 0x48, 0x89, 0xB2, 0x2B, 0x46, 0x3A, 0x46, 0xFC, 0xF7, 0x01, 0xF8, 0xE7, 0xE7, 0xBD, 0x42, 0x02, 0xD0, +0x7B, 0x1C, 0xAB, 0x42, 0x12, 0xD1, 0x11, 0x4D, 0xD5, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0x20, 0x1D, 0xD5, 0xF8, 0x0C, 0x31, +0x98, 0x47, 0x40, 0x20, 0x18, 0xF0, 0x3E, 0xFF, 0xCD, 0xE7, 0x0A, 0x46, 0x4F, 0xF4, 0x00, 0x70, 0x11, 0x49, 0x1A, 0xF0, +0x03, 0xFA, 0x7F, 0xE7, 0x31, 0x88, 0x10, 0x48, 0xDE, 0xE7, 0x31, 0x88, 0x0F, 0x48, 0xDB, 0xE7, 0x0F, 0x48, 0xFB, 0xF7, +0xDF, 0xFF, 0xC5, 0xE7, 0x56, 0x28, 0x17, 0x00, 0x58, 0x28, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xCD, 0xCC, 0xCC, 0xCC, 0xF8, 0x5F, 0x17, 0x00, 0xD0, 0x85, 0x15, 0x00, 0xC0, 0x85, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, +0xB0, 0x85, 0x15, 0x00, 0x78, 0x85, 0x15, 0x00, 0x68, 0x85, 0x15, 0x00, 0x70, 0x85, 0x15, 0x00, 0x84, 0x85, 0x15, 0x00, +0x98, 0x85, 0x15, 0x00, 0x59, 0x28, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x2A, 0x2A, 0x4B, +0x0C, 0xBF, 0x02, 0x21, 0x03, 0x21, 0x19, 0x70, 0x19, 0x78, 0x02, 0x29, 0x3D, 0xD1, 0x27, 0x4C, 0x22, 0x78, 0x00, 0x21, +0x19, 0x70, 0x52, 0xB3, 0x25, 0x4D, 0x26, 0x4F, 0xA5, 0xF1, 0x08, 0x06, 0x0A, 0xE0, 0x01, 0x2A, 0x41, 0x46, 0x38, 0x46, +0x28, 0xD1, 0x13, 0x2B, 0x40, 0x46, 0x01, 0xD0, 0xFD, 0xF7, 0x90, 0xF8, 0x23, 0x78, 0xD3, 0xB1, 0x28, 0x46, 0x18, 0xF0, +0xCD, 0xFF, 0x42, 0x68, 0x23, 0x78, 0xD2, 0xF8, 0x04, 0x80, 0x01, 0x3B, 0x01, 0x46, 0x30, 0x46, 0x23, 0x70, 0x18, 0xF0, +0x7F, 0xFF, 0x98, 0xF8, 0x02, 0x30, 0x1A, 0x09, 0xE3, 0xD1, 0x17, 0x4A, 0x13, 0x88, 0x10, 0x20, 0x01, 0x33, 0x13, 0x80, +0x18, 0xF0, 0xD2, 0xFE, 0x23, 0x78, 0x00, 0x2B, 0xE4, 0xD1, 0x13, 0x4B, 0xD3, 0xF8, 0x44, 0x34, 0x98, 0x47, 0x01, 0x20, +0xBD, 0xE8, 0xF0, 0x81, 0xFB, 0xF7, 0x78, 0xFF, 0x40, 0x46, 0x20, 0x21, 0x1A, 0xF0, 0x1C, 0xFD, 0xD4, 0xE7, 0x19, 0x78, +0x0C, 0x48, 0xFB, 0xF7, 0x6F, 0xFF, 0x47, 0xF2, 0x30, 0x52, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0x18, 0xF0, 0x28, 0xF9, +0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, +0xF0, 0x85, 0x15, 0x00, 0x54, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x86, 0x15, 0x00, 0x10, 0x4B, 0x11, 0x49, +0x11, 0x4A, 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x00, 0x68, 0x18, 0x60, 0xDF, 0xF8, 0x44, 0x80, 0x0E, 0x4F, 0x0F, 0x4E, +0x00, 0x23, 0x0B, 0x70, 0x13, 0x70, 0x29, 0x7A, 0xD8, 0xF8, 0x08, 0x31, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x38, 0x46, +0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x30, 0x46, 0x1A, 0xF0, 0x04, 0xF9, 0x00, 0x2C, 0xF0, 0xD1, 0x20, 0x46, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0xBF, 0x60, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x5A, 0x28, 0x17, 0x00, 0x38, 0x1A, 0x17, 0x00, +0x20, 0x86, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4D, 0x2B, 0x78, 0xFB, 0xB9, 0xD8, 0xB1, 0x0A, 0x46, +0xC9, 0xB1, 0x1B, 0x4F, 0x3B, 0x78, 0xE3, 0xB9, 0x1A, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, 0x30, 0x3B, 0x23, 0xF0, +0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0x01, 0x46, 0xC4, 0xF8, 0x30, 0x3B, 0x30, 0x46, 0xFE, 0xF7, 0x7B, 0xFE, 0x04, 0x46, +0xC8, 0xB9, 0x13, 0x4B, 0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, +0x6F, 0xF0, 0x0D, 0x04, 0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xFD, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, +0x31, 0x46, 0xFE, 0xF7, 0xB3, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, +0xEF, 0xFE, 0x4F, 0xF0, 0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, +0x58, 0x28, 0x17, 0x00, 0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x20, 0x4D, 0x2B, 0x78, 0x2B, 0xBB, +0x08, 0xB3, 0x0A, 0x46, 0xF9, 0xB1, 0x1E, 0x4F, 0x3B, 0x78, 0x13, 0xBB, 0x1D, 0x4C, 0x01, 0x26, 0x3E, 0x70, 0xD4, 0xF8, +0x30, 0x3B, 0x23, 0xF0, 0xFF, 0x53, 0x23, 0xF4, 0xC0, 0x13, 0xC4, 0xF8, 0x30, 0x3B, 0xD4, 0xF8, 0x00, 0x38, 0x43, 0xF4, +0x00, 0x53, 0x01, 0x46, 0xC4, 0xF8, 0x00, 0x38, 0x30, 0x46, 0xFE, 0xF7, 0x87, 0xFE, 0x04, 0x46, 0xC8, 0xB9, 0x13, 0x4B, +0x1E, 0x70, 0x2B, 0x78, 0x73, 0xB9, 0x20, 0x46, 0xF8, 0xBD, 0x6F, 0xF0, 0x0A, 0x04, 0xFA, 0xE7, 0x6F, 0xF0, 0x0D, 0x04, +0xF7, 0xE7, 0x39, 0x78, 0x0D, 0x48, 0xFB, 0xF7, 0xAF, 0xFE, 0x6F, 0xF0, 0x02, 0x04, 0xF0, 0xE7, 0x31, 0x46, 0xFE, 0xF7, +0x65, 0xFC, 0x3C, 0x70, 0x6F, 0xF0, 0x0D, 0x04, 0xE9, 0xE7, 0x01, 0x46, 0x07, 0x48, 0xFB, 0xF7, 0xA1, 0xFE, 0x4F, 0xF0, +0xFF, 0x34, 0xE2, 0xE7, 0x5B, 0x28, 0x17, 0x00, 0x59, 0x28, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x58, 0x28, 0x17, 0x00, +0x30, 0x86, 0x15, 0x00, 0x48, 0x86, 0x15, 0x00, 0xF8, 0xB5, 0x26, 0x4C, 0xFF, 0xF7, 0xFE, 0xFB, 0x23, 0x78, 0x00, 0x2B, +0x42, 0xD1, 0x24, 0x4D, 0x28, 0x46, 0x18, 0xF0, 0xFB, 0xFE, 0xDF, 0xF8, 0x90, 0xC0, 0xC0, 0xB2, 0x8C, 0xF8, 0x00, 0x00, +0x00, 0x28, 0x31, 0xD0, 0x1F, 0x4A, 0x2F, 0x68, 0x42, 0xF2, 0x30, 0x03, 0x01, 0x28, 0xD6, 0x58, 0x28, 0xD0, 0xBD, 0x89, +0xB3, 0x89, 0xAB, 0x42, 0x11, 0xD2, 0x39, 0x46, 0x03, 0x46, 0x03, 0xE0, 0x53, 0xB1, 0x95, 0x89, 0x0E, 0x46, 0x11, 0x46, +0xC2, 0x1A, 0xD2, 0xB2, 0x01, 0x3B, 0xF5, 0xB1, 0x0A, 0x68, 0xDB, 0xB2, 0x00, 0x2A, 0xF3, 0xD1, 0x8C, 0xF8, 0x00, 0x30, +0x0E, 0x46, 0xB3, 0x7B, 0x72, 0x68, 0x79, 0x68, 0x01, 0x3B, 0x02, 0xEB, 0xC3, 0x02, 0x01, 0x20, 0xD3, 0x78, 0x20, 0x70, +0x23, 0xF0, 0x0A, 0x03, 0x43, 0xF0, 0x0A, 0x03, 0xD3, 0x70, 0x02, 0x20, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0x0A, 0xBC, +0x00, 0x2E, 0xEA, 0xD1, 0x6F, 0xF0, 0x61, 0x00, 0xF8, 0xBD, 0x8C, 0xF8, 0x00, 0x20, 0xE4, 0xE7, 0x6F, 0xF0, 0x62, 0x00, +0xF8, 0xBD, 0x00, 0xBF, 0x5A, 0x28, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x64, 0x60, 0x17, 0x00, +0x01, 0x28, 0x07, 0xD0, 0x06, 0x28, 0x07, 0xD0, 0x04, 0x4B, 0x0F, 0x28, 0x0C, 0xBF, 0x18, 0x46, 0x00, 0x20, 0x70, 0x47, +0x02, 0x48, 0x70, 0x47, 0x02, 0x48, 0x70, 0x47, 0x74, 0x86, 0x15, 0x00, 0x80, 0x86, 0x15, 0x00, 0x94, 0x86, 0x15, 0x00, +0x06, 0x28, 0x0B, 0xD8, 0x01, 0x38, 0x05, 0x28, 0x16, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x05, 0x03, 0x13, 0x0F, 0x11, 0x03, +0x09, 0x48, 0x70, 0x47, 0x09, 0x48, 0x70, 0x47, 0x12, 0x30, 0xC0, 0xB2, 0x06, 0x4B, 0x02, 0x28, 0x34, 0xBF, 0x18, 0x46, +0x00, 0x20, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, 0x05, 0x48, 0x70, 0x47, +0xC4, 0x86, 0x15, 0x00, 0xB4, 0x86, 0x15, 0x00, 0xA0, 0x86, 0x15, 0x00, 0xA8, 0x86, 0x15, 0x00, 0xD8, 0x86, 0x15, 0x00, +0xEC, 0x86, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x1D, 0x4F, 0x1E, 0x48, 0x18, 0xF0, 0xE4, 0xFD, 0x3B, 0x68, 0x1B, 0x89, +0x93, 0xB3, 0xDF, 0xF8, 0x7C, 0x90, 0x1B, 0x4E, 0xDF, 0xF8, 0x78, 0x80, 0xDF, 0xF8, 0x78, 0xB0, 0xDF, 0xF8, 0x78, 0xA0, +0x00, 0x25, 0x0C, 0xE0, 0x21, 0x46, 0x15, 0x48, 0x18, 0xF0, 0xD6, 0xFD, 0x3A, 0x68, 0x33, 0x88, 0x11, 0x89, 0x01, 0x35, +0xAA, 0xB2, 0x01, 0x33, 0x91, 0x42, 0x33, 0x80, 0x1A, 0xD9, 0xB9, 0xF8, 0xD4, 0x10, 0x04, 0x39, 0x89, 0xB2, 0x40, 0x46, +0xFC, 0xF7, 0x58, 0xFC, 0x04, 0x46, 0x00, 0x28, 0xE8, 0xD1, 0xA9, 0xB2, 0x58, 0x46, 0x19, 0xF0, 0x99, 0xFF, 0xDA, 0xF8, +0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDE, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xFB, 0x72, 0x1A, 0xF0, +0x07, 0xFA, 0xD7, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x78, 0x36, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0xF0, 0x86, 0x15, 0x00, +0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x0C, 0x4C, 0x0C, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0xD2, 0xFD, 0x18, 0xB1, 0x0A, 0x4A, +0x13, 0x88, 0x01, 0x3B, 0x13, 0x80, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, +0x66, 0x28, 0x17, 0x00, 0x38, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x28, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0x27, 0x4C, 0x28, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x65, 0xFD, 0x26, 0x4A, +0x26, 0x49, 0x13, 0x88, 0x0D, 0x78, 0x01, 0x33, 0x9B, 0xB2, 0x13, 0x80, 0x24, 0x4A, 0x11, 0x78, 0x9D, 0xB9, 0x49, 0xB9, +0x23, 0x68, 0x33, 0xB1, 0x1C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, +0x1E, 0x49, 0x09, 0x78, 0x99, 0x42, 0xF1, 0xD8, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x15, 0x70, 0x1B, 0xE0, 0x00, 0x29, +0xEA, 0xD0, 0x19, 0x49, 0x09, 0x78, 0x99, 0x42, 0xE6, 0xD8, 0x18, 0x4B, 0x00, 0x21, 0x11, 0x70, 0xD3, 0xF8, 0x00, 0x28, +0x22, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0x00, 0x28, 0xD3, 0xF8, 0x20, 0x2B, 0x8A, 0x42, 0x05, 0xDA, 0xD3, 0xF8, 0x20, 0x2B, +0x42, 0xF0, 0x80, 0x62, 0xC3, 0xF8, 0x20, 0x2B, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xA9, 0xFF, 0x0D, 0x49, +0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x4E, 0xFF, 0x0B, 0x4B, 0xD3, 0xF8, 0x3C, 0x34, 0x98, 0x47, 0xC4, 0xE7, 0x00, 0xBF, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, +0x64, 0x28, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x87, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xF8, 0xB5, 0x0C, 0x4D, 0x0C, 0x48, 0x18, 0xF0, 0x01, 0xFD, 0x2B, 0x68, 0x9B, 0x88, 0x83, 0xB1, 0x0A, 0x4F, 0x09, 0x4E, +0x00, 0x24, 0x7C, 0x21, 0x38, 0x46, 0xFC, 0xF7, 0x8D, 0xFB, 0x01, 0x46, 0x30, 0x46, 0x18, 0xF0, 0xF7, 0xFC, 0x2B, 0x68, +0x01, 0x34, 0x9A, 0x88, 0xA3, 0xB2, 0x9A, 0x42, 0xF1, 0xD8, 0xF8, 0xBD, 0x78, 0x36, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, +0xE4, 0x25, 0x17, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x09, 0x4C, 0x09, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x1E, 0xFD, 0x23, 0x68, 0x33, 0xB1, +0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4C, 0x0A, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, +0xB9, 0xFC, 0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, +0x10, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x60, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, +0xFF, 0xF7, 0x5E, 0xFD, 0x03, 0x48, 0x19, 0xF0, 0x7B, 0xFE, 0x01, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xFC, 0x87, 0x15, 0x00, +0x28, 0x87, 0x15, 0x00, 0x70, 0xB5, 0x3C, 0x4D, 0x3C, 0x4C, 0x2A, 0x68, 0x3C, 0x49, 0x12, 0x69, 0x3C, 0x4B, 0x22, 0x60, +0x02, 0xF1, 0x40, 0x06, 0x00, 0x24, 0x0E, 0x60, 0x3A, 0x4E, 0x98, 0x60, 0xC3, 0xE9, 0x00, 0x44, 0x21, 0x46, 0x10, 0x46, +0x4F, 0xF4, 0xA0, 0x72, 0xC3, 0xE9, 0x04, 0x44, 0xDC, 0x60, 0xB4, 0x81, 0xF5, 0xF7, 0xEC, 0xFB, 0x2B, 0x68, 0x34, 0x49, +0x58, 0x69, 0x34, 0x4A, 0x34, 0x4B, 0x08, 0x60, 0x21, 0x46, 0x00, 0xF1, 0x08, 0x04, 0x14, 0x60, 0x00, 0xF1, 0x10, 0x02, +0x1A, 0x60, 0x00, 0xF1, 0x18, 0x02, 0x5A, 0x60, 0x00, 0xF1, 0x20, 0x02, 0x9A, 0x60, 0x2E, 0x4C, 0x00, 0xF1, 0x28, 0x02, +0xDA, 0x60, 0x00, 0xF1, 0x30, 0x03, 0x4F, 0xF4, 0x4B, 0x62, 0x23, 0x60, 0xF5, 0xF7, 0xCE, 0xFB, 0x29, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2E, 0xDB, 0x27, 0x4B, 0x28, 0x49, 0xB3, 0xF8, 0xD4, 0x20, 0x0C, 0x68, 0xB3, 0xF8, +0xD6, 0x00, 0xB3, 0xF8, 0xE6, 0x10, 0x25, 0x4D, 0x25, 0x4E, 0x12, 0x1B, 0x25, 0x4C, 0x04, 0x3A, 0x22, 0x60, 0x04, 0x38, +0x24, 0x4C, 0x30, 0x60, 0x05, 0xFB, 0x01, 0xF1, 0x93, 0xF8, 0xE0, 0x00, 0x22, 0x4D, 0x20, 0x70, 0x22, 0x4A, 0x93, 0xF8, +0xE1, 0x00, 0x28, 0x70, 0x93, 0xF8, 0xE2, 0x50, 0x20, 0x48, 0x15, 0x70, 0x20, 0x4C, 0x21, 0x4A, 0x93, 0xF8, 0xE3, 0x50, +0x93, 0xF8, 0xE4, 0x30, 0x03, 0x70, 0x1F, 0x4B, 0x25, 0x70, 0x91, 0x42, 0xD4, 0xBF, 0x19, 0x60, 0x1A, 0x60, 0x01, 0x20, +0x70, 0xBD, 0x2B, 0x68, 0x9B, 0x69, 0xB3, 0xF5, 0x4B, 0x6F, 0xCB, 0xD2, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0xF2, 0x22, +0x1A, 0xF0, 0x76, 0xF8, 0xC4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x60, 0x60, 0x17, 0x00, 0x58, 0x60, 0x17, 0x00, +0xA4, 0x60, 0x17, 0x00, 0x8C, 0x60, 0x17, 0x00, 0x5C, 0x60, 0x17, 0x00, 0x40, 0x60, 0x17, 0x00, 0x44, 0x60, 0x17, 0x00, +0x54, 0x60, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, +0x9C, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x88, 0x60, 0x17, 0x00, 0xA0, 0x60, 0x17, 0x00, +0x68, 0x60, 0x17, 0x00, 0xA1, 0x60, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x6C, 0x60, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x3C, 0x87, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x43, 0x7E, 0x07, 0x7E, 0x09, 0x2B, 0x05, 0x46, 0x09, 0xD8, 0x49, 0x4A, +0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x25, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x81, 0x80, 0x6B, 0x8B, +0xDF, 0xF8, 0x30, 0x81, 0x1A, 0x07, 0x5A, 0xD4, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x64, 0x30, +0x00, 0x2B, 0x73, 0xD0, 0x3E, 0x4B, 0xAE, 0x7D, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0xDB, 0x3C, 0x48, +0x18, 0xF0, 0x0C, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x4C, 0xD0, 0x3A, 0x48, 0xE1, 0x8B, 0x83, 0x5D, 0xE2, 0x6C, 0x4F, 0xF0, +0x00, 0x09, 0x01, 0x33, 0x21, 0xF0, 0x01, 0x01, 0x83, 0x55, 0xE1, 0x83, 0xC4, 0xF8, 0x44, 0x90, 0x29, 0x46, 0xC2, 0xF8, +0x10, 0x90, 0x20, 0x1D, 0x1C, 0x22, 0xC4, 0xF8, 0x2C, 0x90, 0x2C, 0xF0, 0xA9, 0xFA, 0x30, 0x4B, 0xE1, 0x8B, 0x1B, 0x68, +0x84, 0xF8, 0x42, 0x90, 0xEB, 0x1A, 0x04, 0x3B, 0x21, 0xF4, 0x00, 0x42, 0x22, 0xF0, 0x02, 0x02, 0xA3, 0x64, 0x0B, 0x07, +0xC4, 0xF8, 0x24, 0x90, 0xC4, 0xF8, 0x50, 0x90, 0xE2, 0x83, 0x29, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, +0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x23, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, +0x23, 0x20, 0x02, 0x44, 0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x07, 0x60, 0x99, 0x30, 0x21, 0x46, 0x08, 0xEB, +0xC0, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x7F, 0xBB, 0x16, 0x48, 0x18, 0xF0, 0xC0, 0xFB, 0x05, 0x26, 0x04, 0x46, +0x00, 0x28, 0xB2, 0xD1, 0x13, 0x4B, 0x16, 0x48, 0x99, 0x5D, 0xFB, 0xF7, 0x83, 0xFB, 0xFE, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, +0x00, 0xFB, 0x07, 0x80, 0x21, 0x46, 0x00, 0xF5, 0xA3, 0x60, 0xBD, 0xE8, 0xF8, 0x43, 0x18, 0xF0, 0x67, 0xBB, 0x05, 0x2E, +0x99, 0xD9, 0x0E, 0x49, 0x0E, 0x48, 0x40, 0xF2, 0x5F, 0x32, 0x19, 0xF0, 0xB3, 0xFF, 0x92, 0xE7, 0x07, 0x4B, 0x18, 0x68, +0x28, 0x1A, 0x04, 0x38, 0xBD, 0xE8, 0xF8, 0x43, 0xFC, 0xF7, 0x58, 0xBC, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x20, 0x58, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x60, 0x87, 0x15, 0x00, +0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x48, 0x81, +0xDF, 0xF8, 0x48, 0x91, 0xDF, 0xF8, 0x48, 0xA1, 0x59, 0xE0, 0x47, 0x48, 0x18, 0xF0, 0x7A, 0xFB, 0x04, 0x46, 0xDF, 0xF8, +0x40, 0xE1, 0x1C, 0x22, 0x29, 0x46, 0x04, 0x30, 0x00, 0x2C, 0x63, 0xD0, 0xB4, 0xF8, 0x1E, 0xB0, 0x1E, 0xF8, 0x07, 0xC0, +0xE3, 0x6C, 0x66, 0x64, 0x2B, 0xF0, 0x01, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, 0xA4, 0xF8, 0x1E, 0xB0, 0x1E, 0x61, 0xE6, 0x62, +0x0E, 0xF8, 0x07, 0xC0, 0x2C, 0xF0, 0x16, 0xFA, 0x95, 0xF8, 0x20, 0x20, 0xE3, 0x8B, 0x38, 0x48, 0x12, 0xF0, 0x01, 0x0F, +0x14, 0xBF, 0x4F, 0xF4, 0x00, 0x52, 0x4F, 0xF4, 0x08, 0x52, 0x2A, 0x61, 0x84, 0xF8, 0x42, 0x60, 0xC5, 0xE9, 0x05, 0x66, +0x62, 0x7F, 0x10, 0x32, 0x92, 0x02, 0x45, 0xF8, 0x18, 0x2C, 0x21, 0x7F, 0x26, 0x65, 0xA4, 0x22, 0x99, 0x37, 0x23, 0xF4, +0x00, 0x43, 0x12, 0xFB, 0x01, 0x77, 0x23, 0xF0, 0x02, 0x03, 0x4C, 0x3D, 0xA5, 0x64, 0x00, 0xEB, 0xC7, 0x00, 0xE3, 0x83, +0x21, 0x46, 0x18, 0xF0, 0xF5, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x24, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x24, 0x4C, 0x24, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x2A, 0xFB, 0x98, 0xF8, 0x11, 0x35, +0x22, 0x68, 0x01, 0x3B, 0x88, 0xF8, 0x11, 0x35, 0x3A, 0xBB, 0xD8, 0xF8, 0x14, 0x35, 0x00, 0x26, 0xDB, 0xB1, 0xD9, 0xF8, +0x00, 0x20, 0x5D, 0x68, 0xB2, 0xF9, 0x00, 0x30, 0xAF, 0x7D, 0x00, 0x2B, 0x99, 0xDA, 0x05, 0x2F, 0x97, 0xD9, 0x18, 0x49, +0x4F, 0xF4, 0x66, 0x72, 0x50, 0x46, 0x19, 0xF0, 0x1F, 0xFF, 0x90, 0xE7, 0x15, 0x48, 0x1E, 0xF8, 0x07, 0x10, 0xFB, 0xF7, +0xD5, 0xFA, 0x14, 0x4B, 0x18, 0x68, 0x28, 0x1A, 0x04, 0x38, 0xFC, 0xF7, 0xC1, 0xFB, 0x20, 0x20, 0x18, 0xF0, 0x3E, 0xFA, +0xBD, 0xE8, 0xF8, 0x4F, 0x40, 0x20, 0x18, 0xF0, 0x15, 0xBA, 0x08, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0x22, 0x60, 0x00, 0x2A, +0x7F, 0xF4, 0x74, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x71, 0xAF, 0x62, 0xB6, 0x6E, 0xE7, 0x00, 0xBF, 0x20, 0x58, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x60, 0x87, 0x15, 0x00, 0x80, 0x1A, 0x17, 0x00, 0x58, 0x58, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x82, 0x15, 0x00, +0x74, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xB8, 0x90, 0x29, 0x4D, 0x2A, 0x4F, 0xDF, 0xF8, 0xAC, 0x80, +0x29, 0x4E, 0x20, 0xE0, 0x5C, 0x68, 0x20, 0x46, 0xFA, 0xF7, 0x1E, 0xFB, 0x38, 0x68, 0x20, 0x1A, 0x04, 0x38, 0xFC, 0xF7, +0x81, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, +0x00, 0x30, 0x30, 0x46, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xB3, 0xFA, 0x95, 0xF8, 0x9D, 0x37, 0xD9, 0xF8, +0x00, 0x20, 0x01, 0x3B, 0x85, 0xF8, 0x9D, 0x37, 0x0A, 0xBB, 0xD5, 0xF8, 0xA0, 0x37, 0x00, 0x2B, 0xDA, 0xD1, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x14, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x4F, 0xF4, +0x00, 0x00, 0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0xD4, 0xF9, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x0D, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x01, 0x3A, +0xD8, 0xF8, 0x00, 0x30, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, 0xB3, 0xD1, 0x00, 0x2B, 0xB1, 0xD0, 0x62, 0xB6, 0xAF, 0xE7, +0x58, 0x58, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, 0xF8, 0x5F, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x0E, 0x4B, 0x10, 0xB5, 0xD3, 0xF8, 0x90, 0x32, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4C, 0x23, 0x68, 0x10, 0x20, 0x01, 0x33, 0x23, 0x60, 0x18, 0xF0, 0x9E, 0xF9, +0x23, 0x68, 0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, +0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x16, 0x4C, 0x16, 0x4E, 0x17, 0x4F, +0x14, 0x4D, 0x15, 0xE0, 0x58, 0x68, 0xFC, 0xF7, 0x05, 0xFB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, +0x01, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x28, 0x46, 0x01, 0x33, 0x3B, 0x60, 0x18, 0xF0, 0x3A, 0xFA, 0x0E, 0x4A, 0x39, 0x68, +0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0x39, 0xB9, 0x23, 0x68, 0x00, 0x2B, 0xE6, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x08, 0x20, +0x18, 0xF0, 0x6A, 0xB9, 0x01, 0x39, 0x33, 0x68, 0x39, 0x60, 0x00, 0x29, 0xDA, 0xD1, 0x00, 0x2B, 0xD8, 0xD0, 0x62, 0xB6, +0xD6, 0xE7, 0x00, 0xBF, 0x94, 0x4E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8E, 0x4E, 0x17, 0x00, +0x59, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x67, 0xD1, 0x2D, 0xE9, 0xF0, 0x47, 0x57, 0x4D, 0x2B, 0x78, 0x00, 0x2B, 0x47, 0xD1, +0x56, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x5B, 0xD1, 0x55, 0x49, 0x56, 0x4A, 0x09, 0x78, 0x12, 0x88, 0x91, 0x42, 0x5E, 0xD2, +0x54, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x78, 0xD0, 0x2B, 0x78, 0x00, 0x2B, +0x4D, 0xD0, 0x4C, 0x4B, 0xDF, 0xF8, 0x60, 0xA1, 0x1B, 0x78, 0x4E, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0x00, 0x2B, 0x7B, 0xD1, +0x4C, 0x4B, 0x39, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x20, 0x44, 0x98, 0x47, 0x00, 0x28, 0x39, 0xD0, 0x01, 0x46, 0x49, 0x48, +0xDF, 0xF8, 0x08, 0x91, 0xDF, 0xF8, 0x18, 0x81, 0xFB, 0xF7, 0xAE, 0xF9, 0x05, 0x26, 0x2B, 0x78, 0x00, 0x2B, 0x48, 0xD1, +0xDA, 0xF8, 0x00, 0x00, 0xD8, 0xF8, 0x40, 0x34, 0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0x28, 0xB3, 0x01, 0x3E, 0xF2, 0xD1, +0x05, 0x21, 0x3F, 0x48, 0xFB, 0xF7, 0x9C, 0xF9, 0x20, 0x46, 0xFC, 0xF7, 0x8B, 0xFA, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0x20, +0x18, 0xF0, 0xE2, 0xB8, 0x34, 0x4B, 0x1B, 0x88, 0x00, 0x2B, 0x46, 0xD0, 0x31, 0x4A, 0x12, 0x78, 0x9A, 0x42, 0xB9, 0xD3, +0x36, 0x4A, 0x2E, 0x4B, 0x12, 0x68, 0x01, 0x21, 0x19, 0x70, 0x00, 0x2A, 0x47, 0xD1, 0x34, 0x4B, 0x34, 0x49, 0x1A, 0x88, +0x4F, 0xF4, 0x00, 0x70, 0x92, 0xB2, 0x19, 0xF0, 0x97, 0xFB, 0xA9, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0xDF, 0xF8, +0xC8, 0xA0, 0x28, 0x4F, 0xDA, 0xF8, 0x00, 0x00, 0xB4, 0xE7, 0x1A, 0x78, 0x00, 0x2A, 0x9D, 0xD1, 0x28, 0x4A, 0x12, 0x68, +0x01, 0x21, 0x19, 0x70, 0x92, 0xBB, 0x27, 0x4B, 0x27, 0x49, 0x1A, 0x88, 0xBD, 0xE8, 0xF0, 0x47, 0x4F, 0xF4, 0x00, 0x70, +0x92, 0xB2, 0x19, 0xF0, 0x7B, 0xBB, 0x99, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x00, 0x00, 0x2B, 0xB9, 0xD8, 0xF8, 0x40, 0x34, +0x39, 0x68, 0x20, 0x44, 0x98, 0x47, 0xB2, 0xE7, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x72, 0xFA, 0xAD, 0xE7, 0x04, 0x20, +0x18, 0xF0, 0x9C, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x19, 0x48, 0xFB, 0xF7, 0x49, 0xB9, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x49, +0x4F, 0xF4, 0x00, 0x70, 0x19, 0xF0, 0x5C, 0xBB, 0x39, 0x68, 0x20, 0x44, 0xFF, 0xF7, 0x5E, 0xFA, 0x84, 0xE7, 0x40, 0xF2, +0x1F, 0x40, 0x17, 0xF0, 0xF9, 0xFA, 0xB2, 0xE7, 0x40, 0xF2, 0x1F, 0x40, 0x17, 0xF0, 0xF4, 0xFA, 0xC7, 0xE7, 0x00, 0xBF, +0x58, 0x28, 0x17, 0x00, 0x68, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0x7C, 0x60, 0x17, 0x00, 0x66, 0x28, 0x17, 0x00, +0xA4, 0x60, 0x17, 0x00, 0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x8C, 0x87, 0x15, 0x00, 0xAC, 0x87, 0x15, 0x00, +0x6C, 0x60, 0x17, 0x00, 0x56, 0x28, 0x17, 0x00, 0x7C, 0x87, 0x15, 0x00, 0x98, 0x87, 0x15, 0x00, 0x84, 0x87, 0x15, 0x00, +0x80, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x0F, 0x48, 0x19, 0xF0, 0xD8, 0xFA, 0x0E, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, +0x98, 0x47, 0x80, 0xB1, 0x0C, 0x4B, 0x0D, 0x49, 0x1A, 0x68, 0x0D, 0x4B, 0x09, 0x68, 0xD3, 0xF8, 0x40, 0x34, 0x10, 0x44, +0x98, 0x47, 0x01, 0x1E, 0x00, 0xDB, 0x08, 0xBD, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x48, 0xFB, 0xF7, 0xF7, 0xB8, 0xBD, 0xE8, +0x08, 0x40, 0x07, 0x48, 0xFB, 0xF7, 0xF2, 0xB8, 0xC0, 0x87, 0x15, 0x00, 0xA4, 0x60, 0x17, 0x00, 0x80, 0x1A, 0x17, 0x00, +0x78, 0x60, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x87, 0x15, 0x00, 0xE4, 0x87, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x20, +0x18, 0xF0, 0x52, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0x09, 0x4C, 0x0A, 0x4A, 0x23, 0x68, 0xD2, 0xF8, 0x3C, 0x24, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x33, 0xB1, +0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x11, 0x4D, 0x11, 0x4F, 0x28, 0x68, 0x00, 0xF5, 0x0D, 0x70, +0x18, 0xF0, 0xA4, 0xF8, 0x28, 0x68, 0x00, 0xF5, 0x0F, 0x70, 0x18, 0xF0, 0x9F, 0xF8, 0x3B, 0x68, 0x1B, 0x89, 0x93, 0xB1, +0x0B, 0x4E, 0x00, 0x24, 0x4F, 0xF4, 0xD7, 0x61, 0x30, 0x46, 0xFB, 0xF7, 0x2B, 0xFF, 0x01, 0x46, 0x28, 0x68, 0x00, 0xF5, +0x0D, 0x70, 0x18, 0xF0, 0x93, 0xF8, 0x3B, 0x68, 0x01, 0x34, 0x1A, 0x89, 0xA3, 0xB2, 0x9A, 0x42, 0xEE, 0xD8, 0xF8, 0xBD, +0x00, 0x38, 0x18, 0x00, 0x78, 0x36, 0x17, 0x00, 0xE4, 0x25, 0x17, 0x00, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x12, 0x4A, +0x01, 0x46, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0E, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0E, 0x4A, 0x23, 0x68, 0x10, 0x68, 0x01, 0x33, 0x00, 0xF5, 0x0D, 0x70, 0x23, 0x60, +0x18, 0xF0, 0x6C, 0xF8, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x4C, 0x40, 0x04, 0x40, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x00, 0x38, 0x18, 0x00, 0x08, 0xB5, 0x03, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x19, 0xF0, 0x7A, 0xFA, +0x01, 0x20, 0x08, 0xBD, 0x08, 0x88, 0x15, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x00, 0x23, 0xC2, 0xE9, 0x02, 0x03, 0xC2, 0xE9, +0x04, 0x33, 0xC2, 0xE9, 0x00, 0x33, 0x8B, 0x81, 0x01, 0x20, 0x70, 0x47, 0xBC, 0x60, 0x17, 0x00, 0xD4, 0x60, 0x17, 0x00, +0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x0C, 0x92, 0xDF, 0xF8, 0x0C, 0x82, 0xD9, 0xF8, 0x14, 0x35, 0x00, 0x2B, 0x00, 0xF0, +0x8F, 0x80, 0xDF, 0xF8, 0xE8, 0xA1, 0xDF, 0xF8, 0x00, 0xB2, 0x78, 0xE0, 0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, +0x06, 0x12, 0x92, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x6D, 0x4A, 0x1F, 0x7A, 0x13, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA1, 0x80, 0x6A, 0x48, 0x18, 0xF0, 0x5B, 0xF8, 0x04, 0x46, 0x00, 0x28, 0x6C, 0xD0, +0xC2, 0x8B, 0xC1, 0x6C, 0x1A, 0xF8, 0x07, 0xC0, 0x00, 0x23, 0x22, 0xF0, 0x01, 0x02, 0xC2, 0x83, 0x43, 0x64, 0x0C, 0xF1, +0x01, 0x0C, 0x0B, 0x61, 0x1C, 0x22, 0xC3, 0x62, 0x29, 0x46, 0x04, 0x30, 0x0A, 0xF8, 0x07, 0xC0, 0x2B, 0xF0, 0xFA, 0xFE, +0xE2, 0x8B, 0xDB, 0xF8, 0x00, 0x10, 0x6D, 0x1A, 0xC2, 0xF3, 0x0E, 0x01, 0x00, 0x23, 0xE1, 0x83, 0x11, 0x07, 0x84, 0xF8, +0x42, 0x30, 0x23, 0x65, 0xA5, 0x64, 0x6F, 0xD4, 0x63, 0x7F, 0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, +0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x53, 0x49, 0xA0, 0x88, 0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x02, 0x44, +0x41, 0xF8, 0x23, 0x20, 0xA4, 0x20, 0x00, 0xFB, 0x06, 0x76, 0x4A, 0x48, 0x99, 0x36, 0x21, 0x46, 0x00, 0xEB, 0xC6, 0x00, +0x17, 0xF0, 0xD6, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x48, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0xD8, 0xF8, 0x00, 0x30, 0x46, 0x48, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x18, 0xF0, 0x0A, 0xF8, 0x99, 0xF8, 0x11, 0x35, +0xD8, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0x89, 0xF8, 0x11, 0x35, 0x3A, 0xB1, 0x3E, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, +0x00, 0x20, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD9, 0xF8, 0x14, 0x35, 0x83, 0xB1, 0x5D, 0x68, 0x6A, 0x8B, 0x2E, 0x7E, +0x14, 0x07, 0x81, 0xD5, 0x34, 0x48, 0x17, 0xF0, 0xEF, 0xFF, 0x05, 0x27, 0x04, 0x46, 0x00, 0x28, 0x92, 0xD1, 0x35, 0x4B, +0x35, 0x48, 0xD9, 0x5D, 0xFA, 0xF7, 0xB2, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x20, 0x20, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x14, 0xFF, +0x40, 0x20, 0x17, 0xF0, 0xED, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x25, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, +0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x8F, 0x24, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x21, 0x46, +0x00, 0xFB, 0x06, 0x30, 0x17, 0xF0, 0x7A, 0xFF, 0xA2, 0xE7, 0x05, 0x2F, 0x7F, 0xF6, 0x5C, 0xAF, 0x1F, 0x49, 0x20, 0x48, +0xB8, 0x22, 0x19, 0xF0, 0xC5, 0xFB, 0x55, 0xE7, 0xDB, 0xF8, 0x00, 0x00, 0x28, 0x1A, 0xFC, 0xF7, 0x6D, 0xF8, 0xEF, 0xF3, +0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x11, 0x48, +0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x17, 0xF0, 0x9F, 0xFF, 0x99, 0xF8, 0x11, 0x25, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x3A, +0x89, 0xF8, 0x11, 0x25, 0x00, 0x2B, 0x9B, 0xD0, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2B, +0x94, 0xD1, 0x00, 0x2A, 0x92, 0xD0, 0x90, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, +0x7C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x5D, 0x17, 0x00, 0x74, 0x28, 0x17, 0x00, 0x1C, 0x88, 0x15, 0x00, +0x30, 0x8D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x88, 0x82, 0x15, 0x00, 0x58, 0x58, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x84, 0x1A, 0x17, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x04, 0x20, 0x17, 0xF0, +0xA5, 0xBE, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xD0, 0xF8, 0xA8, 0x44, 0xD1, 0xF8, 0xB0, 0x50, 0x07, 0x46, 0x0E, 0x46, +0x00, 0x2C, 0x00, 0xF0, 0x8F, 0x80, 0xA2, 0x49, 0xA2, 0x4A, 0x4F, 0xF0, 0xFF, 0x33, 0x0B, 0x60, 0x13, 0x60, 0x94, 0xF8, +0x60, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF2, 0xB9, 0x81, 0xDF, 0xE8, 0x18, 0xF0, 0x49, 0x00, 0xF3, 0x00, 0x45, 0x01, +0x03, 0x01, 0x05, 0x00, 0x9A, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, +0xDA, 0x60, 0x22, 0x6D, 0xDA, 0x61, 0x62, 0x6D, 0x1A, 0x62, 0xA2, 0x6D, 0x5A, 0x62, 0x94, 0x4B, 0x94, 0x4A, 0xE1, 0x6D, +0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x13, 0xF0, 0x02, 0x0F, 0xC1, 0x46, 0x4F, 0xF4, 0x80, 0x63, 0x4F, 0xF4, 0x80, 0x51, +0x4F, 0xF0, 0x01, 0x08, 0x48, 0xD0, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, 0x8C, 0x4A, 0x43, 0xEA, 0x0C, 0x13, +0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x00, 0x2D, +0x48, 0xD0, 0x81, 0x4B, 0x7F, 0x49, 0xD6, 0xF8, 0x26, 0x00, 0x72, 0x8D, 0x08, 0x60, 0x1A, 0x60, 0x95, 0xF8, 0x60, 0x30, +0x04, 0x2B, 0x00, 0xF2, 0x68, 0x81, 0xDF, 0xE8, 0x13, 0xF0, 0x78, 0x00, 0x41, 0x00, 0xD4, 0x00, 0xCF, 0x00, 0xC5, 0x00, +0x00, 0x21, 0x4F, 0xF0, 0x01, 0x09, 0x77, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, +0x22, 0x6F, 0xDA, 0x60, 0x73, 0x4B, 0x1B, 0x68, 0xB9, 0xF1, 0x02, 0x0F, 0x1B, 0x78, 0x40, 0xF0, 0xF2, 0x80, 0xD8, 0x07, +0x40, 0xF1, 0x20, 0x81, 0x71, 0x48, 0x22, 0x6D, 0x02, 0x60, 0x62, 0x6D, 0x42, 0x60, 0xA2, 0x6D, 0x82, 0x60, 0xE2, 0x6D, +0xC2, 0x60, 0x9B, 0x07, 0x00, 0xF1, 0xFF, 0x80, 0x4F, 0xF4, 0x00, 0x73, 0x97, 0xF8, 0x63, 0xC0, 0x94, 0xF8, 0x62, 0x00, +0x67, 0x4A, 0x43, 0xEA, 0x0C, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x43, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, +0x58, 0x00, 0xFC, 0xD4, 0x00, 0x2D, 0xB6, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0xA1, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0xAE, 0xE7, +0x4F, 0xF0, 0x02, 0x09, 0x59, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, +0xDA, 0x60, 0xB9, 0xF1, 0x04, 0x0F, 0x40, 0xF0, 0x96, 0x80, 0x57, 0x4B, 0x2A, 0x6D, 0x1A, 0x60, 0x6A, 0x6D, 0x5A, 0x60, +0xAA, 0x6D, 0x9A, 0x60, 0x50, 0x4B, 0x51, 0x4A, 0xE9, 0x6D, 0x1B, 0x68, 0x11, 0x60, 0x1B, 0x78, 0x99, 0x07, 0x40, 0xF1, +0xD6, 0x80, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x4A, 0x4A, +0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, +0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x09, 0x3D, 0x4B, +0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0xB9, 0xF1, 0x02, 0x0F, +0x62, 0xD1, 0x38, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0xDA, 0x07, 0x40, 0xF1, 0xB3, 0x80, 0x38, 0x4A, 0x29, 0x6D, 0x11, 0x60, +0x69, 0x6D, 0x51, 0x60, 0xA9, 0x6D, 0x91, 0x60, 0xE9, 0x6D, 0xD1, 0x60, 0x9A, 0x07, 0x7A, 0xD4, 0x4F, 0xF4, 0x00, 0x79, +0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x2E, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, 0x08, 0x03, +0x43, 0xEA, 0x09, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, +0x4F, 0xF0, 0x02, 0x09, 0x22, 0x4B, 0x62, 0x6E, 0x1A, 0x60, 0xA2, 0x6E, 0x5A, 0x60, 0xE2, 0x6E, 0x9A, 0x60, 0x22, 0x6F, +0xDA, 0x60, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, 0x51, 0xE7, 0x4F, 0xF0, 0x01, 0x09, 0xC8, 0x46, 0x4F, 0xF4, +0x80, 0x51, 0x42, 0xE7, 0x18, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, 0x9A, 0x60, 0x2A, 0x6F, +0xDA, 0x60, 0x80, 0xE7, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF0, 0x01, 0x09, 0xA7, 0xE7, 0x95, 0xF8, 0x74, 0x30, 0x10, 0x2B, +0x00, 0xF0, 0x83, 0x80, 0x20, 0x2B, 0x7B, 0xD0, 0x0D, 0x4B, 0x6A, 0x6E, 0x1A, 0x60, 0xAA, 0x6E, 0x5A, 0x60, 0xEA, 0x6E, +0x9A, 0x60, 0x2A, 0x6F, 0xDA, 0x60, 0x4F, 0xF0, 0x03, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0x4F, 0xEA, 0x08, 0x38, 0x9C, 0xD0, +0x06, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x56, 0xD4, 0x4F, 0xEA, 0x09, 0x29, 0xA7, 0xE7, 0xBC, 0x00, 0x32, 0x40, +0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0xD4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, +0xC8, 0x00, 0x32, 0x40, 0x94, 0xF8, 0x74, 0x30, 0x10, 0x2B, 0x5B, 0xD0, 0x20, 0x2B, 0x4A, 0xD0, 0x4F, 0xF0, 0x03, 0x09, +0xA6, 0xE7, 0x9A, 0x07, 0x42, 0xD5, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0x14, 0xD9, 0x4F, 0xEA, 0x09, 0x23, +0xCB, 0xE6, 0x97, 0xF8, 0x63, 0x30, 0x95, 0xF8, 0x62, 0x10, 0x3A, 0x4A, 0x1B, 0x01, 0x43, 0xEA, 0x01, 0x43, 0x43, 0xEA, +0x08, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0xBD, 0xE8, 0xF8, 0x83, 0x97, 0xF8, +0x63, 0x30, 0x94, 0xF8, 0x62, 0x00, 0x31, 0x4A, 0x41, 0xEA, 0x03, 0x13, 0x43, 0xEA, 0x00, 0x43, 0x43, 0xF0, 0x80, 0x43, +0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xB9, 0xE6, 0x4F, 0xEA, 0x08, 0x38, 0x4F, 0xF4, 0x80, 0x69, 0x5F, 0xE7, +0x29, 0x48, 0x02, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x02, 0x60, 0xE2, 0xE6, 0x26, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x01, 0x02, +0x0A, 0x60, 0x4F, 0xE7, 0x09, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x01, 0x2B, 0xC7, 0xD9, 0x4F, 0xEA, 0x09, 0x29, 0x14, 0xE7, +0x4F, 0xEA, 0x09, 0x23, 0xD6, 0xE6, 0x4F, 0xF4, 0x00, 0x51, 0x4F, 0xF0, 0x03, 0x09, 0xB0, 0xE6, 0x4F, 0xF4, 0x00, 0x58, +0x4F, 0xF0, 0x03, 0x09, 0x1F, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x03, 0x09, 0x1A, 0xE7, 0x00, 0x21, 0x88, 0x46, +0x4F, 0xF0, 0x03, 0x09, 0xA1, 0xE6, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xD6, 0xAE, +0x12, 0x49, 0x13, 0x48, 0xA6, 0x22, 0x19, 0xF0, 0xA7, 0xF9, 0xCF, 0xE6, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x06, 0xDB, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x01, 0x08, 0x87, 0xE6, 0x09, 0x49, +0x09, 0x48, 0x4F, 0x22, 0x19, 0xF0, 0x94, 0xF9, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF4, 0x80, 0x51, 0x4F, 0xF0, 0x01, 0x08, +0x7B, 0xE6, 0x00, 0xBF, 0xC4, 0x00, 0x32, 0x40, 0x64, 0x05, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xA3, 0x4E, 0x0D, 0x46, 0xD6, 0xF8, 0xF0, 0x70, 0x04, 0x46, 0xF4, 0xF7, +0xF7, 0xFE, 0xB8, 0x47, 0xA0, 0x4A, 0xA1, 0x49, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0A, 0x68, 0x9F, 0x4B, +0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, +0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x97, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x4F, 0xF4, 0x40, 0x52, 0x00, 0x2B, 0xC1, 0xF8, 0x04, 0x21, 0xC0, 0xF2, 0xAD, 0x80, 0x92, 0x4B, 0x8E, 0x4A, +0x92, 0x49, 0x19, 0x60, 0x13, 0x68, 0x92, 0x4F, 0x43, 0xF4, 0x00, 0x53, 0x13, 0x60, 0xF5, 0xF7, 0x49, 0xFD, 0xDF, 0xF8, +0x9C, 0xC2, 0x8F, 0x49, 0xDC, 0xF8, 0x00, 0x20, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, +0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x0B, 0x68, 0x89, 0x4A, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, +0x02, 0x03, 0x13, 0x60, 0x3B, 0x68, 0x9A, 0x03, 0x00, 0xF1, 0xAF, 0x80, 0x84, 0x4A, 0x28, 0x8C, 0x13, 0x68, 0x80, 0x49, +0x9B, 0xB2, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x60, 0x0B, 0x68, 0x1F, 0x04, 0x00, 0xF1, 0x87, 0x80, 0x75, 0x4B, 0xDF, 0xF8, +0x50, 0xE2, 0x1A, 0x68, 0xDF, 0xF8, 0x4C, 0xC2, 0x7C, 0x48, 0x7D, 0x4F, 0x7D, 0x49, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, +0x4F, 0xF4, 0x40, 0x72, 0xCE, 0xF8, 0x00, 0x20, 0xE2, 0x6D, 0xCC, 0xF8, 0x00, 0x20, 0xB4, 0xF8, 0x60, 0x20, 0x02, 0x60, +0xA2, 0x6B, 0xA0, 0x8F, 0x3A, 0x60, 0xD4, 0xF8, 0x90, 0x21, 0x08, 0x60, 0x91, 0x78, 0x74, 0x4A, 0x02, 0xEB, 0x81, 0x01, +0x50, 0x68, 0x49, 0x69, 0xC7, 0xF8, 0xBC, 0x10, 0x19, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x13, 0x68, 0x6F, 0x49, +0x6F, 0x4A, 0x03, 0x43, 0x3B, 0x64, 0x6F, 0x48, 0x6F, 0x4B, 0x08, 0x60, 0x13, 0x60, 0xD6, 0xF8, 0xB0, 0x31, 0x94, 0xF8, +0x63, 0x10, 0x95, 0xF8, 0x23, 0x00, 0x98, 0x47, 0x29, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFD, 0x09, 0xF0, 0xAC, 0xFB, +0x68, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x67, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD6, 0xF8, +0x60, 0x32, 0x98, 0x47, 0x64, 0x4A, 0x65, 0x49, 0xD6, 0xF8, 0x9C, 0x34, 0x11, 0x60, 0x98, 0x47, 0x4D, 0x4A, 0x63, 0x48, +0x13, 0x68, 0x30, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x01, 0x21, 0x04, 0x60, 0x00, 0x20, 0x17, 0xF0, 0xDE, 0xF9, +0x5E, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x5D, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x5C, 0x49, +0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x58, 0x4A, +0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, +0xF0, 0x81, 0x3C, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, 0xBF, 0xF4, 0x4D, 0xAF, 0x50, 0x49, 0x50, 0x48, 0xF3, 0x22, +0x19, 0xF0, 0x9C, 0xF8, 0x46, 0xE7, 0xF5, 0xF7, 0x35, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x74, 0xAF, 0x6B, 0x68, 0x9A, 0x06, +0x7F, 0xF5, 0x70, 0xAF, 0x28, 0x8C, 0xF5, 0xF7, 0x71, 0xFC, 0x07, 0xF0, 0xB9, 0xFF, 0xD6, 0xF8, 0xE0, 0x33, 0x98, 0x47, +0x94, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x63, 0xAF, 0xD6, 0xF8, 0x30, 0x33, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, +0x5C, 0xE7, 0xF5, 0xF7, 0x3F, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x4C, 0xAF, 0xF5, 0xF7, 0x6E, 0xFC, 0xDF, 0xF8, 0xF4, 0x80, +0xD8, 0xF8, 0x00, 0x30, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, 0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0xC8, 0xF8, 0x00, 0x00, +0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, +0x43, 0xF0, 0x04, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x00, 0x30, +0x3B, 0x68, 0x1B, 0x04, 0x0F, 0xD4, 0x15, 0x4B, 0x1B, 0x68, 0x9B, 0x03, 0x7F, 0xF5, 0x22, 0xAF, 0xF5, 0xF7, 0x18, 0xFC, +0x00, 0x28, 0x3F, 0xF4, 0x1D, 0xAF, 0x27, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x16, 0xE7, 0xF5, 0xF7, +0xDF, 0xFB, 0x00, 0x28, 0xEB, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0xC8, 0xF8, +0x00, 0x30, 0xE2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x54, 0x00, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, +0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0x04, 0x00, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, +0x6C, 0x00, 0x32, 0x40, 0x68, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, +0x98, 0x9C, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, +0x2C, 0x19, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, 0xC0, 0xB3, 0x33, 0x40, 0xA0, 0xA0, 0x28, 0x28, 0x38, 0x00, 0x32, 0x40, +0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, +0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, 0x9C, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, +0x2D, 0xE9, 0xF0, 0x47, 0x5B, 0x4B, 0x5C, 0x4A, 0x1D, 0x68, 0xD2, 0xF8, 0x20, 0x80, 0x15, 0xF0, 0x01, 0x05, 0xD8, 0xF8, +0xE4, 0x90, 0x84, 0xB0, 0x00, 0xF0, 0x83, 0x80, 0x1A, 0x68, 0x57, 0x4F, 0x22, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x00, 0x23, +0x7B, 0x70, 0x01, 0x22, 0x54, 0x48, 0x55, 0x49, 0x03, 0x68, 0x55, 0x4C, 0x43, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x0B, 0x68, +0x00, 0xF5, 0xEC, 0x10, 0x00, 0xF6, 0x6C, 0x70, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x23, 0x68, 0x01, 0x69, 0x00, 0x91, +0x02, 0x20, 0x4E, 0x49, 0x4E, 0x4C, 0x18, 0xF0, 0x9D, 0xFD, 0x3B, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0xD4, 0xF8, 0x3C, 0x31, +0xD8, 0xF8, 0x40, 0x60, 0x00, 0x20, 0x98, 0x47, 0x49, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, +0xD4, 0xF8, 0x9C, 0x34, 0xDF, 0xF8, 0x38, 0xA1, 0x98, 0x47, 0xD4, 0xF8, 0x80, 0x34, 0x30, 0x79, 0x98, 0x47, 0x4F, 0xF0, +0x00, 0x0C, 0x33, 0x89, 0xF2, 0x88, 0x71, 0x79, 0x30, 0x79, 0xCD, 0xF8, 0x08, 0xC0, 0x96, 0xF8, 0x0D, 0xC0, 0xCD, 0xF8, +0x04, 0xC0, 0xB6, 0xF8, 0x0A, 0xC0, 0xCD, 0xF8, 0x00, 0xC0, 0xF5, 0xF7, 0x9F, 0xFA, 0xD4, 0xF8, 0x3C, 0x33, 0x96, 0xF9, +0x0C, 0x00, 0x98, 0x47, 0x9A, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x33, 0xD0, 0xD4, 0xF8, 0xA8, 0x34, 0xBA, 0xF8, 0x26, 0x00, +0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0xD8, 0x34, 0x49, 0x46, 0x40, 0x46, +0x98, 0x47, 0x00, 0x23, 0xC7, 0xE9, 0x01, 0x33, 0x3B, 0x70, 0x00, 0x2D, 0x33, 0xD0, 0x2B, 0x49, 0x2B, 0x4A, 0x0B, 0x68, +0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x28, 0x4A, 0x28, 0x48, 0x13, 0x68, +0x28, 0x49, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x83, 0x68, 0xD4, 0xF8, 0xA0, 0x22, 0x5A, 0x65, +0x20, 0x23, 0x0B, 0x60, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x16, 0x4F, 0x2A, 0x46, 0x81, 0xE7, 0xD4, 0xF8, 0xA0, 0x34, +0xBA, 0xF8, 0x26, 0x00, 0x98, 0x47, 0xBA, 0xF8, 0x26, 0x00, 0xD4, 0xF8, 0xA4, 0x34, 0x98, 0x47, 0xCA, 0xE7, 0x33, 0x7E, +0xFF, 0x2B, 0x99, 0xD1, 0x19, 0x49, 0x1A, 0x48, 0x40, 0xF2, 0x89, 0x12, 0x18, 0xF0, 0x4C, 0xFF, 0x92, 0xE7, 0x40, 0x46, +0x0B, 0xF0, 0xF6, 0xF8, 0xD8, 0xF8, 0x04, 0x30, 0x15, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0xC8, 0xF8, 0x04, 0x30, 0x92, 0xF8, +0xB6, 0x30, 0x00, 0x2B, 0xC7, 0xD0, 0x03, 0xF0, 0x99, 0xF8, 0xC4, 0xE7, 0x10, 0x00, 0x58, 0x40, 0x1C, 0x9E, 0x17, 0x00, +0x3C, 0x36, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, 0x84, 0x40, 0x04, 0x40, 0x88, 0x00, 0x32, 0x40, 0x88, 0x88, 0x15, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, +0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0x79, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, +0xBC, 0x34, 0x17, 0x00, 0xF8, 0xB5, 0x3F, 0x4F, 0x3F, 0x4C, 0x3E, 0x6A, 0x3F, 0x49, 0xD6, 0xF8, 0xE4, 0x50, 0x4F, 0xF4, +0xBE, 0x72, 0x20, 0x46, 0x2B, 0xF0, 0xB0, 0xF9, 0x31, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF5, 0xBE, 0x70, 0x2B, 0xF0, +0xA9, 0xF9, 0x29, 0x46, 0x4F, 0xF4, 0x1E, 0x72, 0x04, 0xF2, 0x9C, 0x60, 0x2B, 0xF0, 0xA2, 0xF9, 0x06, 0xF1, 0xEC, 0x01, +0xE8, 0x22, 0x04, 0xF6, 0x14, 0x10, 0x2B, 0xF0, 0x9B, 0xF9, 0x31, 0x6C, 0x1C, 0x22, 0x04, 0xF6, 0xFC, 0x10, 0x2B, 0xF0, +0x95, 0xF9, 0x2F, 0x49, 0x34, 0x22, 0x04, 0xF6, 0x18, 0x20, 0x2B, 0xF0, 0x8F, 0xF9, 0x2D, 0x49, 0x18, 0x22, 0x04, 0xF6, +0x4C, 0x20, 0x2B, 0xF0, 0x89, 0xF9, 0x2B, 0x49, 0x4F, 0xF4, 0x40, 0x72, 0x04, 0xF6, 0x64, 0x20, 0x2B, 0xF0, 0x82, 0xF9, +0x28, 0x49, 0x4F, 0xF4, 0x98, 0x62, 0x04, 0xF6, 0x64, 0x50, 0x2B, 0xF0, 0x7B, 0xF9, 0x26, 0x49, 0x26, 0x48, 0x40, 0x22, +0x2B, 0xF0, 0x76, 0xF9, 0x39, 0x46, 0x28, 0x22, 0x24, 0x48, 0x2B, 0xF0, 0x71, 0xF9, 0x24, 0x49, 0x24, 0x48, 0x60, 0x22, +0x2B, 0xF0, 0x6C, 0xF9, 0x23, 0x4A, 0x24, 0x4B, 0x12, 0x68, 0xD3, 0xF8, 0x84, 0x60, 0xB2, 0xF8, 0x3C, 0xC0, 0xD3, 0xF8, +0x80, 0x20, 0xD3, 0xE9, 0x22, 0x07, 0x41, 0xF2, 0x10, 0x33, 0x41, 0xF2, 0x30, 0x31, 0x24, 0xF8, 0x03, 0xC0, 0x41, 0xF2, +0x2C, 0x33, 0x66, 0x50, 0xE2, 0x50, 0x41, 0xF2, 0x38, 0x36, 0x41, 0xF2, 0x3C, 0x33, 0x41, 0xF2, 0x34, 0x31, 0x18, 0x4A, +0xE2, 0x50, 0xA7, 0x51, 0x17, 0x4B, 0x60, 0x50, 0x05, 0xF5, 0xBC, 0x70, 0x05, 0xF5, 0xCE, 0x71, 0x50, 0xF8, 0x04, 0x2F, +0x1A, 0xB1, 0x14, 0x7B, 0x9C, 0x70, 0x12, 0x89, 0x1A, 0x80, 0x88, 0x42, 0x03, 0xF1, 0x04, 0x03, 0xF4, 0xD1, 0xF8, 0xBD, +0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, +0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x24, 0x52, 0x1E, 0x00, 0x64, 0x52, 0x1E, 0x00, +0x30, 0x9D, 0x17, 0x00, 0x8C, 0x52, 0x1E, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, +0xEC, 0x52, 0x1E, 0x00, 0x70, 0xB5, 0x65, 0x4A, 0x53, 0x78, 0x00, 0x2B, 0x7F, 0xD1, 0x64, 0x4B, 0x1B, 0x68, 0x3B, 0xB1, +0x63, 0x48, 0xD9, 0x68, 0x00, 0x69, 0x09, 0x1A, 0xB1, 0xF5, 0xFA, 0x6F, 0x00, 0xF1, 0xA5, 0x80, 0x13, 0x78, 0x00, 0x2B, +0x68, 0xD0, 0xD2, 0xE9, 0x01, 0x35, 0x5D, 0x48, 0x5D, 0x4A, 0x5E, 0x49, 0x04, 0x69, 0x0E, 0x68, 0xB2, 0xF8, 0xB0, 0x00, +0xB2, 0xF8, 0xB2, 0x10, 0xB2, 0x8E, 0x2B, 0x44, 0x1B, 0x1B, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, +0x98, 0x80, 0xFF, 0xF7, 0x37, 0xFF, 0x56, 0x4B, 0x1B, 0x6A, 0x1C, 0x6C, 0x23, 0x79, 0x20, 0x89, 0x00, 0x2B, 0x56, 0xD0, +0x2A, 0xF0, 0xC8, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x2A, 0xF0, 0x78, 0xFA, 0x50, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x54, 0xFD, +0x4F, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0x26, 0xFC, 0x2A, 0xF0, 0x1E, 0xFA, 0x2A, 0xF0, 0xBC, 0xFE, 0x05, 0x46, 0x20, 0x89, +0x2A, 0xF0, 0xB4, 0xFB, 0x02, 0x46, 0x0B, 0x46, 0x00, 0x20, 0x49, 0x49, 0x2A, 0xF0, 0x42, 0xFD, 0x00, 0x22, 0x4F, 0xF0, +0x83, 0x43, 0x2A, 0xF0, 0x13, 0xFC, 0x2A, 0xF0, 0x0B, 0xFA, 0x2A, 0xF0, 0xA9, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, +0x2A, 0xF0, 0xA0, 0xFB, 0x34, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x2A, 0xF0, 0x2F, 0xFD, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, +0x2A, 0xF0, 0x00, 0xFC, 0x2A, 0xF0, 0xF8, 0xF9, 0x2A, 0xF0, 0x96, 0xFE, 0x3A, 0x4B, 0x3B, 0x49, 0x03, 0xF5, 0x99, 0x56, +0x02, 0x46, 0x35, 0x60, 0x41, 0xF2, 0x24, 0x30, 0x41, 0xF2, 0x28, 0x35, 0x1C, 0x50, 0x5A, 0x51, 0x02, 0x20, 0x18, 0xF0, +0xD5, 0xFB, 0x35, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x33, 0x49, 0x02, 0x20, 0x18, 0xF0, 0xCC, 0xFB, +0x30, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x30, 0x49, 0xF5, 0xE7, 0x2A, 0xF0, 0x71, 0xFB, 0x2F, 0x4B, +0x00, 0x22, 0x2A, 0xF0, 0xD7, 0xFB, 0x25, 0x4B, 0x00, 0x22, 0x2A, 0xF0, 0xFD, 0xFC, 0x24, 0x4B, 0x00, 0x22, 0x2A, 0xF0, +0xCF, 0xFB, 0x2A, 0xF0, 0xC7, 0xF9, 0x2A, 0xF0, 0x65, 0xFE, 0x05, 0x46, 0x20, 0x89, 0x2A, 0xF0, 0x5D, 0xFB, 0x02, 0x46, +0x0B, 0x46, 0x00, 0x20, 0x24, 0x49, 0x2A, 0xF0, 0xEB, 0xFC, 0x00, 0x22, 0x4F, 0xF0, 0x83, 0x43, 0x2A, 0xF0, 0xBC, 0xFB, +0x2A, 0xF0, 0xB4, 0xF9, 0x2A, 0xF0, 0x52, 0xFE, 0x03, 0x46, 0x20, 0x89, 0x1C, 0x46, 0x2A, 0xF0, 0x49, 0xFB, 0x0B, 0xA3, +0xD3, 0xE9, 0x00, 0x23, 0xA7, 0xE7, 0x5A, 0x68, 0x1A, 0x49, 0x02, 0x20, 0x18, 0xF0, 0x92, 0xFB, 0x13, 0x4B, 0x4F, 0xF0, +0x00, 0x42, 0x1A, 0x60, 0x70, 0xBD, 0x17, 0x49, 0xBB, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0xB3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xA2, 0x40, 0x3C, 0x36, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x00, 0x6A, 0x40, +0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0xB9, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x20, 0x89, 0x15, 0x00, 0x00, 0x41, 0x04, 0x40, +0x1C, 0x89, 0x15, 0x00, 0xC4, 0x88, 0x15, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0xA4, 0x40, 0xE8, 0x88, 0x15, 0x00, +0x00, 0x89, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x56, 0x4E, 0xDF, 0xF8, 0x90, 0x81, 0x96, 0xF8, +0xDF, 0x31, 0x96, 0xF8, 0xBF, 0x56, 0xDF, 0xF8, 0x88, 0xB1, 0x53, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xF7, +0x83, 0xB0, 0x08, 0xEB, 0x07, 0x09, 0x06, 0xF5, 0xBE, 0x71, 0x48, 0x46, 0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x7A, 0x00, 0x97, +0x2B, 0xF0, 0x0E, 0xF8, 0x07, 0xF1, 0xEC, 0x00, 0x0A, 0xFB, 0x05, 0xF5, 0x06, 0xF6, 0x14, 0x11, 0xE8, 0x22, 0x40, 0x44, +0x2B, 0xF0, 0x04, 0xF8, 0x05, 0xEB, 0x0B, 0x03, 0x18, 0x46, 0x52, 0x46, 0x06, 0xF2, 0x9C, 0x61, 0x08, 0xEE, 0x10, 0x3A, +0x2A, 0xF0, 0xFA, 0xFF, 0x06, 0xF6, 0xFC, 0x11, 0x1C, 0x22, 0xD9, 0xF8, 0x40, 0x00, 0x3F, 0x4F, 0xDF, 0xF8, 0x30, 0xA1, +0x2A, 0xF0, 0xF0, 0xFF, 0x06, 0xF6, 0x18, 0x21, 0x34, 0x22, 0x3C, 0x48, 0x2A, 0xF0, 0xEA, 0xFF, 0x31, 0x46, 0x4F, 0xF4, +0xBE, 0x72, 0x3A, 0x48, 0x2A, 0xF0, 0xE4, 0xFF, 0x06, 0xF6, 0x4C, 0x21, 0x18, 0x22, 0x38, 0x48, 0x2A, 0xF0, 0xDE, 0xFF, +0x06, 0xF6, 0x64, 0x21, 0x4F, 0xF4, 0x18, 0x62, 0x35, 0x48, 0x2A, 0xF0, 0xD7, 0xFF, 0x06, 0xF6, 0x64, 0x51, 0x4F, 0xF4, +0x98, 0x62, 0x33, 0x48, 0x33, 0x4E, 0x2A, 0xF0, 0xCF, 0xFF, 0x40, 0x22, 0xA4, 0xF1, 0xC8, 0x01, 0x31, 0x48, 0x2A, 0xF0, +0xC9, 0xFF, 0x28, 0x22, 0xA4, 0xF1, 0x88, 0x01, 0x2F, 0x48, 0x2A, 0xF0, 0xC3, 0xFF, 0x2F, 0x48, 0x60, 0x22, 0xA4, 0xF1, +0x60, 0x01, 0x2A, 0xF0, 0xBD, 0xFF, 0x05, 0xF5, 0xBE, 0x75, 0xAB, 0x44, 0x5B, 0xF8, 0x04, 0x3B, 0x50, 0x46, 0x19, 0x46, +0x4B, 0xB1, 0xA2, 0x78, 0x1A, 0x73, 0xD7, 0xF8, 0xDC, 0x22, 0x25, 0x88, 0x1D, 0x81, 0xC3, 0xE9, 0x45, 0x23, 0x17, 0xF0, +0x01, 0xF9, 0x04, 0x34, 0xB4, 0x42, 0xED, 0xD1, 0x1B, 0x48, 0x22, 0x4D, 0x49, 0x46, 0x17, 0xF0, 0xF9, 0xF8, 0x21, 0x48, +0x49, 0x46, 0x17, 0xF0, 0xA5, 0xF8, 0x00, 0x9E, 0x06, 0xF1, 0xE4, 0x00, 0x18, 0xEE, 0x10, 0x1A, 0x40, 0x44, 0x17, 0xF0, +0x9D, 0xF8, 0x01, 0x9A, 0xA4, 0x24, 0x99, 0x23, 0x14, 0xFB, 0x02, 0x34, 0x08, 0xEB, 0xC4, 0x04, 0x35, 0x44, 0x20, 0x46, +0x17, 0xF0, 0x8E, 0xF8, 0x04, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x17, 0xF0, 0x89, 0xF8, 0xAC, 0x42, 0xF5, 0xD1, 0x00, 0x9B, +0x03, 0xF5, 0xA3, 0x60, 0x40, 0x44, 0x03, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x4F, 0x17, 0xF0, 0x7C, 0xB8, +0x00, 0x40, 0x1E, 0x00, 0xEC, 0x52, 0x1E, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, +0x00, 0x88, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x34, 0xE0, 0x17, 0x00, 0x10, 0x53, 0x1E, 0x00, 0xF4, 0xDF, 0x17, 0x00, +0x1C, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x08, 0x8D, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6C, 0x4E, 0x6D, 0x4A, 0x33, 0x68, 0xDF, 0xF8, +0x00, 0x82, 0x0D, 0x46, 0x09, 0x8C, 0x9B, 0xB2, 0x43, 0xEA, 0x01, 0x43, 0xD0, 0xF8, 0x90, 0x11, 0x33, 0x60, 0x8B, 0x78, +0x67, 0x49, 0x02, 0xEB, 0x83, 0x03, 0x1C, 0x3E, 0x5B, 0x69, 0x0B, 0x60, 0x31, 0x68, 0x21, 0xF4, 0xE0, 0x61, 0x04, 0x46, +0x50, 0x68, 0x31, 0x60, 0x13, 0x68, 0x62, 0x49, 0x62, 0x4A, 0x03, 0x43, 0x0B, 0x60, 0x62, 0x4B, 0x62, 0x49, 0x11, 0x60, +0x62, 0x4A, 0x1A, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x9F, 0x03, 0x70, 0xD4, 0x60, 0x4B, 0x1B, 0x68, 0x1A, 0x68, 0xE2, 0xB1, +0x5F, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0xF2, 0xB1, 0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x61, 0xD1, 0xE1, 0x68, 0x5C, 0x48, +0x22, 0xF4, 0x7F, 0x62, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, 0xA2, 0xB9, +0x57, 0x4A, 0x21, 0x69, 0x11, 0x60, 0xDB, 0x68, 0xA3, 0xB9, 0x56, 0x4B, 0x62, 0x69, 0x1A, 0x60, 0x12, 0xE0, 0x51, 0x4A, +0xA1, 0x68, 0x11, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0xE0, 0xD1, 0x4F, 0x4A, 0xE1, 0x68, 0x11, 0x60, 0x9A, 0x68, 0x00, 0x2A, +0xEA, 0xD0, 0x4D, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0xEA, 0xD0, 0x4B, 0x4A, 0x13, 0x60, 0x4B, 0x4B, 0xD3, 0xF8, +0x60, 0x32, 0x98, 0x47, 0x4A, 0x4B, 0x1B, 0x68, 0x9C, 0x01, 0x06, 0xD4, 0x49, 0x4B, 0x3E, 0x4A, 0x01, 0x21, 0x19, 0x60, +0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x28, 0x46, 0x1B, 0xF0, 0xE4, 0xFA, 0x43, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, +0x13, 0x60, 0x01, 0x21, 0x00, 0x20, 0x16, 0xF0, 0x51, 0xFD, 0x41, 0x4B, 0x1B, 0x68, 0x5A, 0x78, 0x22, 0xB1, 0x40, 0x49, +0x0A, 0x68, 0x42, 0xF0, 0x40, 0x02, 0x0A, 0x60, 0x3E, 0x49, 0x9B, 0x78, 0x0A, 0x68, 0xD8, 0x06, 0x4C, 0xBF, 0x22, 0xF0, +0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x3A, 0x4A, 0x13, 0xF0, 0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, +0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x2B, 0x49, 0x0A, 0x60, 0xB8, 0xE7, 0xF4, 0xF7, +0xD7, 0xFF, 0x00, 0x28, 0x8A, 0xD0, 0xF5, 0xF7, 0x07, 0xF8, 0x31, 0x4F, 0x3B, 0x68, 0x00, 0x02, 0x23, 0xF4, 0xE0, 0x63, +0x00, 0xF4, 0xE0, 0x60, 0x18, 0x43, 0x38, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x3B, 0x60, +0x3B, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x3B, 0x60, 0x3B, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, +0x1B, 0x04, 0x0F, 0xD4, 0x24, 0x4B, 0x1B, 0x68, 0x9E, 0x03, 0x7F, 0xF5, 0x69, 0xAF, 0xF4, 0xF7, 0xB9, 0xFF, 0x00, 0x28, +0x3F, 0xF4, 0x64, 0xAF, 0x1E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x5D, 0xE7, 0xF4, 0xF7, 0x80, 0xFF, +0x00, 0x28, 0xEB, 0xD0, 0x33, 0x68, 0x43, 0xF4, 0x00, 0x23, 0x33, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, +0x80, 0x63, 0x3B, 0x60, 0xE0, 0xE7, 0x00, 0xBF, 0x68, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, +0x60, 0x00, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0xC0, 0x07, 0xF9, 0x80, +0xAC, 0x35, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, +0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, +0x80, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x50, 0x03, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, +0x33, 0x4D, 0xDF, 0xF8, 0xE4, 0x80, 0xD5, 0xF8, 0xD0, 0x34, 0x32, 0x4E, 0x41, 0xF2, 0x12, 0x32, 0x18, 0xF8, 0x02, 0x70, +0x98, 0x47, 0xD5, 0xF8, 0x9C, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0xBC, 0x41, 0xF4, 0xF7, 0x46, 0xF9, 0x2C, 0x49, 0xD5, 0xF8, +0x88, 0x24, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x0B, 0x60, 0x20, 0x79, 0x90, 0x47, 0x23, 0x79, 0x86, 0xF8, 0x2A, 0x30, +0x62, 0x79, 0x86, 0xF8, 0x2B, 0x20, 0x62, 0x7B, 0x86, 0xF8, 0x2C, 0x20, 0xE1, 0x88, 0x20, 0x89, 0x62, 0x89, 0x32, 0x85, +0xFF, 0xB2, 0xB1, 0x84, 0xF0, 0x84, 0xD3, 0xB9, 0xD5, 0xF8, 0xA0, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xA4, 0x34, +0x98, 0x47, 0x1D, 0x4E, 0x94, 0xF9, 0x0C, 0x00, 0xD5, 0xF8, 0x3C, 0x33, 0x98, 0x47, 0xD5, 0xF8, 0xD4, 0x34, 0x06, 0xF5, +0xA4, 0x61, 0x30, 0x46, 0x98, 0x47, 0x17, 0xF0, 0x0D, 0x0F, 0x0C, 0xD0, 0xD5, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, +0x18, 0x47, 0xD5, 0xF8, 0xA8, 0x34, 0x98, 0x47, 0xF0, 0x8C, 0xD5, 0xF8, 0xAC, 0x34, 0x98, 0x47, 0xE3, 0xE7, 0xBB, 0x07, +0x14, 0xD5, 0x0F, 0x4A, 0xD8, 0xF8, 0x80, 0x31, 0x11, 0x69, 0x0E, 0x48, 0xD5, 0xF8, 0xE0, 0x21, 0x46, 0x61, 0x05, 0x24, +0x44, 0x77, 0x01, 0xF5, 0x1C, 0x51, 0x43, 0xF0, 0x02, 0x03, 0xC8, 0xF8, 0x80, 0x31, 0x10, 0x31, 0xBD, 0xE8, 0xF0, 0x41, +0x0C, 0x30, 0x10, 0x47, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x1A, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, +0x7C, 0x41, 0x1E, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x38, 0xB5, 0x50, 0xBB, +0x1A, 0x4B, 0x1A, 0x68, 0x52, 0xB1, 0x1A, 0x4B, 0x1A, 0x49, 0x18, 0x69, 0xD3, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x1B, 0x1A, +0x5B, 0x1A, 0xB3, 0xF5, 0xFA, 0x6F, 0x17, 0xD4, 0x16, 0x4A, 0x13, 0x78, 0x7B, 0xB1, 0xD2, 0xE9, 0x01, 0x34, 0x12, 0x48, +0x14, 0x4D, 0x12, 0x49, 0x00, 0x69, 0x2A, 0x68, 0xB1, 0xF8, 0xB0, 0x10, 0x92, 0x8E, 0x23, 0x44, 0x1B, 0x1A, 0x5B, 0x1A, +0x9B, 0x1A, 0x00, 0x2B, 0x0E, 0xDB, 0x0F, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x52, 0x68, 0x0D, 0x49, +0x02, 0x20, 0x18, 0xF0, 0xDB, 0xF8, 0x0A, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x38, 0xBD, 0x09, 0x49, 0x02, 0x20, +0x18, 0xF0, 0xD2, 0xF8, 0xF5, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, +0x3C, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x41, 0x04, 0x40, 0xE8, 0x88, 0x15, 0x00, 0x28, 0x89, 0x15, 0x00, +0xF0, 0xB5, 0x1B, 0x4B, 0x01, 0x22, 0x85, 0xB0, 0xDA, 0x60, 0xEF, 0xF3, 0x14, 0x81, 0xEF, 0xF3, 0x03, 0x82, 0xEF, 0xF3, +0x09, 0x85, 0xEF, 0xF3, 0x08, 0x84, 0xEF, 0xF3, 0x10, 0x83, 0x70, 0x46, 0xCD, 0xE9, 0x01, 0x30, 0x00, 0x94, 0x13, 0x48, +0x2B, 0x46, 0x18, 0xF0, 0x59, 0xF8, 0x15, 0xB9, 0x34, 0xB9, 0x05, 0xB0, 0xF0, 0xBD, 0x10, 0x48, 0x18, 0xF0, 0x52, 0xF8, +0x00, 0x2C, 0xF8, 0xD0, 0x0E, 0x48, 0x0F, 0x4F, 0x0F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0x18, 0xF0, 0x49, 0xF8, 0x04, 0xF5, +0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0x18, 0xF0, 0x41, 0xF8, 0xA5, 0x42, 0xE7, 0xD0, 0x23, 0x07, +0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0x18, 0xF0, 0x39, 0xF8, 0xF1, 0xE7, 0x00, 0xA0, 0x10, 0x40, 0x40, 0x89, 0x15, 0x00, +0x94, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x30, 0xB4, 0x0C, 0x4C, +0x0C, 0x49, 0xD4, 0xF8, 0x3C, 0x31, 0x0C, 0x4A, 0x0C, 0x4D, 0x43, 0xF0, 0x04, 0x03, 0xC4, 0xF8, 0x3C, 0x31, 0xC0, 0x03, +0x03, 0x24, 0xF4, 0x23, 0x08, 0x60, 0x8C, 0x60, 0x82, 0xF8, 0x44, 0x33, 0xAB, 0x68, 0x07, 0x49, 0xC3, 0xF8, 0x50, 0x11, +0x10, 0x23, 0x30, 0xBC, 0x93, 0x60, 0x70, 0x47, 0x00, 0x00, 0x50, 0x40, 0x00, 0xA0, 0x10, 0x40, 0x00, 0xE1, 0x00, 0xE0, +0x00, 0xED, 0x00, 0xE0, 0xA9, 0xC5, 0x12, 0x00, 0x01, 0x4B, 0x1A, 0x68, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, +0x02, 0x4A, 0x93, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x02, 0x4A, 0x93, 0x68, +0x43, 0xF0, 0x02, 0x03, 0x93, 0x60, 0x70, 0x47, 0x00, 0xA0, 0x10, 0x40, 0x08, 0xB5, 0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0xFE, 0xE7, 0x03, 0x49, 0x04, 0x48, 0xBA, 0x22, 0x18, 0xF0, 0x5F, 0xFA, 0xF8, 0xE7, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x0B, 0x4B, 0x41, 0xF2, 0x1C, 0x32, 0x41, 0xF2, +0x18, 0x31, 0x9A, 0x58, 0x5B, 0x58, 0x72, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x00, 0x22, 0x19, 0x68, 0x58, 0x68, 0x08, 0x60, +0x21, 0x68, 0x02, 0x32, 0x91, 0x42, 0x03, 0xF1, 0x08, 0x03, 0xF6, 0xD8, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, +0x00, 0x40, 0x1E, 0x00, 0x1C, 0x53, 0x1E, 0x00, 0x32, 0x49, 0x33, 0x4B, 0x99, 0x42, 0x10, 0xB5, 0x0C, 0xD2, 0x01, 0x3B, +0x5B, 0x1A, 0x31, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0B, +0x9A, 0x42, 0xF9, 0xD1, 0x2C, 0x4A, 0x2D, 0x4B, 0x9A, 0x42, 0x0A, 0xD2, 0x01, 0x3B, 0x9B, 0x1A, 0x23, 0xF0, 0x03, 0x03, +0x04, 0x33, 0x13, 0x44, 0x00, 0x21, 0x42, 0xF8, 0x04, 0x1B, 0x9A, 0x42, 0xFB, 0xD1, 0x27, 0x49, 0x27, 0x4B, 0x99, 0x42, +0x0D, 0xD2, 0x01, 0x3B, 0x5B, 0x1A, 0x26, 0x4A, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x13, 0x44, 0x08, 0x46, 0x52, 0xF8, +0x04, 0x4B, 0x40, 0xF8, 0x04, 0x4B, 0x9A, 0x42, 0xF9, 0xD1, 0x21, 0x4A, 0x21, 0x48, 0xD2, 0xF8, 0x88, 0x30, 0x43, 0xF4, +0x70, 0x03, 0xC2, 0xF8, 0x88, 0x30, 0x91, 0x60, 0x00, 0x23, 0xFF, 0x21, 0xC2, 0x18, 0x01, 0x33, 0x50, 0x2B, 0x82, 0xF8, +0x00, 0x13, 0xF9, 0xD1, 0x1A, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x80, 0x6F, 0x16, 0x4B, 0x1B, 0x68, 0x4F, 0xF6, 0xF0, 0x72, +0x03, 0xEA, 0x02, 0x03, 0x0D, 0xD0, 0x4C, 0xF2, 0x40, 0x22, 0x93, 0x42, 0x0D, 0xD0, 0x14, 0x4C, 0xF5, 0xF7, 0xBC, 0xFC, +0xD4, 0xF8, 0x7C, 0x34, 0x98, 0x47, 0xD4, 0xF8, 0x74, 0x34, 0x98, 0x47, 0xFE, 0xE7, 0x4D, 0xF2, 0x10, 0x22, 0x93, 0x42, +0xF1, 0xD1, 0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xED, 0xE7, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x5C, 0x25, 0x17, 0x00, +0x2C, 0xD2, 0x15, 0x00, 0x60, 0x25, 0x17, 0x00, 0x28, 0x07, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x80, 0x01, 0x17, 0x00, +0x00, 0x00, 0x12, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x00, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x68, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x72, 0x4F, 0x73, 0x4E, 0x86, 0xB0, 0x3D, 0x46, 0x00, 0x24, 0x21, 0x46, +0x55, 0xF8, 0x04, 0x2B, 0x30, 0x46, 0x01, 0x34, 0xF9, 0xF7, 0x6A, 0xFD, 0x0D, 0x2C, 0xF6, 0xD1, 0xD7, 0xE9, 0x11, 0x21, +0x3B, 0x6C, 0x6C, 0x4D, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x21, 0x6B, 0x48, 0x79, 0x6B, 0xD7, 0xE9, 0x0E, 0x23, 0xF9, 0xF7, +0x5B, 0xFD, 0x29, 0x68, 0x6A, 0x68, 0xAB, 0x68, 0xE8, 0x68, 0x00, 0x90, 0x66, 0x48, 0xF9, 0xF7, 0x53, 0xFD, 0x69, 0x6A, +0xAA, 0x6A, 0xEB, 0x6A, 0x28, 0x6B, 0xEC, 0x6B, 0xCD, 0xE9, 0x00, 0x04, 0x62, 0x48, 0xF9, 0xF7, 0x49, 0xFD, 0xAC, 0x6A, +0x14, 0xF0, 0xFF, 0x01, 0x68, 0xD1, 0xC4, 0xF3, 0x07, 0x25, 0x14, 0xF4, 0x7F, 0x4F, 0x29, 0x46, 0x44, 0xD1, 0x21, 0x0C, +0x2E, 0xD1, 0xFB, 0x6C, 0x1C, 0x07, 0x23, 0xD5, 0x5A, 0x48, 0xF9, 0xF7, 0x37, 0xFD, 0x3B, 0x6D, 0xD8, 0x07, 0x21, 0xD4, +0x58, 0x48, 0xF9, 0xF7, 0x31, 0xFD, 0xFB, 0x6C, 0x59, 0x07, 0x4C, 0xBF, 0x56, 0x48, 0x57, 0x48, 0xF9, 0xF7, 0x2A, 0xFD, +0x39, 0x6D, 0xEF, 0xF3, 0x10, 0x82, 0xEF, 0xF3, 0x13, 0x83, 0xEF, 0xF3, 0x11, 0x80, 0x00, 0x90, 0x52, 0x48, 0xF9, 0xF7, +0x1F, 0xFD, 0xBC, 0x6C, 0x00, 0x2C, 0x71, 0xD1, 0x7C, 0x6C, 0x00, 0x2C, 0x56, 0xD1, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, +0x4D, 0x48, 0xF9, 0xF7, 0x13, 0xFD, 0xDD, 0xE7, 0x4C, 0x48, 0xF9, 0xF7, 0x0F, 0xFD, 0xDC, 0xE7, 0xC4, 0xF3, 0x40, 0x63, +0xC4, 0xF3, 0x00, 0x60, 0xC4, 0xF3, 0xC0, 0x42, 0x03, 0x93, 0xC4, 0xF3, 0x80, 0x43, 0xCD, 0xE9, 0x01, 0x20, 0x00, 0x93, +0xC4, 0xF3, 0x00, 0x42, 0xC4, 0xF3, 0x40, 0x43, 0x43, 0x48, 0xF9, 0xF7, 0xFB, 0xFC, 0xBC, 0xE7, 0xC4, 0xF3, 0xC0, 0x33, +0xC4, 0xF3, 0x00, 0x30, 0xC4, 0xF3, 0xC0, 0x22, 0x04, 0x93, 0xC4, 0xF3, 0x40, 0x36, 0xC4, 0xF3, 0x80, 0x23, 0xCD, 0xE9, +0x00, 0x32, 0xCD, 0xE9, 0x02, 0x06, 0xC4, 0xF3, 0x40, 0x23, 0x3A, 0x48, 0xC4, 0xF3, 0x00, 0x22, 0xF9, 0xF7, 0xE4, 0xFC, +0x2D, 0x06, 0xA2, 0xD5, 0x2A, 0x4B, 0x37, 0x48, 0x99, 0x6B, 0xF9, 0xF7, 0xDD, 0xFC, 0x9C, 0xE7, 0xC4, 0xF3, 0xC0, 0x16, +0xC4, 0xF3, 0x40, 0x10, 0xC4, 0xF3, 0x00, 0x12, 0xC4, 0xF3, 0xC0, 0x03, 0xCD, 0xE9, 0x02, 0x06, 0xCD, 0xE9, 0x00, 0x32, +0x2F, 0x48, 0xC4, 0xF3, 0x40, 0x03, 0x04, 0xF0, 0x01, 0x02, 0xF9, 0xF7, 0xC9, 0xFC, 0x26, 0x06, 0x81, 0xD5, 0x69, 0x6B, +0x2B, 0x48, 0xF9, 0xF7, 0xC3, 0xFC, 0x7C, 0xE7, 0x2A, 0x48, 0x2B, 0x4F, 0x2B, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, +0xBB, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x06, 0xE0, 0x54, 0xF8, 0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0xB3, 0xFC, 0xA5, 0x42, +0x97, 0xD0, 0x23, 0x07, 0xF6, 0xD1, 0x21, 0x46, 0x38, 0x46, 0xF9, 0xF7, 0xAB, 0xFC, 0xF1, 0xE7, 0x21, 0x48, 0xDF, 0xF8, +0x7C, 0x80, 0x1F, 0x4E, 0x24, 0xF0, 0x0F, 0x04, 0xF9, 0xF7, 0xA2, 0xFC, 0x04, 0xF5, 0x80, 0x75, 0x07, 0xE0, 0x54, 0xF8, +0x04, 0x1B, 0x30, 0x46, 0xF9, 0xF7, 0x9A, 0xFC, 0xA5, 0x42, 0x3F, 0xF4, 0x7B, 0xAF, 0x22, 0x07, 0xF5, 0xD1, 0x21, 0x46, +0x40, 0x46, 0xF9, 0xF7, 0x91, 0xFC, 0xF0, 0xE7, 0xE4, 0x60, 0x17, 0x00, 0xC0, 0x89, 0x15, 0x00, 0x00, 0xED, 0x00, 0xE0, +0xD0, 0x89, 0x15, 0x00, 0x1C, 0x8A, 0x15, 0x00, 0x50, 0x8A, 0x15, 0x00, 0xF0, 0x8B, 0x15, 0x00, 0x10, 0x8C, 0x15, 0x00, +0x34, 0x8C, 0x15, 0x00, 0x40, 0x8C, 0x15, 0x00, 0x4C, 0x8C, 0x15, 0x00, 0x24, 0x8C, 0x15, 0x00, 0x00, 0x8C, 0x15, 0x00, +0x8C, 0x8B, 0x15, 0x00, 0x04, 0x8B, 0x15, 0x00, 0x7C, 0x8B, 0x15, 0x00, 0x90, 0x8A, 0x15, 0x00, 0xF4, 0x8A, 0x15, 0x00, +0x80, 0x8C, 0x15, 0x00, 0xAC, 0x89, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0xA0, 0x89, 0x15, 0x00, 0x08, 0xB5, 0x02, 0x48, +0xF9, 0xF7, 0x60, 0xFC, 0xFE, 0xE7, 0x00, 0xBF, 0x8C, 0x8C, 0x15, 0x00, 0x04, 0x46, 0x08, 0xB5, 0x10, 0x48, 0xF9, 0xF7, +0x57, 0xFC, 0x30, 0x2C, 0x10, 0xD0, 0x40, 0x2C, 0x16, 0xD0, 0x20, 0x2C, 0x10, 0xD0, 0x0D, 0x48, 0xF9, 0xF7, 0x4E, 0xFC, +0x0C, 0x48, 0xF9, 0xF7, 0x4B, 0xFC, 0xFF, 0xF7, 0xD1, 0xFE, 0x0B, 0x48, 0xF9, 0xF7, 0x46, 0xFC, 0xFF, 0xF7, 0xE0, 0xFF, +0x09, 0x48, 0xF9, 0xF7, 0x41, 0xFC, 0xF1, 0xE7, 0x08, 0x48, 0xF9, 0xF7, 0x3D, 0xFC, 0xED, 0xE7, 0x07, 0x48, 0xF9, 0xF7, +0x39, 0xFC, 0xE9, 0xE7, 0x98, 0x8C, 0x15, 0x00, 0xE8, 0x8C, 0x15, 0x00, 0xF4, 0x8C, 0x15, 0x00, 0x00, 0x8D, 0x15, 0x00, +0xD0, 0x8C, 0x15, 0x00, 0xC0, 0x8C, 0x15, 0x00, 0xDC, 0x8C, 0x15, 0x00, 0x4F, 0xF0, 0x10, 0x03, 0x00, 0xF0, 0x0C, 0xB8, +0x4F, 0xF0, 0x20, 0x03, 0x00, 0xF0, 0x08, 0xB8, 0x4F, 0xF0, 0x30, 0x03, 0x00, 0xF0, 0x04, 0xB8, 0x4F, 0xF0, 0x40, 0x03, +0x00, 0xF0, 0x00, 0xB8, 0xEF, 0xF3, 0x08, 0x80, 0x4F, 0xF0, 0x04, 0x01, 0x72, 0x46, 0x0A, 0x42, 0x01, 0xD0, 0xEF, 0xF3, +0x09, 0x80, 0x9C, 0x46, 0x24, 0x49, 0x02, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x42, 0x68, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x68, +0x0A, 0x60, 0x04, 0x31, 0xC2, 0x68, 0x0A, 0x60, 0x04, 0x31, 0xF0, 0xC1, 0x47, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x4F, 0x46, +0x0F, 0x60, 0x04, 0x31, 0x57, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x5F, 0x46, 0x0F, 0x60, 0x04, 0x31, 0x02, 0x69, 0x0A, 0x60, +0x08, 0x31, 0x42, 0x69, 0x0A, 0x60, 0x04, 0x31, 0x82, 0x69, 0x0A, 0x60, 0x04, 0x31, 0xC2, 0x69, 0x0A, 0x60, 0x04, 0x31, +0x03, 0x46, 0x20, 0x33, 0x4F, 0xF4, 0x00, 0x76, 0x32, 0x42, 0x00, 0xD0, 0x04, 0x33, 0x75, 0x46, 0x4F, 0xF0, 0x10, 0x06, +0x35, 0x42, 0x00, 0xD1, 0x48, 0x33, 0x0C, 0x46, 0x10, 0x3C, 0x23, 0x60, 0xEF, 0xF3, 0x09, 0x82, 0x0A, 0x60, 0x04, 0x31, +0xEF, 0xF3, 0x08, 0x82, 0x0A, 0x60, 0x04, 0x31, 0x72, 0x46, 0x0A, 0x60, 0x04, 0x31, 0xEF, 0xF3, 0x14, 0x82, 0x0A, 0x60, +0x03, 0x4B, 0x60, 0x46, 0x01, 0x49, 0x98, 0x47, 0xFE, 0xE7, 0x00, 0x00, 0xE4, 0x60, 0x17, 0x00, 0x3D, 0xCA, 0x12, 0x00, +0x08, 0xB5, 0x08, 0x4B, 0x00, 0x22, 0x5A, 0x70, 0x18, 0xF0, 0x3E, 0xF8, 0x1A, 0xF0, 0x14, 0xFC, 0x05, 0x4B, 0xD3, 0xF8, +0xA8, 0x31, 0x98, 0x47, 0x16, 0xF0, 0x88, 0xFB, 0xBD, 0xE8, 0x08, 0x40, 0x18, 0xF0, 0x42, 0xB8, 0x70, 0x28, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x4B, 0x4E, 0x4C, 0x4A, 0x4C, 0x49, 0x4D, 0x48, 0x17, 0xF0, 0x6E, 0xFD, +0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0x40, 0xF0, 0x89, 0x80, 0x62, 0xB6, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, +0xDF, 0xF8, 0x3C, 0x81, 0xDF, 0xF8, 0x3C, 0x91, 0x45, 0x4D, 0x46, 0x4F, 0x46, 0x4C, 0xDF, 0xF8, 0x38, 0xB1, 0x4F, 0xF0, +0x01, 0x0A, 0x33, 0x68, 0xDB, 0x78, 0xFB, 0xB9, 0x98, 0xF8, 0x00, 0x30, 0x13, 0xB3, 0x18, 0xF0, 0x71, 0xFE, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC9, 0xF8, 0x00, 0xA0, 0x2B, 0x68, 0x3A, 0x68, 0x01, 0x33, 0x2B, 0x60, +0xBA, 0xB1, 0x00, 0x2B, 0xE9, 0xD0, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x00, 0x2B, 0xE3, 0xD1, 0x00, 0x2A, +0xE1, 0xD0, 0x62, 0xB6, 0x33, 0x68, 0xDB, 0x78, 0x00, 0x2B, 0xDF, 0xD0, 0xFF, 0xF7, 0x2C, 0xFD, 0x98, 0xF8, 0x00, 0x30, +0x00, 0x2B, 0xDC, 0xD1, 0x16, 0xF0, 0xF8, 0xFA, 0xD9, 0xE7, 0xD4, 0xF8, 0x7C, 0x32, 0x98, 0x47, 0x33, 0x68, 0xDB, 0x78, +0x00, 0x2B, 0x37, 0xD1, 0xDB, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x01, 0x2B, 0x17, 0xD0, 0xBF, 0xF3, 0x4F, 0x8F, 0x30, 0xBF, +0xBF, 0xF3, 0x6F, 0x8F, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0xD4, 0xF8, 0x78, 0x32, 0x98, 0x47, 0x00, 0x28, +0xF1, 0xD0, 0x33, 0x68, 0xDB, 0x78, 0x23, 0xBB, 0xD4, 0xF8, 0x84, 0x32, 0x98, 0x47, 0x2B, 0x68, 0x00, 0x2B, 0xB0, 0xD0, +0xC5, 0xE7, 0x1D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE3, 0xD0, 0x1C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x17, 0xD0, +0x01, 0x2B, 0x05, 0xD0, 0x00, 0x2B, 0xDA, 0xD1, 0x18, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD6, 0xD0, 0x17, 0x4B, 0x5B, 0x78, +0x00, 0x2B, 0xD2, 0xD0, 0x16, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, 0x13, 0x60, 0xCC, 0xE7, 0xFF, 0xF7, 0xEA, 0xFC, +0xC4, 0xE7, 0xFF, 0xF7, 0xEF, 0xFC, 0xD7, 0xE7, 0xFB, 0xF7, 0x32, 0xFE, 0x00, 0x28, 0xEF, 0xD1, 0x0B, 0x4B, 0x1B, 0x68, +0x1B, 0x78, 0xDF, 0xE7, 0x10, 0x20, 0xFF, 0xF7, 0xB1, 0xFC, 0x72, 0xE7, 0x34, 0x36, 0x17, 0x00, 0xDC, 0xD1, 0x15, 0x00, +0x00, 0xD2, 0x15, 0x00, 0x1C, 0x8D, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x3D, 0x61, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, 0x70, 0x28, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, +0x3C, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xEF, 0xF3, 0x10, 0x83, +0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x72, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x71, 0x4C, 0x72, 0x4A, 0x23, 0x68, 0x72, 0x49, +0x72, 0x4D, 0x01, 0x33, 0x4F, 0xF4, 0x80, 0x60, 0x23, 0x60, 0x17, 0xF0, 0xF9, 0xFC, 0x4F, 0xF0, 0x00, 0x40, 0x16, 0xF0, +0x4D, 0xFA, 0xD5, 0xF8, 0xEC, 0x30, 0x98, 0x47, 0x6C, 0x4B, 0x6D, 0x4A, 0x19, 0x68, 0x21, 0xF0, 0x7F, 0x41, 0x19, 0x60, +0x19, 0x68, 0x41, 0xF0, 0x10, 0x01, 0x19, 0x60, 0x11, 0x69, 0x64, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, +0x66, 0x4E, 0xD5, 0xF8, 0x10, 0x24, 0x33, 0x68, 0x40, 0xF2, 0x11, 0x17, 0x3B, 0x43, 0x33, 0x60, 0x90, 0x47, 0x60, 0x49, +0x62, 0x4A, 0x0B, 0x68, 0xDF, 0xF8, 0xAC, 0xC1, 0x23, 0xF0, 0x10, 0x03, 0x0B, 0x60, 0x33, 0x68, 0x23, 0xF4, 0x88, 0x73, +0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x0B, 0x23, 0x10, 0x68, 0x13, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDB, 0x06, 0x18, 0xD5, +0x59, 0x4B, 0x40, 0xF2, 0x01, 0x2C, 0x19, 0x68, 0xC3, 0xF8, 0x00, 0xC0, 0x19, 0x60, 0x33, 0x68, 0xA2, 0xF5, 0x7C, 0x72, +0x1F, 0x43, 0x37, 0x60, 0x11, 0x68, 0x02, 0x31, 0x13, 0x68, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x4E, 0x4A, 0x13, 0x68, +0x23, 0xF4, 0x88, 0x73, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x4C, 0x4B, 0x18, 0x60, 0x0A, 0xF0, 0xBD, 0xFF, 0x00, 0x20, +0x16, 0xF0, 0x8E, 0xF8, 0x00, 0x28, 0x6C, 0xD0, 0x49, 0x4E, 0x09, 0xF0, 0xA1, 0xFB, 0xB3, 0x79, 0x00, 0x2B, 0x4F, 0xD0, +0x47, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x66, 0xD0, 0x33, 0x78, 0x00, 0x2B, 0x47, 0xD0, 0x44, 0x4B, 0x77, 0x79, +0x1A, 0x68, 0x96, 0xF9, 0x07, 0x30, 0x96, 0xF9, 0x04, 0xE0, 0xDF, 0xF8, 0x20, 0xC1, 0x41, 0x48, 0xDC, 0xF8, 0x00, 0x10, +0xD5, 0xF8, 0xE0, 0x81, 0x37, 0x4D, 0x02, 0xF0, 0x0F, 0x02, 0x17, 0x44, 0x7F, 0xB2, 0x3B, 0x44, 0x73, 0x45, 0xA8, 0xBF, +0x73, 0x46, 0x5F, 0xFA, 0x83, 0xFE, 0x21, 0xF0, 0xFF, 0x01, 0x41, 0xEA, 0x0E, 0x01, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, +0x22, 0xF0, 0xFF, 0x02, 0x42, 0xEA, 0x0E, 0x02, 0x02, 0x60, 0xDC, 0xF8, 0x00, 0x10, 0xDA, 0x1E, 0x5F, 0xFA, 0x82, 0xFE, +0x21, 0xF4, 0x7F, 0x21, 0x41, 0xEA, 0x0E, 0x31, 0xCC, 0xF8, 0x00, 0x10, 0x02, 0x68, 0xB6, 0xF8, 0x08, 0xC0, 0x22, 0xF4, +0x7F, 0x22, 0x42, 0xEA, 0x0E, 0x32, 0x02, 0x60, 0x2A, 0x69, 0x2A, 0x48, 0x5D, 0xB2, 0x4E, 0xF6, 0x60, 0x21, 0x01, 0xFB, +0x0C, 0x21, 0xF5, 0x71, 0xC0, 0x47, 0x00, 0x23, 0x26, 0x48, 0xB3, 0x71, 0x29, 0x46, 0x3A, 0x46, 0x17, 0xF0, 0xFC, 0xFB, +0x24, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x17, 0xF0, 0x47, 0xFC, 0x08, 0xF0, 0x85, 0xFE, 0x18, 0xB1, 0x4F, 0xF4, 0x80, 0x10, +0x16, 0xF0, 0x74, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x0D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF0, 0x80, 0x60, 0x16, 0xF0, 0x89, 0xF9, 0x8D, 0xE7, 0x17, 0x4B, 0x1B, 0x68, +0x00, 0x22, 0x1A, 0x60, 0xF8, 0xF7, 0x8C, 0xFA, 0x33, 0x78, 0x00, 0x2B, 0xDA, 0xD0, 0xB3, 0x79, 0x00, 0x2B, 0x8F, 0xD1, +0xD6, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x30, 0x8E, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x00, 0x04, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x18, 0x00, 0x34, 0x40, 0x10, 0x05, 0x32, 0x40, +0x00, 0x10, 0x34, 0x40, 0x80, 0x35, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x01, 0x32, 0x40, 0xD4, 0xB3, 0x33, 0x40, +0x8C, 0x35, 0x17, 0x00, 0x30, 0x8D, 0x15, 0x00, 0x40, 0x8D, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0x0C, 0x05, 0x32, 0x40, +0xAC, 0xB3, 0x33, 0x40, 0x22, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x20, 0x4B, +0xD3, 0xF8, 0x04, 0x31, 0x1A, 0x03, 0x10, 0xB5, 0x16, 0xD4, 0x00, 0x22, 0x93, 0x00, 0x03, 0xF1, 0x60, 0x43, 0x03, 0xF5, +0x61, 0x43, 0x01, 0x2A, 0xD3, 0xF8, 0x00, 0x01, 0x1B, 0x68, 0x00, 0xEA, 0x03, 0x00, 0x04, 0xD0, 0x30, 0xB9, 0x02, 0x2A, +0x05, 0xD0, 0x01, 0x32, 0xEE, 0xE7, 0x30, 0xF4, 0x00, 0x23, 0xFA, 0xD0, 0x01, 0x20, 0x10, 0xBD, 0x12, 0x4B, 0x1C, 0x68, +0x41, 0xF6, 0x33, 0x70, 0x20, 0x40, 0xF7, 0xD1, 0x63, 0x00, 0x0F, 0xD4, 0x00, 0x2C, 0x07, 0xDA, 0x0E, 0x4B, 0xD3, 0xF8, +0x68, 0x34, 0x98, 0x47, 0x0D, 0x4B, 0x4F, 0xF0, 0x00, 0x42, 0x1A, 0x60, 0x08, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0xC3, 0xF8, +0x84, 0x21, 0xD0, 0xE7, 0x07, 0x4B, 0xD3, 0xF8, 0x78, 0x34, 0x98, 0x47, 0x06, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x1A, 0x60, +0xE6, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x00, 0xE1, 0x00, 0xE0, 0x1C, 0x41, 0x04, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x08, 0x41, 0x04, 0x40, 0x38, 0xB5, 0x3F, 0x4C, 0x3F, 0x4D, 0x23, 0x68, 0x3F, 0x49, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x20, +0x2B, 0x70, 0x17, 0xF0, 0x9F, 0xFB, 0x23, 0x68, 0x18, 0x07, 0x40, 0xD0, 0x3B, 0x49, 0x3C, 0x4A, 0x0B, 0x68, 0x00, 0x20, +0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x59, 0x07, 0xFC, 0xD5, 0x38, 0x4B, 0x35, 0x49, 0x38, 0x4A, +0x04, 0x20, 0x18, 0x60, 0x0B, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x63, 0x13, 0x60, +0x33, 0x4B, 0x1B, 0x78, 0x01, 0x22, 0x6A, 0x70, 0x9B, 0xB1, 0x32, 0x49, 0x32, 0x4A, 0x0B, 0x68, 0x23, 0xF4, 0x00, 0x13, +0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, 0x19, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, +0x01, 0x20, 0x41, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x10, 0x60, 0x20, 0x4B, 0x2A, 0x4A, 0x2B, 0x49, 0x20, 0x20, 0x18, 0x60, +0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x0B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x26, 0xD0, 0x01, 0x2B, 0x06, 0xD0, +0x38, 0xBD, 0x1E, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x63, 0x13, 0x60, 0xD0, 0xE7, 0x22, 0x4A, 0x13, 0x68, 0x5B, 0x03, +0xFC, 0xD5, 0x21, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0xFB, 0xDA, 0x1E, 0x49, 0x1F, 0x4A, +0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, 0x23, 0xF0, +0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x38, 0xBD, 0x17, 0x4B, 0x1A, 0x68, 0x42, 0xF0, +0x01, 0x02, 0x1A, 0x60, 0x1B, 0x68, 0x5A, 0x07, 0xD2, 0xD5, 0x14, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x38, 0xBD, +0x38, 0x00, 0x32, 0x40, 0x70, 0x28, 0x17, 0x00, 0x50, 0x8D, 0x15, 0x00, 0x74, 0x80, 0x32, 0x40, 0x6C, 0x80, 0x32, 0x40, +0x70, 0x80, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, 0x3D, 0x61, 0x17, 0x00, 0x58, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, +0x18, 0x00, 0x58, 0x40, 0x10, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x20, 0x10, 0x04, 0x40, 0x00, 0x10, 0x50, 0x40, +0x14, 0x00, 0x24, 0x40, 0x00, 0x60, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x00, 0x28, 0x00, 0xF0, +0xE7, 0x80, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x64, 0x30, 0x04, 0x46, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x8F, 0x83, 0x4B, +0x83, 0x4A, 0x84, 0x4F, 0xDF, 0xF8, 0x2C, 0x92, 0xDF, 0xF8, 0x64, 0x82, 0x82, 0x4E, 0x83, 0x48, 0x0D, 0x46, 0x83, 0x49, +0x4F, 0xF0, 0x02, 0x0B, 0xD1, 0xF8, 0x70, 0xC4, 0xC3, 0xF8, 0x80, 0xB1, 0x92, 0x68, 0x80, 0x49, 0xC2, 0xF8, 0x44, 0xC0, +0x01, 0x22, 0xC3, 0xF8, 0x00, 0xB0, 0x3A, 0x70, 0xD9, 0xF8, 0x10, 0x20, 0x0B, 0x68, 0x7A, 0x60, 0x23, 0xF0, 0x02, 0x03, +0x0B, 0x60, 0xD8, 0xF8, 0x00, 0x10, 0xB6, 0xF8, 0xB2, 0xC0, 0x8B, 0x8F, 0x01, 0x68, 0x63, 0x44, 0xB3, 0xEB, 0x41, 0x1F, +0x4F, 0xEA, 0x41, 0x1A, 0xD1, 0xD2, 0x74, 0x49, 0x58, 0x46, 0x17, 0xF0, 0xC9, 0xFA, 0xD9, 0xF8, 0x10, 0x20, 0xFB, 0x68, +0x9B, 0x1A, 0x00, 0x2B, 0x80, 0xF2, 0xB6, 0x80, 0xB4, 0xF8, 0x68, 0x20, 0x6E, 0x4B, 0xA8, 0x68, 0x41, 0xF2, 0x13, 0x31, +0x01, 0x2A, 0x5C, 0x5C, 0x40, 0xF2, 0x9F, 0x80, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x41, 0xF2, 0x13, 0x31, 0x52, 0x46, +0x5B, 0x5C, 0x68, 0x49, 0x02, 0x20, 0x17, 0xF0, 0xAD, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB6, 0xF8, 0xB2, 0x00, 0x9A, 0x8F, +0x60, 0x49, 0x64, 0x4B, 0xDF, 0xF8, 0xA8, 0xC1, 0x1C, 0x69, 0x0B, 0x68, 0x02, 0x44, 0xAA, 0xEB, 0x02, 0x02, 0x22, 0xF0, +0x03, 0x05, 0x03, 0xF0, 0x03, 0x03, 0x2B, 0x43, 0x5E, 0x4D, 0x0B, 0x60, 0x2B, 0x68, 0xBA, 0x60, 0x43, 0xF0, 0x01, 0x03, +0x2B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0xDC, 0xF8, 0x00, 0x10, 0xC3, 0xF3, 0x09, 0x03, 0x21, 0xF4, 0x7F, 0x71, 0x43, 0xF0, +0x01, 0x03, 0x21, 0xF0, 0x03, 0x01, 0x0B, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x22, 0x44, 0x5B, 0x07, 0xFA, 0x60, +0x03, 0xD5, 0x52, 0x4B, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0x51, 0x49, 0x51, 0x4A, 0x0B, 0x68, 0x43, 0xF0, 0x08, 0x03, +0x0B, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x4E, 0x4C, 0x45, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x23, 0x60, +0x01, 0x23, 0x13, 0x60, 0x0B, 0x68, 0x45, 0x4A, 0x43, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x11, 0x69, 0x01, 0xF5, 0x96, 0x71, +0x13, 0x69, 0x5B, 0x1A, 0x00, 0x2B, 0xFB, 0xDB, 0x45, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x7F, 0xF4, 0x5D, 0xAF, +0x43, 0x49, 0x44, 0x4C, 0x4B, 0x6A, 0x24, 0x68, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0xDF, 0x03, 0x4B, 0x62, 0x4B, 0x6A, +0x23, 0xF4, 0x7F, 0x43, 0x43, 0xF4, 0x5F, 0x43, 0x4B, 0x62, 0xB4, 0xB1, 0x3D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x3F, 0xDB, 0xE3, 0x68, 0x62, 0x68, 0x3A, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x3C, 0xFA, 0xB6, 0xF8, 0xB2, 0x10, +0xE2, 0x68, 0x2D, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x99, 0x60, 0x34, 0x49, +0x2F, 0x4A, 0x0B, 0x68, 0x43, 0xF4, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x6D, 0x43, 0xF4, 0x00, 0x43, 0x13, 0x65, 0xD3, 0x6D, +0x23, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xD3, 0x65, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x53, +0x13, 0x60, 0x1E, 0xE7, 0x70, 0x47, 0x41, 0xF2, 0x14, 0x32, 0x9C, 0x5C, 0x01, 0x2C, 0x7F, 0xF6, 0x5E, 0xAF, 0x5C, 0x5C, +0xDC, 0xB1, 0x5A, 0x5C, 0x01, 0x3A, 0x00, 0xFB, 0x02, 0xAA, 0x56, 0xE7, 0x14, 0x4A, 0x22, 0x49, 0x41, 0xF2, 0x13, 0x33, +0x58, 0x46, 0xD3, 0x5C, 0x52, 0x46, 0x17, 0xF0, 0x03, 0xFA, 0x54, 0xE7, 0x12, 0x69, 0xE3, 0x68, 0x9A, 0x1A, 0x10, 0x1A, +0x00, 0x28, 0xBA, 0xDA, 0x1B, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x4F, 0x22, 0x17, 0xF0, 0x20, 0xFC, 0xB2, 0xE7, 0x9A, 0x5C, +0x3A, 0xE7, 0x00, 0xBF, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0xED, 0x00, 0xE0, 0x3C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, +0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x84, 0x00, 0x32, 0x40, 0x54, 0x8D, 0x15, 0x00, 0x00, 0x40, 0x1E, 0x00, +0x70, 0x8D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x84, 0x40, 0x04, 0x40, 0x00, 0x41, 0x04, 0x40, 0x10, 0x00, 0x58, 0x40, +0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x78, 0x36, 0x17, 0x00, 0x00, 0x60, 0x50, 0x40, 0xD0, 0x9C, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0xC8, 0x8D, 0x15, 0x00, 0x14, 0x00, 0x24, 0x40, 0x5C, 0x8D, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, +0x80, 0x8D, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x70, 0xB5, 0x45, 0x4C, 0x21, 0x68, 0x0B, 0x78, 0x73, 0xB9, 0x44, 0x4B, +0x44, 0x4D, 0x9B, 0x68, 0x01, 0x22, 0x2A, 0x70, 0x00, 0x2B, 0x3E, 0xD1, 0x0A, 0x78, 0x42, 0x49, 0x01, 0x23, 0x02, 0x20, +0x17, 0xF0, 0xAC, 0xF9, 0x01, 0x23, 0x2B, 0x70, 0x3F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x40, 0xD0, 0x02, 0x2B, +0x28, 0xD0, 0x11, 0xF0, 0x8F, 0xFD, 0x28, 0xB3, 0x3B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x0B, 0xBB, 0x3A, 0x4B, 0x3B, 0x4D, +0x1B, 0x68, 0x95, 0xF8, 0x24, 0x20, 0xC3, 0xF3, 0x40, 0x63, 0x13, 0x43, 0x18, 0xD0, 0x6B, 0x7F, 0xB3, 0xB9, 0x37, 0x4E, +0xD6, 0xF8, 0xF4, 0x30, 0x98, 0x47, 0x88, 0xB1, 0xF8, 0xF7, 0x7E, 0xFB, 0x34, 0x4A, 0xC0, 0xB2, 0x10, 0x70, 0x00, 0x28, +0x35, 0xD0, 0x23, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD8, 0xD6, 0xF8, 0xB4, 0x34, 0x98, 0x47, 0x23, 0x68, 0x1B, 0x78, +0x02, 0x2B, 0x22, 0xD0, 0x70, 0xBD, 0x93, 0xF8, 0x64, 0x20, 0x42, 0xB9, 0x1B, 0x68, 0x00, 0x2B, 0xC0, 0xD0, 0x93, 0xF8, +0x62, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x02, 0x2A, 0xF6, 0xD1, 0x0A, 0x78, 0x1F, 0x49, 0x00, 0x23, 0x02, 0x20, 0x17, 0xF0, +0x67, 0xF9, 0x00, 0x23, 0x2B, 0x70, 0x70, 0xBD, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x15, 0xD0, 0xFB, 0xF7, 0x5A, 0xFA, +0x00, 0x28, 0xE1, 0xD0, 0x1E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xB4, 0xD0, 0x70, 0xBD, 0x28, 0x6A, 0xD6, 0xF8, 0xB8, 0x34, +0xD0, 0xF8, 0xE4, 0x10, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x49, 0x02, 0x20, 0x17, 0xF0, 0x4B, 0xF9, 0xC4, 0xE7, +0xF8, 0xF7, 0x3C, 0xFB, 0x13, 0x4B, 0x18, 0x70, 0xFB, 0xF7, 0x40, 0xFA, 0x18, 0xB1, 0x10, 0x4B, 0xD3, 0xF8, 0xB4, 0x34, +0x98, 0x47, 0x12, 0x4A, 0x13, 0x68, 0x5B, 0x03, 0xFC, 0xD5, 0x11, 0x4A, 0x11, 0x69, 0x1C, 0x31, 0x13, 0x69, 0xCB, 0x1A, +0x00, 0x2B, 0xFB, 0xDA, 0x70, 0xBD, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x3C, 0x61, 0x17, 0x00, +0xD8, 0x8D, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x3D, 0x61, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, 0xD4, 0x8D, 0x15, 0x00, 0x20, 0x10, 0x04, 0x40, +0x00, 0x10, 0x50, 0x40, 0x38, 0xB5, 0x43, 0x4D, 0x6B, 0x78, 0x03, 0xB9, 0x38, 0xBD, 0x42, 0x48, 0x42, 0x49, 0x03, 0x68, +0x42, 0x4A, 0x23, 0xF0, 0x10, 0x03, 0x03, 0x60, 0x4B, 0x6F, 0x43, 0xF0, 0x10, 0x03, 0x4B, 0x67, 0x13, 0x68, 0x23, 0xF0, +0x00, 0x73, 0x13, 0x60, 0x00, 0xBF, 0x00, 0xBF, 0x00, 0xBF, 0x3C, 0x4C, 0x3C, 0x49, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x43, +0x23, 0x60, 0x02, 0x20, 0x17, 0xF0, 0xF6, 0xF8, 0x00, 0x23, 0x22, 0x46, 0x6B, 0x70, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD5, +0x36, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3C, 0xDB, 0x31, 0x4B, 0x34, 0x4A, 0x19, 0x68, 0x21, 0xF0, +0x80, 0x41, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x2F, 0x4B, +0x2F, 0x48, 0x19, 0x68, 0x2F, 0x4C, 0x41, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x01, 0x25, 0x21, 0xF0, 0x02, 0x01, +0x19, 0x60, 0x15, 0x60, 0x03, 0x68, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, 0x23, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x2E, 0xD0, +0x01, 0x2B, 0x26, 0xD0, 0x26, 0x4B, 0x1B, 0x78, 0x53, 0xB1, 0x1D, 0x4A, 0x25, 0x49, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x73, +0x13, 0x60, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xB8, 0xB8, 0x16, 0x4A, 0x20, 0x49, 0x53, 0x6F, 0x23, 0xF0, +0x10, 0x03, 0x53, 0x67, 0x02, 0x20, 0xBD, 0xE8, 0x38, 0x40, 0x17, 0xF0, 0xAD, 0xB8, 0x1C, 0x4B, 0x2A, 0x78, 0x1B, 0x68, +0x03, 0xF0, 0x0F, 0x03, 0x9A, 0x42, 0xBB, 0xD0, 0x19, 0x49, 0x1A, 0x48, 0x4F, 0xF4, 0x3A, 0x72, 0x17, 0xF0, 0xCA, 0xFA, +0xB4, 0xE7, 0x18, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x43, 0x13, 0x60, 0xD2, 0xE7, 0x16, 0x4A, 0x13, 0x68, 0x23, 0xF0, +0x01, 0x03, 0x13, 0x60, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xCC, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x70, 0x28, 0x17, 0x00, +0x10, 0x00, 0x58, 0x40, 0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x48, 0x80, 0x32, 0x40, 0xEC, 0x8D, 0x15, 0x00, +0x38, 0x36, 0x17, 0x00, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0x78, 0x36, 0x17, 0x00, +0x4C, 0x36, 0x17, 0x00, 0x28, 0x8E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x8D, 0x15, 0x00, +0x14, 0x00, 0x24, 0x40, 0x84, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x48, 0x20, 0x4D, 0x15, 0xF0, 0x36, 0xFE, +0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4E, 0x28, 0x68, 0xDF, 0xF8, 0x7C, 0x90, +0xDF, 0xF8, 0x60, 0x80, 0xD9, 0xF8, 0x00, 0x30, 0x1A, 0x89, 0x54, 0x24, 0x02, 0xFB, 0x04, 0x42, 0x00, 0x21, 0xF2, 0xF7, +0x91, 0xFD, 0x4F, 0xF0, 0x00, 0x0A, 0x58, 0x27, 0x29, 0x68, 0x33, 0x68, 0x1F, 0xFA, 0x8A, 0xF2, 0x04, 0xFB, 0x02, 0x11, +0x07, 0xFB, 0x02, 0x33, 0xCB, 0x64, 0x40, 0x46, 0x15, 0xF0, 0x16, 0xFE, 0xD9, 0xF8, 0x00, 0x30, 0x0A, 0xF1, 0x01, 0x0A, +0x1A, 0x89, 0x1F, 0xFA, 0x8A, 0xF3, 0x9A, 0x42, 0xEA, 0xD2, 0xBD, 0xE8, 0xF0, 0x87, 0x28, 0x68, 0x08, 0x4E, 0x10, 0xB1, +0x33, 0x68, 0x00, 0x2B, 0xD2, 0xD1, 0x07, 0x48, 0x07, 0x49, 0x5B, 0x22, 0x17, 0xF0, 0x54, 0xFA, 0x28, 0x68, 0xCB, 0xE7, +0x20, 0x58, 0x17, 0x00, 0x40, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x14, 0x63, 0x18, 0x00, 0x40, 0x8E, 0x15, 0x00, +0x70, 0x79, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0x0D, 0x49, 0x00, 0xEB, 0xC0, 0x03, 0x10, 0xB4, 0x9C, 0x00, 0x00, 0x22, +0x01, 0xEB, 0x83, 0x03, 0x16, 0x30, 0x0A, 0x51, 0x01, 0xEB, 0xC0, 0x00, 0x4F, 0xF4, 0x55, 0x64, 0x4F, 0xF0, 0xFF, 0x31, +0xC3, 0xE9, 0x02, 0x41, 0xC0, 0xE9, 0x01, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x5A, 0x60, 0x83, 0xF8, 0x20, 0x20, 0x5A, 0x61, +0x19, 0x61, 0x70, 0x47, 0x44, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, 0xF9, 0xF7, 0xCE, 0xFE, +0x00, 0x23, 0xA3, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, 0x38, 0x4C, 0xDF, 0xF8, 0xF0, 0x80, 0x38, 0x4F, +0x38, 0x4D, 0x04, 0xF5, 0x20, 0x76, 0xC4, 0xF8, 0x00, 0x80, 0xF3, 0xF7, 0x0F, 0xFE, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, +0x0B, 0xFE, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, 0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, +0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x27, 0x61, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, +0x63, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xA3, 0x62, 0x2B, 0x68, 0x2A, 0x68, +0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0xE3, 0x62, 0x2B, 0x68, 0x2A, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, +0x13, 0x43, 0x4F, 0xF4, 0x08, 0x51, 0x4F, 0xF4, 0x7C, 0x12, 0xA2, 0x63, 0xC4, 0xE9, 0x0C, 0x31, 0x40, 0x34, 0xB4, 0x42, +0xC5, 0xD1, 0x1B, 0x4C, 0x1B, 0x4F, 0x18, 0x4E, 0xDF, 0xF8, 0x60, 0x80, 0x04, 0xF5, 0x80, 0x75, 0x27, 0x60, 0xF3, 0xF7, +0xCF, 0xFD, 0x80, 0x03, 0x60, 0x60, 0xF3, 0xF7, 0xCB, 0xFD, 0x01, 0x23, 0x01, 0x30, 0x03, 0xFA, 0x00, 0xF0, 0x01, 0x38, +0x00, 0x23, 0xC4, 0xE9, 0x02, 0x03, 0xC4, 0xE9, 0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x26, 0x61, 0xD8, 0xF8, 0x00, 0x20, +0xD8, 0xF8, 0x00, 0x10, 0xA3, 0x62, 0x12, 0x02, 0xC9, 0xB2, 0x92, 0xB2, 0x0A, 0x43, 0x4F, 0xF4, 0x7C, 0x11, 0x62, 0x62, +0xC4, 0xE9, 0x0B, 0x33, 0xC4, 0xE9, 0x0D, 0x31, 0x40, 0x34, 0xAC, 0x42, 0xD8, 0xD1, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, +0x04, 0x39, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xA0, 0x00, 0x32, 0x40, 0x04, 0x38, 0x18, 0x00, 0x1E, 0xAB, 0xDC, 0xBA, +0xF0, 0xB5, 0x16, 0x4C, 0x24, 0x68, 0x24, 0x78, 0x1D, 0x46, 0xE3, 0x07, 0x87, 0xB0, 0x16, 0x46, 0x06, 0xD5, 0x50, 0x19, +0x00, 0x21, 0x08, 0x22, 0xF2, 0xF7, 0xA8, 0xFC, 0x07, 0xB0, 0xF0, 0xBD, 0xC3, 0x7E, 0x00, 0x93, 0x02, 0xAC, 0x07, 0x46, +0x07, 0xF1, 0x12, 0x03, 0x20, 0x46, 0x07, 0xF1, 0x0C, 0x02, 0x1A, 0xF0, 0xE7, 0xFF, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, +0x1B, 0xF0, 0x08, 0xF8, 0x20, 0x46, 0x1B, 0xF0, 0xA3, 0xF8, 0x35, 0x44, 0x21, 0x46, 0x04, 0xAA, 0x60, 0x1A, 0x14, 0xF8, +0x01, 0x3B, 0x43, 0x55, 0x94, 0x42, 0xF9, 0xD1, 0x07, 0xB0, 0xF0, 0xBD, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x83, 0x6C, 0x90, 0xF8, 0x42, 0xA0, 0x90, 0xF8, 0x33, 0x40, 0x90, 0xF8, 0x35, 0x20, 0x87, 0x88, 0x90, 0xF8, 0x32, 0x80, +0xD3, 0xF8, 0x24, 0xC0, 0xC6, 0x6C, 0x93, 0xF8, 0x20, 0xE0, 0xA3, 0xEB, 0x0A, 0x05, 0xA8, 0x35, 0x22, 0x44, 0x01, 0x3F, +0xAA, 0xEB, 0x04, 0x04, 0x3A, 0x44, 0x08, 0xEB, 0x05, 0x09, 0x2C, 0xF0, 0x02, 0x07, 0x04, 0xEB, 0x09, 0x0B, 0x5F, 0x62, +0x54, 0x19, 0x03, 0xF1, 0x0C, 0x0A, 0xB8, 0xF1, 0x00, 0x0F, 0x03, 0xD0, 0x09, 0xF1, 0xFF, 0x32, 0xC6, 0xE9, 0x09, 0x52, +0xF2, 0x6C, 0xC3, 0xF8, 0x14, 0xB0, 0x00, 0x25, 0x42, 0xF4, 0x80, 0x72, 0x1C, 0xF0, 0x01, 0x0F, 0x9C, 0x61, 0x1D, 0x61, +0xC6, 0xF8, 0x20, 0xA0, 0xDD, 0x61, 0xF2, 0x64, 0x16, 0xD1, 0x40, 0x6A, 0x00, 0xF4, 0x60, 0x14, 0xB4, 0xF5, 0x60, 0x1F, +0x01, 0xD0, 0x80, 0x02, 0x0E, 0xD4, 0x09, 0x48, 0x71, 0x44, 0x01, 0xEB, 0xC1, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x47, 0xF0, +0x01, 0x07, 0x91, 0xF8, 0x20, 0x00, 0x5F, 0x62, 0x01, 0x30, 0x81, 0xF8, 0x20, 0x00, 0xF2, 0x64, 0x00, 0x22, 0x1A, 0x61, +0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x61, 0x17, 0x00, 0x0A, 0x88, 0x03, 0x7F, 0x0A, 0x49, 0x12, 0xF4, 0x00, 0x5F, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x03, 0x12, 0x4F, 0xF4, 0xA4, 0x60, 0x92, 0xF8, 0xDA, 0x20, 0x00, 0xFB, 0x03, 0x13, 0x14, 0xBF, +0x42, 0xF0, 0x02, 0x02, 0x02, 0xF0, 0xFD, 0x02, 0x83, 0xF8, 0xDA, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x43, 0x6A, 0x2D, 0xE9, 0xF0, 0x47, 0x91, 0x46, 0x9A, 0x02, 0xD0, 0xF8, 0x48, 0x80, 0x06, 0x46, 0x0F, 0x46, 0x29, 0xD5, +0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x24, 0xD0, 0x50, 0x4C, 0x88, 0xF8, 0x20, 0x90, 0xD4, 0xF8, 0x80, 0x33, +0x39, 0x46, 0x30, 0x46, 0x98, 0x47, 0x31, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, 0x68, 0xD0, 0x4A, 0x4B, 0xB1, 0x6C, +0x93, 0xF8, 0x05, 0x31, 0x00, 0x2B, 0x59, 0xD1, 0xB3, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x4B, 0x6A, 0x46, 0x4A, 0xCA, 0x60, +0x23, 0xF0, 0x10, 0x03, 0x4B, 0x62, 0x30, 0x46, 0xD4, 0xF8, 0x04, 0x34, 0x8E, 0x60, 0x3A, 0x46, 0x98, 0x47, 0x00, 0x20, +0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x2C, 0xA0, 0x08, 0xF1, 0x24, 0x04, 0x0A, 0xF1, 0x40, 0x00, 0x53, 0x46, 0x53, 0xF8, +0x04, 0x5B, 0x44, 0xF8, 0x04, 0x5F, 0x83, 0x42, 0xF9, 0xD1, 0xF3, 0x8B, 0x9D, 0x04, 0xCA, 0xD5, 0x38, 0x4B, 0x39, 0x49, +0x1A, 0x68, 0x73, 0x7F, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, +0x4C, 0x41, 0x38, 0xDB, 0x41, 0x46, 0xDA, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0xC8, 0xF8, 0x40, 0x20, 0xDA, 0xF8, +0x24, 0x20, 0xC8, 0xF8, 0x50, 0x20, 0xC3, 0xF3, 0xC2, 0x22, 0x05, 0x2A, 0xC8, 0xF8, 0x3C, 0x30, 0x31, 0xD0, 0xDA, 0xF8, +0x3C, 0x30, 0x5C, 0x07, 0x5E, 0xBF, 0xD8, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xC8, 0xF8, 0x2C, 0x30, 0x88, 0x46, +0x9F, 0xE7, 0x32, 0x8B, 0x33, 0x65, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0xAF, 0xD1, 0x8B, 0x6B, 0x23, 0xF4, 0x7F, 0x43, +0x43, 0xF4, 0x60, 0x63, 0x8B, 0x63, 0xA8, 0xE7, 0xF2, 0x8B, 0x10, 0x07, 0xA5, 0xD4, 0xB2, 0x68, 0x52, 0x00, 0x58, 0xBF, +0x81, 0xF8, 0x39, 0x30, 0x9F, 0xE7, 0xF3, 0x6C, 0x19, 0x48, 0xDA, 0x6A, 0x16, 0xF0, 0xFA, 0xFD, 0x90, 0xE7, 0x00, 0x2C, +0xC4, 0xD1, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x17, 0xF0, 0x6B, 0xF8, 0xB1, 0x6C, 0xBD, 0xE7, 0x03, 0xF4, +0xC0, 0x63, 0xD8, 0xF8, 0x4C, 0x20, 0x94, 0xF8, 0xA1, 0x00, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x34, +0x4F, 0xF4, 0x00, 0x34, 0x22, 0xF4, 0x40, 0x33, 0x23, 0x43, 0x20, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, +0xB7, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xC8, 0xF8, 0x4C, 0x30, 0xB2, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, +0xDE, 0xFA, 0xFE, 0xCA, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x78, 0x8E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, +0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x43, 0x6A, 0x85, 0x6C, 0x13, 0xF4, 0x00, 0x18, 0x83, 0xB0, 0x04, 0x46, +0x05, 0xF1, 0x28, 0x07, 0x08, 0xD0, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x00, 0xF0, 0x93, 0x80, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x83, 0xC3, 0x8B, 0xC6, 0x6C, 0x1A, 0x07, 0x38, 0xD5, 0xDF, 0xF8, 0x58, 0x92, 0xD9, 0xF8, 0x00, 0x20, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xCF, 0x80, 0x71, 0x6A, 0x09, 0xB9, 0x32, 0x6A, 0x91, 0x68, 0x18, 0x06, +0x09, 0xD5, 0x94, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDD, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x00, 0x2B, 0x40, 0xF0, +0xDF, 0x80, 0xF3, 0x6C, 0x23, 0xF4, 0xF0, 0x03, 0xF3, 0x64, 0x0B, 0x79, 0xB7, 0x63, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, +0x4F, 0xF4, 0x00, 0x78, 0x00, 0x23, 0xC6, 0xF8, 0x48, 0x80, 0x33, 0x65, 0xEB, 0x6A, 0x2A, 0x6E, 0x72, 0x63, 0x43, 0xF0, +0x02, 0x03, 0xEB, 0x62, 0x20, 0x46, 0x06, 0xF0, 0xBB, 0xF8, 0xA2, 0x6C, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x53, 0x62, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x74, 0x4B, 0xD3, 0xF8, 0x28, 0x34, 0x98, 0x47, 0xEB, 0x6D, 0xB3, 0x64, 0x22, 0x7F, +0x71, 0x49, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, 0x62, 0x20, 0x5A, 0xBB, 0x6E, 0x49, 0x62, 0x7F, +0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x52, 0x68, 0x91, 0x06, 0x22, 0xD5, 0xE2, 0x8B, 0x12, 0xF4, 0x00, 0x5F, +0xE2, 0x6A, 0xD2, 0x6B, 0x14, 0xBF, 0xC2, 0xF3, 0x00, 0x12, 0xC2, 0xF3, 0xC0, 0x02, 0xBA, 0xB9, 0x70, 0x6A, 0x02, 0x88, +0x91, 0xB2, 0x12, 0x04, 0x12, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x20, +0x04, 0x39, 0x04, 0x3A, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x20, 0xD6, 0xE9, 0x0A, 0x21, 0x04, 0x39, 0x04, 0x3A, +0xC6, 0xE9, 0x0A, 0x21, 0xDF, 0xF8, 0x70, 0x81, 0xB7, 0x63, 0xD8, 0xF8, 0x00, 0x20, 0xE7, 0x6C, 0xB2, 0xF9, 0x00, 0x20, +0x00, 0x2A, 0x4F, 0xDB, 0x7A, 0x6A, 0x0A, 0xB9, 0x3A, 0x6A, 0x92, 0x68, 0x23, 0xF4, 0xC0, 0x63, 0xB3, 0x64, 0x12, 0x79, +0xD2, 0x07, 0x5C, 0xBF, 0x43, 0xF4, 0x00, 0x73, 0xB3, 0x64, 0x9B, 0xE7, 0x83, 0x6A, 0x46, 0x6C, 0xC3, 0xF3, 0xC2, 0x22, +0x05, 0x2A, 0x37, 0x63, 0x15, 0xD1, 0x03, 0xF4, 0xC0, 0x63, 0xEA, 0x6C, 0x90, 0xF8, 0x36, 0x10, 0xB3, 0xF5, 0x80, 0x6F, +0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x33, 0x4F, 0xF4, 0x00, 0x33, 0x22, 0xF4, 0x40, 0x32, 0x1A, 0x43, 0x89, 0x06, 0x4C, 0xBF, +0x42, 0xF4, 0x80, 0x22, 0x22, 0xF4, 0x80, 0x22, 0xEA, 0x64, 0x04, 0xF1, 0x28, 0x00, 0x04, 0xF0, 0xDD, 0xF9, 0xD4, 0xF8, +0x48, 0xC0, 0xA2, 0x6A, 0xB0, 0x88, 0xDC, 0xF8, 0x24, 0x30, 0xE9, 0x6D, 0xEA, 0x63, 0xEA, 0x6A, 0x40, 0xF0, 0x08, 0x04, +0xB4, 0x80, 0x41, 0xF4, 0xC0, 0x60, 0x2C, 0x6E, 0xF4, 0x62, 0x42, 0xF0, 0x02, 0x02, 0x30, 0x64, 0x43, 0xF0, 0x10, 0x03, +0xEA, 0x62, 0x39, 0x46, 0x06, 0xF5, 0x82, 0x70, 0x34, 0x22, 0xCC, 0xF8, 0x24, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, +0x29, 0xF0, 0xFE, 0xB9, 0xA2, 0x6C, 0x00, 0x2A, 0x3C, 0xD0, 0x7A, 0x6A, 0x00, 0x2A, 0xAD, 0xD1, 0x3A, 0x6A, 0x92, 0xB1, +0xB3, 0x6C, 0xA8, 0xE7, 0x2D, 0xB3, 0x71, 0x6A, 0x00, 0x29, 0x7F, 0xF4, 0x30, 0xAF, 0x32, 0x6A, 0x0A, 0xB1, 0xE3, 0x8B, +0x2A, 0xE7, 0x23, 0x49, 0x23, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x3F, 0xFF, 0x32, 0x6A, 0xF5, 0xE7, 0x1F, 0x49, +0x1F, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x37, 0xFF, 0x3A, 0x6A, 0xE4, 0xE7, 0x20, 0x22, 0x20, 0x46, 0x01, 0x91, +0x22, 0xF0, 0xD8, 0xF8, 0x01, 0x99, 0x20, 0xE7, 0xA2, 0x88, 0x01, 0x91, 0x20, 0x46, 0x23, 0xF0, 0x87, 0xFA, 0x01, 0x99, +0x19, 0xE7, 0x14, 0x49, 0x15, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, 0x21, 0xFF, 0x71, 0x6A, 0xA9, 0xB9, 0xD9, 0xF8, +0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCF, 0xDB, 0xD8, 0xE7, 0x4F, 0xF4, 0xD9, 0x72, 0x0B, 0x49, 0x0D, 0x48, +0x16, 0xF0, 0x12, 0xFF, 0x7A, 0x6A, 0x42, 0xB9, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB7, 0xDB, +0xD1, 0xE7, 0xE3, 0x8B, 0xED, 0xE6, 0xB3, 0x6C, 0x60, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, +0x05, 0x28, 0x1C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x07, 0x0B, 0x0F, 0x13, 0x17, 0x03, 0x12, 0x4B, 0x20, 0x22, 0x1A, 0x60, +0x70, 0x47, 0x10, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0E, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0C, 0x4B, +0x08, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x0A, 0x4B, 0x10, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0x70, 0x47, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x04, 0x49, 0x05, 0x48, +0x4F, 0xF4, 0x77, 0x72, 0x16, 0xF0, 0xCA, 0xBE, 0x80, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x85, 0xB0, 0x06, 0x46, 0x00, 0xF0, 0xE5, 0x81, 0xAE, 0x4C, +0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0xAB, 0x4B, 0xAC, 0x4F, 0xDF, 0xF8, 0xD4, 0x92, +0x01, 0x22, 0x19, 0x46, 0xB2, 0x40, 0x71, 0x18, 0x00, 0x92, 0xA3, 0x7E, 0x02, 0x91, 0xD2, 0x43, 0x4F, 0xEA, 0x81, 0x08, +0x01, 0x92, 0x00, 0x2B, 0x3A, 0xD0, 0x3B, 0x68, 0x65, 0x6A, 0x5B, 0x78, 0xD5, 0xF8, 0x8C, 0x20, 0x00, 0x2B, 0x00, 0xF0, +0x8B, 0x80, 0x69, 0x6D, 0x00, 0x29, 0x00, 0xF0, 0x11, 0x81, 0x00, 0x2A, 0x80, 0xF2, 0x29, 0x81, 0x9D, 0x49, 0xD9, 0xF8, +0x00, 0x30, 0x51, 0xF8, 0x26, 0x10, 0x0B, 0x44, 0x11, 0x02, 0xC8, 0xF8, 0x00, 0x30, 0x40, 0xF1, 0xA2, 0x80, 0xAB, 0x88, +0x99, 0x06, 0x40, 0xF1, 0x43, 0x81, 0x97, 0x4A, 0x43, 0xF0, 0x10, 0x03, 0x52, 0xF8, 0x26, 0x00, 0xAB, 0x80, 0x15, 0xF0, +0x87, 0xF9, 0x94, 0xF8, 0x50, 0x30, 0x3A, 0x68, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, +0x53, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x6B, 0x6D, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0xA5, 0x62, 0xEB, 0x7A, +0x01, 0x33, 0xEB, 0x72, 0xE5, 0x68, 0x00, 0x2D, 0x00, 0xF0, 0x90, 0x81, 0xD5, 0xF8, 0x4C, 0xB0, 0xDB, 0xF8, 0x50, 0xA0, +0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0xA9, 0x81, 0x30, 0x46, 0xCB, 0xF8, 0x10, 0xA0, 0x04, 0xF0, 0x03, 0xF9, 0x6A, 0x6A, +0x12, 0xF4, 0x00, 0x10, 0x11, 0xD1, 0xDB, 0xF8, 0x18, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x8B, 0x6B, 0x03, 0xF4, +0x60, 0x13, 0xB3, 0xF5, 0x00, 0x1F, 0x8C, 0x46, 0x00, 0xF0, 0x29, 0x81, 0xDC, 0xF8, 0x3C, 0x30, 0x00, 0x2B, 0x80, 0xF2, +0x9D, 0x81, 0x1A, 0xF4, 0x00, 0x0F, 0x0B, 0xD0, 0x6B, 0x7F, 0x0D, 0x2B, 0x08, 0xD8, 0x73, 0x48, 0x73, 0x49, 0x4F, 0xF4, +0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x03, 0x09, 0x69, 0xC3, 0xF8, 0x58, 0x12, 0x02, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, +0x00, 0xF0, 0x9E, 0x80, 0x04, 0xF1, 0x0C, 0x00, 0x15, 0xF0, 0x18, 0xFA, 0x6B, 0x6A, 0x9B, 0x02, 0x04, 0xD4, 0x94, 0xF8, +0x50, 0x30, 0x01, 0x3B, 0x84, 0xF8, 0x50, 0x30, 0xAB, 0x88, 0x00, 0x2B, 0x5F, 0xD1, 0x28, 0x46, 0x02, 0xF0, 0x4C, 0xF8, +0x60, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0x52, 0xF8, 0x26, 0x20, 0x13, 0x44, 0xC8, 0xF8, 0x00, 0x30, 0xA3, 0x7E, 0x6A, 0xE7, +0x29, 0x69, 0x00, 0x29, 0x00, 0xF0, 0xA4, 0x80, 0xAB, 0x6C, 0x00, 0x2B, 0x80, 0xF2, 0x9D, 0x80, 0x57, 0x4B, 0xD9, 0xF8, +0x00, 0x20, 0x53, 0xF8, 0x26, 0x10, 0xAB, 0x88, 0x0A, 0x44, 0xC8, 0xF8, 0x00, 0x20, 0x9A, 0x06, 0x3F, 0xF5, 0x77, 0xAF, +0xDF, 0xF8, 0x6C, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x99, 0x06, 0x3F, 0xF5, +0x6C, 0xAF, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, +0x62, 0xAF, 0x04, 0xF1, 0x1C, 0x00, 0x15, 0xF0, 0xD3, 0xF9, 0xAB, 0x88, 0x5B, 0xE7, 0x2B, 0x69, 0x00, 0x2B, 0x7F, 0xF4, +0x71, 0xAF, 0x46, 0x4B, 0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x43, 0x4A, 0x01, 0x21, +0x11, 0x60, 0x43, 0x4A, 0x01, 0x99, 0x10, 0x68, 0x3F, 0x4D, 0x0B, 0x40, 0x41, 0x1C, 0x11, 0x60, 0x2B, 0x60, 0x29, 0xB1, +0x3D, 0x4B, 0x10, 0x60, 0x1B, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x00, 0x22, +0xA3, 0x7E, 0x22, 0x60, 0x17, 0xE7, 0x51, 0x46, 0x28, 0x46, 0x32, 0x46, 0x01, 0xF0, 0xC6, 0xF9, 0x9C, 0xE7, 0x33, 0x4B, +0x1B, 0x68, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x30, 0x4A, 0x01, 0x21, 0x11, 0x60, 0xDF, 0xF8, +0xC0, 0xC0, 0x01, 0x99, 0xDC, 0xF8, 0x00, 0x00, 0x2B, 0x4A, 0x0B, 0x40, 0x41, 0x1C, 0xCC, 0xF8, 0x00, 0x10, 0x13, 0x60, +0x39, 0xB1, 0x29, 0x4B, 0xCC, 0xF8, 0x00, 0x00, 0x1B, 0x68, 0x10, 0xB9, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x80, 0x27, 0x4B, +0x00, 0x9A, 0x1A, 0x60, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x2B, 0x22, 0x60, 0x7C, 0xD0, 0x6A, 0x6A, 0x4C, 0xE7, +0x6B, 0x6C, 0x63, 0x62, 0x01, 0x23, 0x40, 0x20, 0xA3, 0x76, 0x15, 0xF0, 0x91, 0xF8, 0x59, 0xE7, 0x94, 0xF8, 0x50, 0x10, +0x01, 0x29, 0x7F, 0xF4, 0xEA, 0xAE, 0xE1, 0x6A, 0x00, 0x29, 0x3F, 0xF4, 0xE6, 0xAE, 0x21, 0x6B, 0x19, 0x48, 0x09, 0x7F, +0x4F, 0xF0, 0xA4, 0x0C, 0x0C, 0xFB, 0x01, 0x61, 0x99, 0x31, 0x50, 0xF8, 0x31, 0x10, 0x00, 0x29, 0x7B, 0xD0, 0x00, 0x2B, +0x3F, 0xF4, 0x62, 0xAF, 0x00, 0x2A, 0xFF, 0xF6, 0xD7, 0xAE, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x50, 0x10, +0x01, 0x29, 0x7F, 0xF4, 0x57, 0xAF, 0xE1, 0x6A, 0x00, 0x29, 0xE2, 0xD1, 0x52, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, +0x4A, 0x80, 0x0C, 0x10, 0x34, 0x36, 0x17, 0x00, 0xB0, 0x35, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, +0x18, 0x88, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xDF, 0xF8, 0x68, 0xB1, 0xDB, 0xF8, 0x9C, 0x32, +0x98, 0x47, 0x4F, 0xF0, 0x04, 0x0A, 0xAB, 0x88, 0x9A, 0x06, 0x3F, 0xF5, 0xB2, 0xAE, 0xDB, 0xF8, 0x9C, 0x32, 0x98, 0x47, +0xBA, 0xF1, 0x01, 0x0A, 0xF5, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xAB, 0x88, 0xBF, 0xF6, +0xA4, 0xAE, 0x98, 0x06, 0x3F, 0xF5, 0xA1, 0xAE, 0x48, 0x49, 0x49, 0x48, 0x4F, 0xF4, 0xAC, 0x62, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x4F, 0x16, 0xF0, 0xEB, 0xBC, 0x43, 0x48, 0x8B, 0x68, 0x01, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, 0x33, 0xDB, +0x60, 0x46, 0x9C, 0x46, 0xCC, 0xE6, 0xE3, 0x6A, 0x00, 0x2B, 0x3F, 0xF4, 0x7F, 0xAF, 0x23, 0x6B, 0x3E, 0x4A, 0x1B, 0x7F, +0xA4, 0x21, 0x01, 0xFB, 0x03, 0x63, 0x99, 0x33, 0x52, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x73, 0xAF, 0x3A, 0x4B, +0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x6D, 0xAF, 0x38, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, +0x66, 0xE7, 0x62, 0xB6, 0x5B, 0xE7, 0x33, 0x49, 0x91, 0xF8, 0xFF, 0x11, 0x00, 0x29, 0x7F, 0xF4, 0x7E, 0xAF, 0x31, 0x4B, +0x03, 0x92, 0xD3, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0x3B, 0x68, 0x03, 0x9A, 0x5B, 0x78, 0x00, 0x2B, 0x7F, 0xF4, +0x75, 0xAF, 0xD5, 0xE6, 0x00, 0x2B, 0xC9, 0xD1, 0x25, 0x49, 0x2A, 0x48, 0x00, 0x93, 0x40, 0xF2, 0x56, 0x42, 0x16, 0xF0, +0xD9, 0xFC, 0x00, 0x9B, 0xDB, 0x6B, 0xFF, 0xDE, 0x26, 0x4C, 0x1F, 0xE6, 0x26, 0x4B, 0x25, 0x60, 0x1B, 0x68, 0xEF, 0xF3, +0x10, 0x82, 0xD0, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x23, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x23, 0x4A, 0x01, 0x99, 0x10, 0x68, +0x1F, 0x4C, 0x19, 0x40, 0x0B, 0x46, 0x41, 0x1C, 0x11, 0x60, 0x23, 0x60, 0x29, 0xB1, 0x1D, 0x4B, 0x10, 0x60, 0x1B, 0x68, +0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x1C, 0x4B, 0x00, 0x9A, 0x1A, 0x60, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x6B, 0x6A, +0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x7F, 0xF4, 0x41, 0xAF, 0x68, 0x6C, 0x31, 0x46, 0x0C, 0x30, 0x05, 0xB0, +0xBD, 0xE8, 0xF0, 0x4F, 0x03, 0xF0, 0x28, 0xBF, 0x10, 0xB1, 0x31, 0x46, 0x03, 0xF0, 0x24, 0xFF, 0x10, 0x4B, 0x11, 0x4A, +0x53, 0xF8, 0x26, 0x10, 0x02, 0x9B, 0x12, 0x68, 0x9B, 0x00, 0x0A, 0x44, 0x1A, 0x60, 0x2A, 0xE7, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xC0, 0x8E, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x88, 0x80, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x43, 0x6A, 0x9B, 0x02, 0x03, 0xD5, 0x4B, 0x6A, +0x5B, 0x07, 0x07, 0xD4, 0x70, 0x47, 0xC1, 0x6C, 0x05, 0x4B, 0x14, 0x31, 0xD3, 0xF8, 0x9C, 0x33, 0x08, 0x46, 0x18, 0x47, +0x42, 0x6C, 0x93, 0x88, 0x43, 0xF0, 0x02, 0x03, 0x93, 0x80, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x43, 0x7F, +0x0B, 0x4E, 0x4F, 0xF4, 0x1E, 0x75, 0x04, 0x46, 0x05, 0xFB, 0x03, 0xF5, 0x05, 0xF5, 0xFE, 0x70, 0x01, 0x23, 0xE1, 0x76, +0x84, 0xF8, 0x5D, 0x30, 0x30, 0x44, 0x21, 0x46, 0x14, 0xF0, 0xFE, 0xFF, 0x04, 0x4B, 0x71, 0x19, 0x20, 0x46, 0x5B, 0x69, +0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x83, 0x88, 0x2D, 0xE9, +0xF0, 0x41, 0x04, 0x46, 0x0E, 0x46, 0x15, 0x46, 0xEB, 0xB1, 0x3A, 0x4B, 0xD0, 0xF8, 0x4C, 0x80, 0x1A, 0x68, 0xB2, 0xF9, +0x00, 0x20, 0x00, 0x2A, 0x23, 0xDB, 0xD8, 0xF8, 0x24, 0x70, 0x17, 0xB9, 0xD8, 0xF8, 0x20, 0x30, 0x9F, 0x68, 0x04, 0x2D, +0x03, 0xD1, 0x39, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFB, 0xE3, 0x7E, 0xFF, 0x2B, 0x25, 0xD0, 0x2F, 0x4F, 0x29, 0x46, +0xD7, 0xF8, 0x00, 0x34, 0x20, 0x46, 0x98, 0x47, 0x05, 0xE0, 0x82, 0x6C, 0x2B, 0x4F, 0x53, 0x6A, 0x43, 0xF0, 0x10, 0x03, +0x53, 0x62, 0xD7, 0xF8, 0xA4, 0x33, 0x2A, 0x46, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x82, 0x6C, +0x5A, 0xB3, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xDB, 0xD1, 0xD8, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0xD6, 0xD1, 0x21, 0x49, +0x21, 0x48, 0x40, 0xF2, 0xB9, 0x12, 0x16, 0xF0, 0x03, 0xFC, 0xCD, 0xE7, 0xE3, 0x8B, 0x1A, 0x07, 0x04, 0xD5, 0x3A, 0x88, +0x02, 0xF0, 0xDC, 0x02, 0x10, 0x2A, 0x25, 0xD0, 0xBB, 0x7D, 0x13, 0xF0, 0x0F, 0x03, 0x07, 0xF1, 0x16, 0x07, 0x06, 0xD0, +0x18, 0x4A, 0xB2, 0xF8, 0xFC, 0x21, 0x43, 0xEA, 0x02, 0x13, 0x3B, 0x80, 0xC4, 0xE7, 0x15, 0x49, 0xB1, 0xF8, 0xFC, 0x21, +0x01, 0x32, 0x92, 0xB2, 0xA1, 0xF8, 0xFC, 0x21, 0xF3, 0xE7, 0x0F, 0x49, 0x11, 0x48, 0x4F, 0xF4, 0xD9, 0x72, 0x16, 0xF0, +0xDF, 0xFB, 0xD8, 0xF8, 0x24, 0x70, 0x00, 0x2F, 0xA9, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xC7, 0xDB, 0x9F, 0xE7, 0x7A, 0x8B, 0x00, 0x2A, 0xD6, 0xD1, 0x43, 0xF0, 0x20, 0x03, 0xE3, 0x83, 0x38, 0x1D, 0x20, 0xF0, +0xF9, 0xFE, 0xCF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x8E, 0x15, 0x00, +0x20, 0x62, 0x17, 0x00, 0x8C, 0x8E, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x05, 0x29, 0x00, 0xF2, 0x33, 0x81, 0xDF, 0xE8, +0x01, 0xF0, 0x36, 0x44, 0x51, 0x5E, 0x6B, 0x03, 0x9D, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x00, 0xF0, +0x04, 0x81, 0x9B, 0x4A, 0x9B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x42, 0x1A, 0x60, 0x9A, 0x49, 0x9A, 0x4A, 0x9B, 0x4B, +0x51, 0xF8, 0x24, 0x50, 0x12, 0x68, 0x9A, 0x48, 0x23, 0x44, 0x9B, 0x00, 0x01, 0x21, 0x2A, 0x44, 0x01, 0xFA, 0x04, 0xF4, +0x1A, 0x60, 0x04, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x94, 0x4B, 0x19, 0x60, 0x94, 0x4B, +0x94, 0x49, 0x18, 0x68, 0x0D, 0x68, 0x42, 0x1C, 0x2C, 0x43, 0x1A, 0x60, 0x0C, 0x60, 0x2A, 0xB1, 0x8E, 0x4A, 0x18, 0x60, +0x13, 0x68, 0x08, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x84, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, +0x00, 0xF0, 0xAE, 0x80, 0x8A, 0x4A, 0x82, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x00, 0x72, 0x1A, 0x60, 0xCB, 0xE7, 0x7D, 0x4A, +0x13, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7D, 0xD0, 0x85, 0x4A, 0x7B, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x62, +0x1A, 0x60, 0xBE, 0xE7, 0x76, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, 0x4F, 0xD0, 0x7F, 0x4A, 0x75, 0x4B, +0x10, 0x60, 0x4F, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0xB1, 0xE7, 0x70, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, +0x21, 0xD0, 0x7A, 0x4A, 0x6E, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xA4, 0xE7, 0x77, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x75, 0x4A, 0x68, 0x4B, 0x10, 0x60, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, +0x97, 0xE7, 0x63, 0x4B, 0x1B, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x02, 0x2B, 0xF2, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x6F, 0x49, +0x6F, 0x48, 0x4F, 0xF4, 0xEC, 0x62, 0x16, 0xF0, 0xFF, 0xBA, 0x60, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, +0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xF6, 0xD0, 0x63, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCA, 0xDA, 0x52, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x43, 0x02, 0x2B, 0xC4, 0xD1, +0xBD, 0xE8, 0x38, 0x40, 0x5E, 0x49, 0x60, 0x48, 0x40, 0xF2, 0x6C, 0x72, 0x16, 0xF0, 0xDE, 0xBA, 0x4F, 0x49, 0x0D, 0x68, +0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x33, 0x02, 0x2B, +0xF6, 0xD0, 0x53, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, 0x42, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, +0x01, 0x33, 0x02, 0x2B, 0x96, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x4E, 0x49, 0x50, 0x48, 0x4F, 0xF4, 0xEF, 0x62, 0x16, 0xF0, +0xBD, 0xBA, 0x3F, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, +0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0xF6, 0xD0, 0x42, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, +0x6E, 0xAF, 0x31, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x23, 0x02, 0x2B, 0x7F, 0xF4, 0x67, 0xAF, 0xBD, 0xE8, 0x38, 0x40, +0x3C, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x84, 0x72, 0x16, 0xF0, 0x9A, 0xBA, 0x2D, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, +0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0xC3, 0xF3, 0x01, 0x13, 0x02, 0x2B, 0xF6, 0xD0, 0x31, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x3E, 0xAF, 0x1F, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x13, +0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xBD, 0xE8, 0x38, 0x40, 0x2B, 0x49, 0x2F, 0x48, 0x4F, 0xF4, 0xF2, 0x62, 0x16, 0xF0, +0x77, 0xBA, 0x1C, 0x49, 0x0D, 0x68, 0x02, 0x35, 0x03, 0xE0, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, +0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0xF6, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, +0xE8, 0xAE, 0x0E, 0x4B, 0x1B, 0x68, 0xC3, 0xF3, 0x01, 0x63, 0x02, 0x2B, 0x7F, 0xF4, 0xE1, 0xAE, 0xBD, 0xE8, 0x38, 0x40, +0x19, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x9C, 0x72, 0x16, 0xF0, 0x54, 0xBA, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xBF, 0xF6, 0xD8, 0xAE, 0x13, 0x49, 0x19, 0x48, 0x40, 0xF2, 0xA2, 0x72, 0x16, 0xF0, 0x79, 0xFA, 0xD0, 0xE6, +0x88, 0x81, 0x32, 0x40, 0x34, 0x83, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, +0x4A, 0x80, 0x0C, 0x10, 0x88, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, +0x9C, 0x81, 0x32, 0x40, 0xA0, 0x81, 0x32, 0x40, 0xA4, 0x81, 0x32, 0x40, 0xA8, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, +0x98, 0x81, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0xF8, 0x8E, 0x15, 0x00, 0x18, 0x8F, 0x15, 0x00, 0x38, 0x8F, 0x15, 0x00, +0x58, 0x8F, 0x15, 0x00, 0x78, 0x8F, 0x15, 0x00, 0x98, 0x8F, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x05, 0x2A, 0xF8, 0xB5, +0x06, 0x46, 0x0D, 0x46, 0x35, 0xD0, 0x54, 0x21, 0x33, 0x4C, 0x01, 0xFB, 0x02, 0xF1, 0x02, 0xEB, 0x42, 0x03, 0x61, 0x58, +0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, 0x00, 0x29, 0x37, 0xD0, 0x2E, 0x4F, 0x3B, 0x68, 0x5B, 0x78, 0xF3, 0xB1, +0x4E, 0x60, 0x05, 0x2A, 0x0B, 0xD0, 0x2C, 0x48, 0x02, 0xEB, 0x42, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x91, 0xF8, 0x2E, 0x10, +0x41, 0xB9, 0x90, 0xF8, 0x8C, 0x10, 0x00, 0x29, 0x3E, 0xD1, 0x10, 0x46, 0xFF, 0xF7, 0x2A, 0xFB, 0x3B, 0x68, 0x5B, 0x78, +0x3B, 0xB9, 0xAA, 0x6B, 0x92, 0x02, 0x46, 0xBF, 0x01, 0x23, 0xC4, 0xE9, 0x01, 0x63, 0xC4, 0xE9, 0x01, 0x33, 0x25, 0x60, +0xF8, 0xBD, 0xA0, 0x68, 0x00, 0x28, 0xDD, 0xD0, 0x61, 0x68, 0x4E, 0x60, 0xDB, 0xE7, 0x19, 0x4C, 0xD4, 0xF8, 0xA4, 0x11, +0x04, 0xF5, 0xD2, 0x74, 0x00, 0x29, 0xCF, 0xD1, 0x11, 0x46, 0x30, 0x46, 0xFF, 0xF7, 0x44, 0xFE, 0x14, 0x4B, 0x1B, 0x68, +0x5B, 0x78, 0xDF, 0xE7, 0x13, 0x4B, 0x02, 0xEB, 0x42, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x51, 0x00, 0x90, 0xF8, 0x2E, 0x00, +0x38, 0xB9, 0x93, 0xF8, 0x8C, 0x00, 0x93, 0xF8, 0x7E, 0x70, 0x00, 0x28, 0xE8, 0xD0, 0xBA, 0x42, 0xE6, 0xD1, 0x0A, 0x44, +0x03, 0xEB, 0x82, 0x03, 0x5A, 0x6A, 0x42, 0xB1, 0x07, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0xC5, 0xE7, 0x90, 0xF8, 0x7E, 0x10, +0x91, 0x42, 0xBC, 0xD1, 0xC0, 0xE7, 0x03, 0x4A, 0x5E, 0x62, 0x13, 0x68, 0x5B, 0x78, 0xBB, 0xE7, 0x20, 0x62, 0x17, 0x00, +0x34, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x38, 0xB5, 0x83, 0x88, 0x33, 0xB1, 0x04, 0x46, 0x80, 0x6C, 0x18, 0xB1, +0x63, 0x6A, 0x13, 0xF4, 0x00, 0x15, 0x00, 0xD0, 0x38, 0xBD, 0xF8, 0xF7, 0x75, 0xFE, 0xA5, 0x64, 0x38, 0xBD, 0x00, 0xBF, +0x70, 0xB5, 0x20, 0x4C, 0x20, 0x4D, 0x02, 0xF0, 0xD9, 0xFC, 0xD4, 0xF8, 0x44, 0x33, 0x98, 0x47, 0xFE, 0xF7, 0x9E, 0xFF, +0x00, 0xF0, 0xA8, 0xFD, 0xD4, 0xF8, 0xA8, 0x33, 0x00, 0x20, 0x98, 0x47, 0x04, 0xF0, 0xBA, 0xFE, 0x4F, 0xF4, 0x01, 0x72, +0x00, 0x21, 0xA5, 0xF1, 0x0C, 0x00, 0xF1, 0xF7, 0xC3, 0xFC, 0x05, 0xF5, 0xD2, 0x76, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, +0x4D, 0xFD, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, 0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, +0x54, 0x35, 0x14, 0xF0, 0x41, 0xFD, 0xB5, 0x42, 0xEE, 0xD1, 0x0C, 0x4D, 0x05, 0xF5, 0xD8, 0x70, 0x14, 0xF0, 0x3A, 0xFD, +0x05, 0xF5, 0xE0, 0x70, 0xC5, 0xE9, 0x72, 0x44, 0xC5, 0xF8, 0xA4, 0x41, 0x85, 0xF8, 0xBE, 0x41, 0x85, 0xF8, 0xF4, 0x41, +0x14, 0xF0, 0x2E, 0xFD, 0xA5, 0xF8, 0xFC, 0x41, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x62, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x0C, 0x4B, 0x93, 0xF8, 0xFE, 0x31, 0x0B, 0xB1, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x04, 0x46, +0x10, 0xF0, 0xBC, 0xF8, 0x20, 0xB1, 0x94, 0xF8, 0xC0, 0x34, 0x1B, 0xB9, 0x01, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, +0x94, 0xF8, 0xC1, 0x04, 0x11, 0xF0, 0x16, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x10, 0xBD, 0x20, 0x62, 0x17, 0x00, +0x45, 0x4B, 0x01, 0x22, 0x70, 0xB4, 0x1B, 0x68, 0x02, 0xFA, 0x00, 0xF6, 0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, +0x72, 0xB6, 0x41, 0x49, 0x0A, 0x60, 0x41, 0x4A, 0x3E, 0x4D, 0x14, 0x68, 0x23, 0xEA, 0x06, 0x03, 0x61, 0x1C, 0x11, 0x60, +0x2B, 0x60, 0x29, 0xB1, 0x3B, 0x4B, 0x14, 0x60, 0x1B, 0x68, 0x0C, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x3A, 0x4B, 0x1E, 0x60, +0x05, 0x28, 0x5D, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x12, 0x21, 0x3F, 0x30, 0x4E, 0x03, 0x37, 0x4B, 0x37, 0x4A, 0x4F, 0xF4, +0x00, 0x11, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x40, 0x7F, 0xFB, 0xD1, 0x34, 0x4B, 0x4F, 0xF4, 0x00, 0x12, 0x70, 0xBC, +0x1A, 0x60, 0x70, 0x47, 0x2F, 0x4B, 0x30, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF0, 0x30, 0x0F, +0xFB, 0xD1, 0x2D, 0x4B, 0x4F, 0xF4, 0x80, 0x32, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x28, 0x4B, 0x28, 0x4A, 0x4F, 0xF4, +0x00, 0x31, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x7F, 0xFB, 0xD1, 0x25, 0x4B, 0x4F, 0xF4, 0x00, 0x32, 0x70, 0xBC, +0x1A, 0x60, 0x70, 0x47, 0x20, 0x4B, 0x21, 0x4A, 0x4F, 0xF4, 0x00, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x3F, +0xFB, 0xD1, 0x1E, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x70, 0xBC, 0x1A, 0x60, 0x70, 0x47, 0x19, 0x4B, 0x19, 0x4A, 0x4F, 0xF4, +0x80, 0x21, 0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0xFB, 0xD1, 0x16, 0x4B, 0x4F, 0xF4, 0x80, 0x22, 0x70, 0xBC, +0x1A, 0x60, 0x70, 0x47, 0x11, 0x4B, 0x12, 0x4A, 0x4F, 0xF4, 0x00, 0x41, 0x19, 0x60, 0x13, 0x68, 0x9B, 0x07, 0xFC, 0xD1, +0x0F, 0x4B, 0x4F, 0xF4, 0x00, 0x42, 0x1A, 0x60, 0x70, 0xBC, 0x70, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xF7, 0xDA, 0x70, 0xBC, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xE7, 0x02, 0x16, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, +0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x80, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, +0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, +0x70, 0xB5, 0x05, 0x28, 0x82, 0xB0, 0x04, 0x46, 0x0A, 0x46, 0x3B, 0xD0, 0x1E, 0x4B, 0x00, 0xEB, 0x40, 0x05, 0xC5, 0xEB, +0xC5, 0x05, 0x03, 0xEB, 0x85, 0x05, 0x1C, 0x4E, 0x1C, 0x49, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x92, 0x01, 0xEB, 0xC4, 0x01, +0x20, 0x46, 0x98, 0x47, 0x01, 0x9A, 0xD6, 0xF8, 0x84, 0x33, 0x05, 0xF1, 0x0C, 0x01, 0x20, 0x46, 0x98, 0x47, 0x00, 0x23, +0x20, 0x46, 0x2B, 0x60, 0x6B, 0x61, 0xFE, 0xF7, 0x59, 0xFE, 0x13, 0x4B, 0x01, 0x22, 0x1B, 0x68, 0x02, 0xFA, 0x04, 0xF4, +0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x0F, 0x49, 0x0A, 0x60, 0x0F, 0x4A, 0x0C, 0x4D, 0x11, 0x68, +0x23, 0xEA, 0x04, 0x03, 0x48, 0x1C, 0x10, 0x60, 0x2B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, +0x03, 0xB1, 0x62, 0xB6, 0x08, 0x4B, 0x1C, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x07, 0x4D, 0xC8, 0xE7, 0x20, 0x62, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x88, 0x80, 0x32, 0x40, 0xC4, 0x63, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x82, 0xB0, 0x00, 0xF5, 0x9E, 0x64, 0x00, 0x25, +0xE8, 0xB2, 0x21, 0x46, 0xD6, 0xF8, 0x84, 0x33, 0x01, 0x90, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x01, 0x35, 0xA4, 0xF1, +0x28, 0x01, 0x01, 0x98, 0xD6, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0x05, 0x2D, 0x04, 0xF1, 0x08, 0x04, +0xEA, 0xD1, 0x02, 0xB0, 0x70, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, +0x04, 0x46, 0x64, 0xD0, 0x33, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, +0x35, 0x10, 0x94, 0xF8, 0x33, 0x20, 0xA3, 0x88, 0x2E, 0x48, 0x0A, 0x44, 0x1A, 0x44, 0xE3, 0x6C, 0xE1, 0x8B, 0x58, 0x61, +0x04, 0x32, 0xDA, 0x62, 0x00, 0x22, 0xC3, 0xE9, 0x0F, 0x22, 0xC3, 0xE9, 0x06, 0x22, 0xC3, 0xE9, 0x08, 0x22, 0x5A, 0x64, +0x9A, 0x62, 0x9A, 0x63, 0xDA, 0x64, 0x1A, 0x63, 0x1A, 0x65, 0xCA, 0x07, 0x05, 0xD4, 0x22, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, +0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0x4B, 0x1B, 0x6A, 0x23, 0xB1, 0x20, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, +0x13, 0x60, 0xDF, 0xF8, 0x88, 0x80, 0x61, 0x7F, 0x20, 0x7F, 0x00, 0x22, 0x12, 0xF0, 0x5A, 0xF9, 0xD8, 0xF8, 0x48, 0x32, +0xE1, 0x7E, 0x60, 0x7F, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x16, 0x4F, 0xD8, 0xF8, 0x68, 0x33, 0x3A, 0x68, 0x01, 0x32, 0x3A, 0x60, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, +0xD8, 0xF8, 0x08, 0x34, 0x31, 0x46, 0x00, 0x22, 0x20, 0x46, 0x98, 0x47, 0x21, 0x46, 0x05, 0xF1, 0x0C, 0x00, 0x14, 0xF0, +0x99, 0xFB, 0x3B, 0x68, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, +0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x07, 0x4D, 0x9F, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, +0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x03, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x70, 0x47, 0x00, 0xBF, +0x20, 0x62, 0x17, 0x00, 0x05, 0x29, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x46, 0x04, 0x46, 0x1C, 0xD0, 0x47, 0x4E, 0x01, 0xEB, +0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x06, 0x22, 0x7F, 0x44, 0x4B, 0xE7, 0x6C, 0x4F, 0xF4, 0xA4, 0x60, +0x00, 0xFB, 0x02, 0x30, 0xFF, 0xF7, 0x32, 0xFE, 0x68, 0xB9, 0x63, 0x7F, 0xFF, 0x2B, 0x67, 0xD0, 0x3F, 0x4B, 0x20, 0x46, +0xD3, 0xF8, 0x90, 0x33, 0x29, 0x46, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x3C, 0x4E, 0xE7, 0xE7, 0x20, 0x46, +0x1C, 0xF0, 0xEE, 0xFF, 0x00, 0x28, 0xEC, 0xD0, 0xFB, 0x6C, 0x43, 0xF4, 0x80, 0x73, 0xFB, 0x64, 0xEF, 0xF3, 0x10, 0x83, +0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4F, 0x96, 0xF8, 0x50, 0x30, 0x3A, 0x68, +0xF1, 0x6A, 0xDF, 0xF8, 0xBC, 0x80, 0x01, 0x32, 0x01, 0x33, 0x3A, 0x60, 0x86, 0xF8, 0x50, 0x30, 0x19, 0xB1, 0xD8, 0xF8, +0x5C, 0x33, 0x28, 0x46, 0x98, 0x47, 0x73, 0x69, 0x00, 0x2B, 0x42, 0xD0, 0x06, 0xF1, 0x0C, 0x00, 0x21, 0x46, 0x14, 0xF0, +0x21, 0xFB, 0x3B, 0x68, 0x2B, 0xB1, 0x26, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x00, 0x2B, 0x31, 0xD0, 0x1F, 0x4A, +0x24, 0x49, 0xD2, 0xF8, 0xF8, 0x31, 0x09, 0x6A, 0x01, 0x33, 0xC2, 0xF8, 0xF8, 0x31, 0x21, 0xB1, 0x21, 0x4A, 0x13, 0x68, +0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x3B, 0x68, 0xD8, 0xF8, 0x04, 0x64, 0xA1, 0x6C, 0x01, 0x33, 0x3B, 0x60, 0x2A, 0x46, 0x20, 0x46, 0xB0, 0x47, +0x3B, 0x68, 0x33, 0xB1, 0x12, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x01, 0x20, +0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x46, 0x00, 0x21, 0x01, 0xF0, 0x7E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2A, +0xCB, 0xD0, 0x62, 0xB6, 0xC9, 0xE7, 0xA3, 0x6C, 0x0B, 0x49, 0x5A, 0x6A, 0x9C, 0x60, 0x22, 0xF0, 0x10, 0x02, 0x5A, 0x62, +0xD9, 0x60, 0xB3, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x80, 0x00, 0x32, 0x40, 0xDE, 0xFA, 0xFE, 0xCA, +0x70, 0x47, 0x00, 0xBF, 0x20, 0x4B, 0x70, 0xB5, 0x1C, 0x68, 0xE1, 0x04, 0x2C, 0xD4, 0x1F, 0x4D, 0x2C, 0x42, 0x24, 0xD1, +0x1E, 0x4B, 0x23, 0x40, 0x20, 0xD0, 0x22, 0x03, 0x0B, 0xD5, 0x1D, 0x4B, 0x4F, 0xF4, 0x00, 0x22, 0x1A, 0x60, 0x05, 0x24, +0x1B, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xA0, 0x33, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x19, 0x4A, 0x12, 0x68, 0xB2, 0xF9, +0x00, 0x20, 0xB3, 0xFA, 0x83, 0xF3, 0xC3, 0xF1, 0x19, 0x04, 0x00, 0x2A, 0xE4, 0xB2, 0x14, 0xDB, 0x05, 0x2C, 0xE6, 0xD0, +0x10, 0x4A, 0xA1, 0x1D, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x60, 0xE5, 0xE7, 0x70, 0xBD, 0x04, 0xF0, 0x07, 0xFB, 0x0C, 0x4B, +0x1D, 0x60, 0xD5, 0xE7, 0x04, 0xF0, 0x56, 0xFA, 0x09, 0x4B, 0x4F, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0xCB, 0xE7, 0x06, 0x2C, +0xE8, 0xD9, 0x09, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xC2, 0x22, 0x15, 0xF0, 0xD9, 0xFE, 0xE3, 0xE7, 0x78, 0x80, 0x32, 0x40, +0x00, 0x08, 0x00, 0x20, 0xC0, 0x07, 0x08, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xB8, 0x8F, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x4B, 0x0D, 0x4D, 0x1C, 0x68, 0xE3, 0x06, 0x05, 0xEA, +0x04, 0x05, 0x03, 0xD5, 0x0B, 0x4B, 0xD3, 0xF8, 0xF0, 0x33, 0x98, 0x47, 0x14, 0xF4, 0x70, 0x04, 0x08, 0xD0, 0x08, 0x4B, +0xB4, 0xFA, 0x84, 0xF4, 0xC4, 0xF1, 0x0B, 0x00, 0xD3, 0xF8, 0x48, 0x33, 0xC0, 0xB2, 0x98, 0x47, 0x04, 0x4B, 0x1D, 0x60, +0x38, 0xBD, 0x00, 0xBF, 0x78, 0x80, 0x32, 0x40, 0x1F, 0x00, 0xF0, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, +0xFF, 0xF7, 0xDA, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1C, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x70, 0x90, 0x1A, 0x4F, 0xD9, 0xF8, 0x00, 0x30, 0xDF, 0xF8, 0x6C, 0x80, 0x01, 0x33, +0xC9, 0xF8, 0x00, 0x30, 0x3D, 0x46, 0x46, 0x46, 0x04, 0x24, 0x95, 0xF8, 0x5E, 0x30, 0xE2, 0xB2, 0x63, 0xB9, 0x97, 0xF8, +0x8C, 0x30, 0x97, 0xF8, 0x7E, 0x10, 0x10, 0x46, 0x0B, 0xB1, 0x91, 0x42, 0x04, 0xD0, 0xD6, 0xF8, 0x50, 0x31, 0x0B, 0xB1, +0xFF, 0xF7, 0x1A, 0xFD, 0x01, 0x3C, 0x63, 0x1C, 0xA5, 0xF1, 0x0C, 0x05, 0xA6, 0xF1, 0x54, 0x06, 0xE7, 0xD1, 0xD9, 0xF8, +0x00, 0x30, 0x01, 0x22, 0x88, 0xF8, 0xFF, 0x21, 0x3B, 0xB1, 0x05, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, +0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4E, 0x31, 0x4D, 0x33, 0x68, 0x31, 0x4F, 0xDF, 0xF8, +0xD0, 0xB0, 0xDF, 0xF8, 0xD0, 0xA0, 0xDF, 0xF8, 0xD0, 0x80, 0x01, 0x33, 0x00, 0x22, 0x33, 0x60, 0x85, 0xF8, 0xFF, 0x21, +0xB9, 0x46, 0x04, 0x24, 0x99, 0xF8, 0x5E, 0x30, 0xE0, 0xB2, 0x00, 0x2B, 0x34, 0xD1, 0x97, 0xF8, 0x8C, 0x30, 0x97, 0xF8, +0x7E, 0x20, 0x0B, 0xB1, 0x82, 0x42, 0x2D, 0xD0, 0xD5, 0xF8, 0x50, 0x31, 0x43, 0xB3, 0x01, 0x90, 0xFE, 0xF7, 0x36, 0xFF, +0x5A, 0xF8, 0x24, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0x20, 0x48, 0x1A, 0x44, 0x40, 0xF8, 0x24, 0x20, 0x01, 0x21, 0x1F, 0x4A, +0x01, 0xFA, 0x04, 0xF3, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x82, 0x12, 0xF0, 0x01, 0x0F, 0x01, 0x98, 0x02, 0xD1, 0x72, 0xB6, +0x14, 0x4A, 0x11, 0x60, 0x32, 0x68, 0xD8, 0xF8, 0x00, 0xC0, 0x51, 0x1C, 0x43, 0xEA, 0x0C, 0x03, 0x31, 0x60, 0xC8, 0xF8, +0x00, 0x30, 0x29, 0xB1, 0x0E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x03, 0xF0, 0x32, 0xF8, +0x01, 0x3C, 0x63, 0x1C, 0xA9, 0xF1, 0x0C, 0x09, 0xA5, 0xF1, 0x54, 0x05, 0xBE, 0xD1, 0x33, 0x68, 0x33, 0xB1, 0x06, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x40, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, +0x14, 0xF0, 0xF8, 0xB8, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, +0x28, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x20, 0x01, 0x32, 0x40, 0xB0, 0x35, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, +0x2D, 0xE9, 0xF0, 0x4F, 0x5D, 0x4E, 0xDF, 0xF8, 0x90, 0x91, 0xB6, 0xF8, 0xFC, 0x31, 0x83, 0xB0, 0x4F, 0xF4, 0x78, 0x30, +0x00, 0x93, 0x06, 0xF1, 0x0C, 0x05, 0x14, 0xF0, 0xFB, 0xF8, 0x01, 0x23, 0x86, 0xF8, 0xFE, 0x31, 0xAA, 0x46, 0x4F, 0xF4, +0x9E, 0x67, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x95, 0x53, 0x49, 0xD9, 0xF8, 0x84, 0x33, 0x5F, 0xFA, 0x8B, 0xF8, 0x40, 0x46, +0x4F, 0xF0, 0x80, 0x42, 0x39, 0x44, 0x98, 0x47, 0x4F, 0x4B, 0x9D, 0x68, 0xA7, 0xF1, 0x28, 0x04, 0xC5, 0xB1, 0xE9, 0x19, +0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x29, 0x19, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, +0x80, 0x42, 0x40, 0x46, 0x98, 0x47, 0x05, 0xF5, 0xA3, 0x61, 0xD9, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x40, 0x46, +0x98, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xE6, 0xD1, 0x51, 0x46, 0xD9, 0xF8, 0x84, 0x33, 0x40, 0x46, 0x08, 0x37, 0x4F, 0xF0, +0x80, 0x42, 0x98, 0x47, 0xB7, 0xF5, 0xA3, 0x6F, 0x0B, 0xF1, 0x01, 0x0B, 0x0A, 0xF1, 0x54, 0x0A, 0xC8, 0xD1, 0xD9, 0xF8, +0x84, 0x33, 0x39, 0x49, 0x01, 0x9D, 0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x37, 0x49, 0xD9, 0xF8, 0x84, 0x33, +0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0x02, 0xF0, 0x30, 0xF9, 0x00, 0xF0, 0x6A, 0xF9, 0xD9, 0xF8, 0xCC, 0x33, +0x98, 0x47, 0x2C, 0x48, 0x4F, 0xF4, 0x01, 0x72, 0x00, 0x21, 0xF1, 0xF7, 0x89, 0xF8, 0x2B, 0x4B, 0xD3, 0xF8, 0x08, 0x80, +0x00, 0x9B, 0xA6, 0xF8, 0xFC, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x17, 0xD0, 0x2B, 0x46, 0x45, 0x46, 0x98, 0x46, 0x05, 0xF5, +0x9E, 0x64, 0x05, 0xF5, 0xA3, 0x67, 0x20, 0x46, 0x14, 0xF0, 0x06, 0xF9, 0xA4, 0xF1, 0x28, 0x00, 0x08, 0x34, 0x14, 0xF0, +0x01, 0xF9, 0xBC, 0x42, 0xF5, 0xD1, 0x20, 0x46, 0x14, 0xF0, 0xFC, 0xF8, 0x2D, 0x68, 0x00, 0x2D, 0xEB, 0xD1, 0x45, 0x46, +0x1B, 0x4F, 0x00, 0x24, 0x28, 0x46, 0x14, 0xF0, 0xF3, 0xF8, 0x45, 0xF8, 0x0C, 0x4C, 0xAC, 0x73, 0x85, 0xF8, 0x44, 0x40, +0xC5, 0xE9, 0x06, 0x44, 0x05, 0xF1, 0x10, 0x00, 0x54, 0x35, 0x14, 0xF0, 0xE7, 0xF8, 0xAF, 0x42, 0xEE, 0xD1, 0x12, 0x48, +0x14, 0xF0, 0xE2, 0xF8, 0x12, 0x48, 0xC6, 0xF8, 0xA4, 0x41, 0xC6, 0xE9, 0x72, 0x44, 0x86, 0xF8, 0xBE, 0x41, 0x86, 0xF8, +0xF4, 0x41, 0x14, 0xF0, 0xD7, 0xF8, 0x0E, 0x4A, 0x00, 0x21, 0x02, 0xF5, 0xB4, 0x70, 0xA2, 0xF1, 0x24, 0x03, 0x43, 0xF8, +0x04, 0x1B, 0x93, 0x42, 0xFB, 0xD1, 0x03, 0xF1, 0x24, 0x02, 0x90, 0x42, 0xF5, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x20, 0x62, 0x17, 0x00, 0x34, 0x5F, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD0, 0x63, 0x17, 0x00, 0x4C, 0x64, 0x17, 0x00, +0xE0, 0x63, 0x17, 0x00, 0xD8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x8C, 0x08, 0x8C, 0x83, 0x42, 0x08, 0xD8, +0x05, 0xD2, 0xC0, 0x1A, 0x3F, 0x28, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, +0x70, 0x47, 0x00, 0xBF, 0x51, 0xB9, 0x81, 0x6C, 0x90, 0xF8, 0x42, 0x30, 0xCB, 0x1A, 0x93, 0xF8, 0xB8, 0x30, 0xDB, 0x07, +0x02, 0xD4, 0x03, 0x8B, 0x08, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x91, 0xF8, 0xA8, 0x30, 0x03, 0xF0, 0xF0, 0x03, 0x40, 0x2B, +0xF8, 0xD1, 0x91, 0xF8, 0xB1, 0x30, 0x06, 0x2B, 0x01, 0xD0, 0x01, 0x2B, 0xF2, 0xD1, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, +0xEE, 0xE7, 0x00, 0xBF, 0x03, 0x6D, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x43, 0x56, 0x4A, 0x12, 0x68, +0x12, 0x78, 0x02, 0x2A, 0x83, 0xB0, 0x04, 0x46, 0x0D, 0x46, 0x07, 0xD0, 0x01, 0x2A, 0x7E, 0xD0, 0x03, 0x2A, 0x00, 0xF0, +0x8D, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xFB, 0xF7, 0x8A, 0xFB, 0x06, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x94, 0x80, +0xDF, 0xF8, 0x60, 0x91, 0x42, 0xF2, 0x24, 0x03, 0x59, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x48, 0x48, +0x14, 0xF0, 0xA8, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x08, 0x22, 0x12, 0x23, 0x32, 0x70, 0x86, 0xF8, 0x01, 0x80, 0x86, 0xF8, +0x03, 0x80, 0xB3, 0x70, 0x23, 0x6D, 0x29, 0x68, 0x00, 0x91, 0x23, 0xF0, 0x40, 0x43, 0x07, 0x46, 0x69, 0x46, 0x30, 0x1D, +0x01, 0x93, 0x27, 0xF0, 0x49, 0xFF, 0x42, 0xF2, 0x34, 0x03, 0x39, 0xF8, 0x03, 0x30, 0xB3, 0xF5, 0xC3, 0x7F, 0x62, 0xD8, +0x03, 0xF1, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xDA, 0x00, 0x37, 0x49, 0xBB, 0x81, 0x09, 0x68, 0x36, 0x4B, 0x01, 0xEB, +0x02, 0x0C, 0x42, 0xF2, 0x34, 0x08, 0xCC, 0xF8, 0x04, 0x60, 0x88, 0x58, 0x03, 0x40, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, +0x0C, 0x03, 0x8B, 0x50, 0x99, 0xF8, 0x02, 0x3C, 0x29, 0xF8, 0x08, 0xE0, 0x01, 0x33, 0x01, 0x22, 0x00, 0x20, 0x0C, 0x21, +0x89, 0xF8, 0x02, 0x3C, 0xC7, 0xF8, 0x04, 0xC0, 0xBA, 0x73, 0x38, 0x60, 0xB9, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x02, 0xD4, 0x72, 0xB6, 0x26, 0x4B, 0x1A, 0x60, 0x26, 0x4E, 0x2B, 0x68, 0x31, 0x68, 0x22, 0x8C, 0x25, 0x48, 0x4D, 0x1C, +0x21, 0x46, 0x35, 0x60, 0x15, 0xF0, 0xEC, 0xF9, 0x23, 0x48, 0x39, 0x46, 0x14, 0xF0, 0x0E, 0xF8, 0x22, 0x4B, 0xD3, 0xF8, +0x44, 0x34, 0x98, 0x47, 0x33, 0x68, 0x00, 0x2B, 0x8D, 0xD0, 0x1B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x00, 0x2B, +0x87, 0xD1, 0x00, 0x2A, 0x85, 0xD0, 0x62, 0xB6, 0x83, 0xE7, 0x0E, 0x68, 0x00, 0x96, 0x23, 0xF0, 0x40, 0x43, 0x69, 0x46, +0x08, 0x22, 0x12, 0x20, 0x01, 0x93, 0xF9, 0xF7, 0xD7, 0xFA, 0x2B, 0x68, 0x22, 0x8C, 0x15, 0x48, 0x21, 0x46, 0x15, 0xF0, +0xC7, 0xF9, 0x72, 0xE7, 0x13, 0x4B, 0x0A, 0x68, 0x1B, 0x68, 0x1A, 0x60, 0xF6, 0xF7, 0x72, 0xF8, 0x6B, 0xE7, 0x42, 0x46, +0x43, 0x46, 0x4F, 0xF0, 0x01, 0x0E, 0x9C, 0xE7, 0x0E, 0x48, 0xF6, 0xF7, 0xED, 0xFF, 0x62, 0xE7, 0x0D, 0x48, 0xF6, 0xF7, +0xE9, 0xFF, 0x5E, 0xE7, 0x78, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x00, 0x00, 0xFF, 0x31, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x90, 0x15, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x20, 0x90, 0x15, 0x00, 0x00, 0x38, 0x18, 0x00, 0xDC, 0x8F, 0x15, 0x00, 0xD8, 0x83, 0x15, 0x00, 0x7C, 0x36, 0x17, 0x00, +0x10, 0xB5, 0x0D, 0x4C, 0x30, 0x22, 0x00, 0x21, 0x20, 0x46, 0xF0, 0xF7, 0x21, 0xFF, 0x20, 0x46, 0x13, 0xF0, 0xAE, 0xFF, +0x04, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0xAA, 0xFF, 0x04, 0xF1, 0x10, 0x00, 0x13, 0xF0, 0xA6, 0xFF, 0x04, 0xF1, 0x18, 0x00, +0x13, 0xF0, 0xA2, 0xFF, 0x04, 0xF1, 0x20, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0xF0, 0x9C, 0xBF, 0x24, 0x64, 0x17, 0x00, +0x38, 0xB5, 0xC3, 0x6C, 0x04, 0x46, 0x09, 0x48, 0x19, 0x61, 0x00, 0xEB, 0xC2, 0x00, 0x21, 0x46, 0x15, 0x46, 0x13, 0xF0, +0x93, 0xFF, 0x63, 0x6A, 0x9B, 0x02, 0x00, 0xD5, 0x38, 0xBD, 0x04, 0x4B, 0x53, 0xF8, 0x25, 0x00, 0xBD, 0xE8, 0x38, 0x40, +0x13, 0xF0, 0xE6, 0xBE, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x38, 0xB5, 0x38, 0x4B, 0x93, 0xF8, 0x8C, 0x20, +0x05, 0x46, 0x00, 0x2A, 0x42, 0xD1, 0x43, 0x6D, 0xC3, 0xF3, 0xC1, 0x23, 0x54, 0x22, 0x1C, 0x21, 0x33, 0x48, 0x12, 0xFB, +0x03, 0x13, 0x18, 0x44, 0x13, 0xF0, 0xB6, 0xFF, 0x04, 0x46, 0x31, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, +0x01, 0xDB, 0x14, 0xB9, 0x38, 0xBD, 0x00, 0x2C, 0x4C, 0xD0, 0xA2, 0x88, 0x68, 0x6D, 0x42, 0xF0, 0x20, 0x02, 0x81, 0x01, +0xA2, 0x80, 0xF5, 0xD5, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF3, 0xCF, 0x31, 0xC0, 0xF3, 0xC9, 0x33, 0x26, 0xDB, +0x62, 0x7A, 0x10, 0x3B, 0x93, 0x42, 0xE9, 0xD1, 0xEB, 0x69, 0x99, 0x68, 0x0B, 0x8A, 0x03, 0xF0, 0x1E, 0x02, 0x16, 0x2A, +0x25, 0xD0, 0x82, 0x05, 0xE0, 0xD4, 0x2A, 0x8E, 0x1C, 0x2A, 0xDD, 0xD1, 0xA2, 0x7A, 0xB2, 0xEB, 0x13, 0x3F, 0xD9, 0xD1, +0x04, 0xF1, 0xE0, 0x05, 0x12, 0x31, 0x28, 0x46, 0x0A, 0x22, 0x27, 0xF0, 0x37, 0xFE, 0xC4, 0xF8, 0xDC, 0x50, 0x1A, 0xE0, +0x93, 0xF8, 0x7E, 0x30, 0x05, 0x2B, 0xBB, 0xD1, 0x14, 0x48, 0x13, 0xF0, 0x77, 0xFF, 0x04, 0x46, 0xBF, 0xE7, 0x11, 0xF4, +0x7C, 0x7F, 0xD5, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0x10, 0x49, 0x11, 0x48, 0xD0, 0x22, 0x15, 0xF0, 0x49, 0xBB, 0x10, 0x4B, +0x28, 0x46, 0xD3, 0xF8, 0xB4, 0x33, 0x21, 0x46, 0x98, 0x47, 0x00, 0x28, 0xB4, 0xD0, 0xA3, 0x88, 0x43, 0xF0, 0x40, 0x03, +0xA3, 0x80, 0x38, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x5F, 0x12, 0x15, 0xF0, 0x34, 0xBB, +0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xE0, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x50, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0x4B, 0xB1, 0x4C, +0x1B, 0x68, 0xB1, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xED, 0x02, 0x8B, 0x87, 0xB0, 0x01, 0x46, 0x01, 0x90, 0x00, 0x2B, +0x04, 0xEB, 0xC0, 0x00, 0x08, 0xEE, 0x10, 0x0A, 0x52, 0xF8, 0x21, 0x40, 0xC0, 0xF2, 0x38, 0x83, 0x20, 0x46, 0x13, 0xF0, +0x6B, 0xFE, 0xA6, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x00, 0xF0, 0xAD, 0x80, 0x00, 0x23, 0xCD, 0xE9, +0x04, 0x33, 0x9B, 0x46, 0x98, 0x46, 0xA2, 0x4B, 0x62, 0x7F, 0x93, 0xF8, 0x00, 0x32, 0x03, 0x92, 0x01, 0x2B, 0x22, 0x7F, +0xE6, 0x6C, 0x67, 0x6C, 0x02, 0x92, 0x00, 0xF0, 0xA1, 0x80, 0x00, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0x3B, 0x79, 0xD8, 0x06, +0x40, 0xF1, 0x95, 0x80, 0x35, 0x69, 0x59, 0x06, 0x25, 0xF4, 0x00, 0x05, 0x0B, 0xF1, 0x01, 0x0B, 0x35, 0x61, 0x00, 0xF1, +0x9B, 0x81, 0xDF, 0xF8, 0x70, 0xA2, 0x00, 0x21, 0xDA, 0xF8, 0x18, 0x34, 0x20, 0x46, 0x98, 0x47, 0x63, 0x6A, 0x03, 0xF4, +0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x08, 0xBF, 0xA0, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x8B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x38, 0x92, 0xD9, 0xF8, 0x00, 0x30, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, +0xC9, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0xE4, 0xFE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, +0x5F, 0x81, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x7F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x30, 0x81, 0xE2, 0x6A, 0xD3, 0x6B, +0x98, 0x06, 0x40, 0xF1, 0xFD, 0x80, 0x15, 0xF4, 0x00, 0x05, 0x00, 0xF0, 0x7E, 0x81, 0xE1, 0x6C, 0x4F, 0x6A, 0x39, 0x88, +0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xEB, 0x81, 0x71, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x36, 0xD0, 0x63, 0x7F, +0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x6B, 0x49, 0xA0, 0x88, +0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x68, 0x4B, 0x93, 0xF8, 0x04, 0x31, +0x13, 0xB1, 0x00, 0x2D, 0x40, 0xF0, 0x33, 0x82, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, 0xFF, 0xF7, 0xC9, 0xFD, 0xE3, 0x8B, +0xDA, 0x07, 0x00, 0xF1, 0x93, 0x81, 0xA0, 0x6C, 0x30, 0xB1, 0xF7, 0xF7, 0x4F, 0xFF, 0x3B, 0x68, 0x1D, 0x78, 0x01, 0x2D, +0x00, 0xF0, 0xCB, 0x81, 0x9D, 0xF8, 0x04, 0x00, 0x21, 0x46, 0x15, 0xF0, 0x5B, 0xFB, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, +0xB3, 0xF5, 0x60, 0x1F, 0x00, 0xF0, 0x74, 0x81, 0x4F, 0x4B, 0x01, 0x9A, 0x53, 0xF8, 0x32, 0x40, 0x00, 0x2C, 0x7F, 0xF4, +0x58, 0xAF, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x4A, 0x00, 0x23, 0x40, 0x20, 0x82, 0xF8, +0x00, 0x32, 0x13, 0xF0, 0x87, 0xFD, 0x00, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0xEF, 0xF3, 0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x45, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x47, 0x4D, 0x2B, 0x68, 0x18, 0xEE, 0x10, 0x0A, 0x01, 0x33, 0x2B, 0x60, +0x13, 0xF0, 0x5A, 0xFE, 0x2B, 0x68, 0x3B, 0xB1, 0x3E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x13, 0xB9, 0x00, 0x2A, +0x40, 0xF0, 0xF3, 0x81, 0x20, 0x46, 0xD6, 0xF8, 0x10, 0x90, 0x94, 0xF8, 0x1C, 0xA0, 0x23, 0xF0, 0x95, 0xFF, 0xE2, 0x6A, +0xD3, 0x6B, 0x98, 0x06, 0x40, 0xF1, 0x8C, 0x80, 0x19, 0xF4, 0x00, 0x0F, 0x0C, 0xD0, 0xE1, 0x6C, 0x4D, 0x6A, 0x29, 0x88, +0x88, 0xB2, 0x09, 0x04, 0x00, 0xF1, 0xFE, 0x81, 0x32, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x40, 0xF0, 0x86, 0x80, +0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x42, 0xB1, 0x93, 0xF8, 0xC1, 0x34, +0x2D, 0x4F, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x07, 0xEB, 0x83, 0x07, 0x63, 0x7F, 0x09, 0x2B, 0x08, 0xD8, +0xE3, 0x8B, 0x18, 0x07, 0x05, 0xD4, 0x09, 0xF4, 0x01, 0x09, 0xB9, 0xF5, 0x80, 0x3F, 0x00, 0xF0, 0x2B, 0x82, 0x25, 0x4F, +0x9D, 0xF8, 0x04, 0x50, 0xD7, 0xF8, 0x18, 0x34, 0x00, 0x21, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0xAC, 0x33, 0x00, 0x22, +0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x22, 0x8B, 0x48, 0xF6, 0x88, 0x63, 0x9A, 0x42, 0x00, 0xF0, 0x05, 0x81, 0x63, 0x7F, +0x09, 0x2B, 0x0E, 0xD8, 0xE2, 0x7E, 0x08, 0x2A, 0x0B, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x11, 0x49, 0xA0, 0x88, +0x03, 0xF6, 0x0E, 0x03, 0x51, 0xF8, 0x23, 0x20, 0x12, 0x1A, 0x41, 0xF8, 0x23, 0x20, 0x06, 0xF1, 0x10, 0x01, 0x20, 0x46, +0xFF, 0xF7, 0x1C, 0xFD, 0xE3, 0x8B, 0xDB, 0x07, 0x00, 0xF1, 0x08, 0x81, 0x21, 0x46, 0x28, 0x46, 0x15, 0xF0, 0xB8, 0xFA, +0x62, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x24, 0x64, 0x17, 0x00, 0xC4, 0x90, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB7, 0x4F, 0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, +0x3F, 0xF4, 0x44, 0xAF, 0x15, 0xF4, 0x00, 0x05, 0x7F, 0xF4, 0x09, 0xAF, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, +0xC0, 0xF2, 0x81, 0x80, 0x00, 0x25, 0x00, 0xE7, 0xAF, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x00, 0x2B, 0x3F, 0xF4, 0x7E, 0xAF, +0x19, 0xF4, 0x00, 0x0F, 0x3F, 0xF4, 0x7A, 0xAF, 0xE3, 0x8B, 0x1D, 0x07, 0x3F, 0xF5, 0x76, 0xAF, 0x23, 0x7F, 0xA9, 0x4D, +0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x53, 0x03, 0xF1, 0x98, 0x02, 0x93, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, +0xAF, 0xFC, 0x68, 0xE7, 0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xCA, 0xAE, 0x03, 0x9B, 0xA0, 0x48, +0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xBF, 0xAE, 0xE2, 0x6C, +0xB0, 0xF8, 0x5E, 0x12, 0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xB8, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, +0x5E, 0x22, 0xB1, 0xE6, 0x95, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x59, 0x46, +0x40, 0x46, 0x04, 0x9A, 0x23, 0xF0, 0xCA, 0xFE, 0x38, 0x46, 0x02, 0xF0, 0x9D, 0xF8, 0x00, 0x23, 0x04, 0x93, 0x9B, 0x46, +0x98, 0x46, 0x8C, 0xE6, 0xD7, 0xF8, 0xDC, 0x20, 0xDA, 0xB1, 0x11, 0x88, 0x23, 0x8C, 0xA3, 0xEB, 0x11, 0x13, 0xC3, 0xF3, +0x0B, 0x03, 0x40, 0xF2, 0xFE, 0x71, 0x8B, 0x42, 0x0C, 0xD8, 0x3F, 0x2B, 0x4F, 0xEA, 0x13, 0x11, 0x08, 0xD8, 0x02, 0xEB, +0x41, 0x02, 0x03, 0xF0, 0x0F, 0x03, 0x52, 0x88, 0x42, 0xFA, 0x03, 0xF3, 0xDA, 0x07, 0x04, 0xD4, 0x4F, 0xF4, 0x80, 0x23, +0x1D, 0x43, 0x35, 0x61, 0x45, 0xE6, 0x04, 0x9B, 0x01, 0x33, 0x04, 0x93, 0x4F, 0xF4, 0x04, 0x03, 0xF6, 0xE7, 0x75, 0x4F, +0x3B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0x3F, 0xF4, 0xBF, 0xAE, 0xB4, 0xF9, 0x1E, 0x30, 0xE2, 0x8B, 0x00, 0x2B, 0xBF, 0xF6, +0x7F, 0xAF, 0x71, 0x4D, 0x02, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x53, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, +0x3F, 0xF4, 0x74, 0xAF, 0xE6, 0x6C, 0x01, 0x98, 0x00, 0x21, 0xC2, 0xF3, 0x0E, 0x03, 0x31, 0x65, 0x43, 0xF0, 0x01, 0x03, +0x61, 0x64, 0x31, 0x61, 0x02, 0x9E, 0xE3, 0x83, 0x9E, 0x30, 0xA4, 0x23, 0x13, 0xFB, 0x06, 0x00, 0xE1, 0x62, 0x61, 0x62, +0x65, 0x4A, 0x05, 0xEB, 0xC0, 0x00, 0x21, 0x46, 0x13, 0xF0, 0x60, 0xFD, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, +0x60, 0x1F, 0x00, 0xF0, 0xE4, 0x80, 0x01, 0x23, 0x05, 0x93, 0x8B, 0xE6, 0x05, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xDC, 0x80, +0x40, 0x20, 0x13, 0xF0, 0x1F, 0xFC, 0x00, 0x23, 0x05, 0x93, 0x81, 0xE6, 0x40, 0x20, 0x13, 0xF0, 0x19, 0xFC, 0x68, 0xE6, +0x33, 0x69, 0x03, 0xF0, 0x0F, 0x03, 0x09, 0x2B, 0x7F, 0xF4, 0xF5, 0xAE, 0x03, 0x9B, 0x51, 0x48, 0x4F, 0xF4, 0x1E, 0x72, +0x02, 0xFB, 0x03, 0x00, 0x90, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x3F, 0xF6, 0xEA, 0xAE, 0xE2, 0x6C, 0xB0, 0xF8, 0x5E, 0x12, +0xD2, 0x6A, 0x8A, 0x42, 0x3F, 0xF4, 0xE3, 0xAE, 0x01, 0x33, 0x80, 0xF8, 0x5D, 0x32, 0xA0, 0xF8, 0x5E, 0x22, 0xDC, 0xE6, +0x40, 0x20, 0x13, 0xF0, 0xF7, 0xFB, 0xF3, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0x61, 0xAF, 0x44, 0x49, 0x45, 0x48, +0x40, 0xF2, 0x3D, 0x22, 0x15, 0xF0, 0xE2, 0xF8, 0x59, 0xE7, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0x10, 0xAE, +0xD7, 0xF8, 0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0x09, 0xAE, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, +0x04, 0xE6, 0x3B, 0x4B, 0xD3, 0xE9, 0x01, 0x02, 0x13, 0x69, 0x98, 0x47, 0x06, 0x46, 0x00, 0x28, 0x3F, 0xF4, 0x2C, 0xAE, +0xF7, 0xF7, 0x96, 0xFE, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x02, 0x81, 0x00, 0x22, 0x34, 0x4B, 0x02, 0x60, 0x1B, 0x68, +0x42, 0x60, 0x1E, 0x44, 0x82, 0x60, 0x06, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x2F, 0x4B, +0x1D, 0x60, 0x2F, 0x49, 0xD9, 0xF8, 0x00, 0x20, 0x0B, 0x68, 0x01, 0x32, 0x43, 0xF0, 0x01, 0x03, 0xC9, 0xF8, 0x00, 0x20, +0x0B, 0x60, 0x2A, 0x4B, 0x1B, 0x68, 0x9E, 0x07, 0xFB, 0xD4, 0x29, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xE4, 0x80, +0x27, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xF0, 0x80, 0x25, 0x4B, 0x25, 0x4D, 0x1F, 0x60, 0x22, 0x48, 0xA9, 0x89, +0x03, 0x68, 0x6F, 0x60, 0x01, 0x31, 0xA9, 0x81, 0x01, 0x33, 0x1E, 0x49, 0x03, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, +0x0B, 0x60, 0x00, 0x2A, 0x3F, 0xF4, 0xEC, 0xAD, 0x18, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC9, 0xF8, 0x00, 0x20, 0x00, 0x2A, +0x7F, 0xF4, 0xE4, 0xAD, 0x00, 0x2B, 0x3F, 0xF4, 0xE1, 0xAD, 0x62, 0xB6, 0xDE, 0xE5, 0x23, 0x7F, 0x09, 0x4D, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x03, 0x55, 0x05, 0xF1, 0x98, 0x02, 0x95, 0xF8, 0x62, 0x10, 0x20, 0x46, 0xFF, 0xF7, 0x70, 0xFB, +0xBE, 0xE5, 0x62, 0xB6, 0x0A, 0xE6, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xF1, 0x12, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x90, 0x15, 0x00, +0x28, 0x60, 0x17, 0x00, 0x34, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x60, 0x00, 0x24, 0x40, 0x64, 0x00, 0x24, 0x40, +0x68, 0x00, 0x24, 0x40, 0x10, 0x60, 0x17, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x08, 0x28, 0x7F, 0xF4, 0xFD, 0xAD, 0xD5, 0xF8, +0x1A, 0x10, 0x01, 0xF0, 0x3F, 0x01, 0x07, 0x29, 0x7F, 0xF4, 0xF6, 0xAD, 0x23, 0xF0, 0x20, 0x03, 0xD3, 0x63, 0xF1, 0xE5, +0x4E, 0x4D, 0x02, 0x9B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x03, 0x50, 0xFE, 0xF7, 0xB8, 0xFE, 0x00, 0x28, 0x3F, 0xF4, +0x19, 0xAF, 0x4A, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0x13, 0xAF, 0x01, 0x9A, 0x02, 0x99, 0xA4, 0x23, +0x02, 0xF1, 0x9E, 0x06, 0x13, 0xFB, 0x01, 0x66, 0x03, 0xFB, 0x01, 0x23, 0x03, 0xF1, 0x9E, 0x04, 0x05, 0xEB, 0xC6, 0x06, +0xD7, 0xB2, 0xA1, 0x46, 0x0C, 0xE0, 0x13, 0xF0, 0x09, 0xFC, 0xDA, 0xF8, 0x24, 0x34, 0x20, 0x46, 0x39, 0x46, 0x98, 0x47, +0x3B, 0x4B, 0x93, 0xF8, 0xFF, 0x31, 0x00, 0x2B, 0x7F, 0xF4, 0xF6, 0xAE, 0x55, 0xF8, 0x39, 0x40, 0x30, 0x46, 0x00, 0x2C, +0xED, 0xD1, 0xEF, 0xE6, 0x36, 0x4B, 0x1B, 0x68, 0x1C, 0x42, 0x7F, 0xF4, 0xC3, 0xAC, 0x35, 0x49, 0x35, 0x48, 0x4F, 0xF4, +0xF2, 0x72, 0x14, 0xF0, 0xFD, 0xFF, 0xBB, 0xE4, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x0A, 0x59, 0x99, 0xF8, 0x64, 0x10, +0x00, 0x29, 0x3F, 0xF4, 0xCC, 0xAD, 0x2F, 0x48, 0x03, 0x99, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x01, 0x01, 0x91, 0xF8, +0x24, 0x10, 0x01, 0x29, 0x0F, 0xD0, 0x99, 0x07, 0x2F, 0xD4, 0x00, 0x2A, 0x3F, 0xF4, 0xBD, 0xAD, 0x97, 0xF8, 0x70, 0x30, +0x01, 0x2B, 0x7F, 0xF4, 0xB8, 0xAD, 0x97, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xB3, 0xAD, 0xE3, 0x8B, 0xE1, 0x6C, +0x01, 0x98, 0x22, 0x4A, 0xC3, 0xF3, 0x0E, 0x03, 0x00, 0x26, 0x43, 0xF0, 0x01, 0x03, 0x0E, 0x65, 0x0E, 0x61, 0x9E, 0x30, +0xE3, 0x83, 0xA4, 0x23, 0x13, 0xFB, 0x0A, 0x00, 0x05, 0xEB, 0xC0, 0x00, 0xE6, 0x62, 0x21, 0x46, 0x13, 0xF0, 0xFE, 0xFB, +0x40, 0x20, 0x13, 0xF0, 0xCB, 0xFA, 0x2F, 0xE5, 0x30, 0x46, 0xF7, 0xF7, 0x6B, 0xFC, 0x1F, 0xE5, 0x15, 0x4D, 0x6B, 0x68, +0x9B, 0xB1, 0x5F, 0x60, 0x1E, 0xE7, 0xB4, 0xF8, 0x40, 0x00, 0x20, 0xF0, 0x75, 0xFC, 0x00, 0x28, 0xD6, 0xD0, 0x99, 0xF8, +0xC0, 0x24, 0x00, 0x2A, 0x3F, 0xF4, 0x85, 0xAD, 0xC6, 0xE7, 0x0E, 0x48, 0x14, 0xF0, 0x2E, 0xFD, 0xD9, 0xF8, 0x00, 0x20, +0x09, 0xE7, 0x0C, 0x48, 0x14, 0xF0, 0x28, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x06, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, +0x61, 0xF1, 0x12, 0x00, 0x10, 0x60, 0x17, 0x00, 0xA8, 0x90, 0x15, 0x00, 0xB0, 0x90, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, +0x27, 0x4F, 0xDF, 0xF8, 0xA0, 0xA0, 0x91, 0x46, 0x06, 0x46, 0x0D, 0x46, 0x42, 0xF0, 0x70, 0x58, 0x28, 0x46, 0x13, 0xF0, +0x6D, 0xFB, 0x04, 0x46, 0x80, 0xB1, 0x42, 0x6C, 0xC1, 0x6C, 0x00, 0x2A, 0x38, 0xD0, 0xC1, 0xF8, 0x10, 0x80, 0xA2, 0x88, +0x62, 0xB9, 0x20, 0x46, 0x00, 0xF0, 0xA2, 0xF9, 0x28, 0x46, 0x13, 0xF0, 0x5D, 0xFB, 0x04, 0x46, 0x00, 0x28, 0xEE, 0xD1, +0xBD, 0xE8, 0xF0, 0x47, 0x00, 0xF0, 0xBC, 0xB9, 0x0A, 0x69, 0x42, 0xF4, 0x00, 0x02, 0x41, 0xF8, 0x10, 0x2F, 0x20, 0x46, +0xFF, 0xF7, 0x7E, 0xFA, 0xD7, 0xF8, 0x18, 0x34, 0x01, 0x21, 0x20, 0x46, 0x98, 0x47, 0x63, 0x7F, 0x09, 0x2B, 0x0D, 0xD8, +0xE2, 0x7E, 0x08, 0x2A, 0x0A, 0xD8, 0x03, 0xEB, 0xC3, 0x03, 0x13, 0x44, 0x03, 0xF6, 0x0E, 0x03, 0xA1, 0x88, 0x5A, 0xF8, +0x23, 0x20, 0x52, 0x1A, 0x4A, 0xF8, 0x23, 0x20, 0x31, 0x46, 0x20, 0x46, 0xD7, 0xF8, 0x78, 0x33, 0x98, 0x47, 0x21, 0x46, +0x30, 0x46, 0x15, 0xF0, 0x03, 0xF8, 0xBD, 0xE7, 0x0A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC1, 0xF8, 0x10, 0x90, 0xC2, 0xE7, +0x88, 0x1A, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x6C, 0x80, 0x92, 0x46, 0x06, 0x46, +0x0F, 0x46, 0x42, 0xF0, 0x70, 0x59, 0x38, 0x46, 0x13, 0xF0, 0x18, 0xFB, 0x04, 0x46, 0xF0, 0xB1, 0x42, 0x6C, 0xC3, 0x6C, +0x12, 0xB3, 0xC3, 0xF8, 0x10, 0x90, 0xA2, 0x88, 0x00, 0x21, 0x20, 0x46, 0xCA, 0xB1, 0x1D, 0x69, 0x45, 0xF4, 0x00, 0x05, +0x1D, 0x61, 0xD8, 0xF8, 0x18, 0x34, 0x98, 0x47, 0xD8, 0xF8, 0x78, 0x33, 0x20, 0x46, 0x31, 0x46, 0x98, 0x47, 0x21, 0x46, +0x30, 0x46, 0x14, 0xF0, 0xD1, 0xFF, 0x38, 0x46, 0x13, 0xF0, 0xFA, 0xFA, 0x04, 0x46, 0x00, 0x28, 0xE0, 0xD1, 0xBD, 0xE8, +0xF0, 0x47, 0x00, 0xF0, 0x59, 0xB9, 0x00, 0xF0, 0x33, 0xF9, 0xD4, 0xE7, 0x1A, 0x69, 0x00, 0x2A, 0xA8, 0xBF, 0xC3, 0xF8, +0x10, 0xA0, 0xD8, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x14, 0x46, 0x05, 0x46, 0x0F, 0x46, 0x60, 0x22, 0x00, 0x21, +0x1E, 0x46, 0xF0, 0xF7, 0x07, 0xFA, 0x4F, 0xF0, 0x01, 0x0C, 0x85, 0xF8, 0x5C, 0xC0, 0x00, 0x23, 0x07, 0x49, 0x08, 0x4A, +0xAF, 0x64, 0x07, 0xF1, 0x68, 0x00, 0xEE, 0x62, 0xEC, 0x64, 0xC4, 0xE9, 0x0F, 0x33, 0x60, 0x62, 0x61, 0x61, 0x23, 0x63, +0x63, 0x64, 0x32, 0x60, 0xF8, 0xBD, 0x00, 0xBF, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0x2D, 0xE9, 0xF8, 0x4F, +0x07, 0x46, 0x3C, 0x48, 0x3C, 0x4C, 0xDF, 0xF8, 0x08, 0xA1, 0x3C, 0x4E, 0x3C, 0x4D, 0xDF, 0xF8, 0x04, 0xB1, 0x81, 0x46, +0x13, 0xF0, 0x70, 0xFA, 0x09, 0xF1, 0x08, 0x00, 0x13, 0xF0, 0x6C, 0xFA, 0x04, 0xF5, 0xC0, 0x78, 0x00, 0x21, 0x20, 0x46, +0x60, 0x22, 0x17, 0xB1, 0x94, 0xF8, 0x5D, 0x30, 0xC3, 0xB9, 0xF0, 0xF7, 0xD1, 0xF9, 0x00, 0x22, 0x32, 0x4B, 0xC4, 0xF8, +0x48, 0xA0, 0x0A, 0xF1, 0x68, 0x0C, 0xC5, 0xE9, 0x0F, 0x22, 0x21, 0x46, 0x48, 0x46, 0xE6, 0x62, 0xE5, 0x64, 0xC5, 0xF8, +0x14, 0xB0, 0x33, 0x60, 0x84, 0xF8, 0x5C, 0x20, 0x2A, 0x63, 0x6A, 0x64, 0xC5, 0xF8, 0x24, 0xC0, 0x13, 0xF0, 0x4E, 0xFA, +0x60, 0x34, 0xA0, 0x45, 0x0A, 0xF5, 0xF4, 0x7A, 0x06, 0xF1, 0x40, 0x06, 0x05, 0xF1, 0x58, 0x05, 0xD6, 0xD1, 0x24, 0x4E, +0xDF, 0xF8, 0x88, 0x90, 0xC6, 0xF8, 0x00, 0x90, 0x00, 0x24, 0xC6, 0xE9, 0x0D, 0x44, 0xF4, 0x63, 0xF1, 0xF7, 0x8E, 0xFA, +0x80, 0x03, 0x70, 0x60, 0xF1, 0xF7, 0x8A, 0xFA, 0x01, 0x27, 0x43, 0x1C, 0x07, 0xFA, 0x03, 0xF3, 0x1B, 0x4D, 0xDF, 0xF8, +0x78, 0x80, 0xF4, 0x60, 0x01, 0x3B, 0xB3, 0x60, 0x4F, 0xF4, 0x80, 0x63, 0xC6, 0xE9, 0x04, 0x83, 0xC6, 0xE9, 0x06, 0x44, +0x34, 0x62, 0xC5, 0xF8, 0x00, 0x90, 0xC6, 0xE9, 0x0A, 0x44, 0xC5, 0xE9, 0x0D, 0x44, 0x34, 0x63, 0xEC, 0x63, 0xF1, 0xF7, +0x6F, 0xFA, 0x80, 0x03, 0x68, 0x60, 0xF1, 0xF7, 0x6B, 0xFA, 0x38, 0x44, 0x87, 0x40, 0x01, 0x3F, 0x04, 0x23, 0xC5, 0xE9, +0x02, 0x74, 0xC5, 0xE9, 0x06, 0x44, 0xC5, 0xE9, 0x0A, 0x44, 0xC5, 0xF8, 0x10, 0x80, 0x2C, 0x62, 0x2C, 0x63, 0x6B, 0x61, +0xBD, 0xE8, 0xF8, 0x8F, 0x54, 0x64, 0x17, 0x00, 0x90, 0x28, 0x17, 0x00, 0x84, 0x3B, 0x18, 0x00, 0x04, 0x3D, 0x18, 0x00, +0x1E, 0xAB, 0xDC, 0xBA, 0xC4, 0x3C, 0x18, 0x00, 0x84, 0x3C, 0x18, 0x00, 0x4C, 0x50, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, +0x04, 0x07, 0xFF, 0xFF, 0xF8, 0xB5, 0xD0, 0xE9, 0x12, 0x64, 0x63, 0x6A, 0x05, 0x46, 0x50, 0x1E, 0x03, 0x44, 0x04, 0x32, +0xC4, 0xE9, 0x0A, 0x32, 0xC1, 0xB1, 0x01, 0x29, 0x1A, 0xD0, 0x06, 0xF1, 0x28, 0x01, 0x0F, 0x46, 0x34, 0x22, 0x38, 0x46, +0x27, 0xF0, 0xD8, 0xF8, 0x0B, 0x4A, 0x13, 0x68, 0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, +0xF3, 0x64, 0xC4, 0xE9, 0x0D, 0x27, 0xE2, 0x64, 0x22, 0x62, 0xC5, 0xE9, 0x15, 0x22, 0xF8, 0xBD, 0x04, 0x49, 0x06, 0xF1, +0x28, 0x07, 0xE7, 0xE7, 0x03, 0x49, 0x06, 0xF1, 0x28, 0x07, 0xE3, 0xE7, 0xA0, 0x00, 0x32, 0x40, 0xC4, 0x3C, 0x18, 0x00, +0x84, 0x3C, 0x18, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x05, 0x48, 0x0E, 0x46, 0x13, 0xF0, 0xFE, 0xF9, 0x04, 0x46, 0x18, 0xB1, +0x32, 0x46, 0x29, 0x46, 0xFF, 0xF7, 0xC2, 0xFF, 0x20, 0x46, 0x70, 0xBD, 0x54, 0x64, 0x17, 0x00, 0x16, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x2D, 0xE9, 0xF0, 0x41, 0xC4, 0x6C, 0x00, 0x2B, 0x62, 0x6A, 0x05, 0x46, 0x0E, 0x46, 0x16, 0xDB, +0xE3, 0x6C, 0x11, 0x4F, 0x23, 0xF4, 0xF0, 0x03, 0xE3, 0x64, 0x00, 0x23, 0xC4, 0xE9, 0x06, 0x33, 0x12, 0x79, 0x23, 0x65, +0x12, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x4F, 0xF4, 0x00, 0x73, 0xA3, 0x64, 0xD7, 0xF8, 0x98, 0x33, 0x31, 0x46, 0x28, 0x46, +0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xD3, 0x07, 0xE6, 0xD5, 0x4F, 0xF4, 0xB1, 0x72, 0x05, 0x49, 0x05, 0x48, 0x14, 0xF0, +0xD9, 0xFD, 0x62, 0x6A, 0xDE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xDC, 0x90, 0x15, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x04, 0x48, 0x13, 0xF0, 0x75, 0xF9, 0xBD, 0xE8, 0x08, 0x40, 0x4F, 0xF4, +0x80, 0x20, 0x13, 0xF0, 0xCD, 0xB8, 0x00, 0xBF, 0x5C, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x5C, 0x30, 0x04, 0x46, +0x0D, 0x46, 0x43, 0xB1, 0x35, 0xB1, 0x63, 0x6D, 0x23, 0xB1, 0xA0, 0x6D, 0x00, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, +0x70, 0xBD, 0x01, 0x46, 0x01, 0x48, 0x13, 0xF0, 0x59, 0xF9, 0xF1, 0xE7, 0x54, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x4F, 0xF4, 0x80, 0x20, 0x13, 0xF0, 0xD2, 0xF8, 0xDF, 0xF8, 0x88, 0x80, 0x1D, 0x4F, 0x1E, 0x4E, 0x1E, 0x4D, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x30, 0x46, 0x01, 0x33, +0xC8, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0x80, 0xF9, 0xD8, 0xF8, 0x00, 0x30, 0x04, 0x46, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, +0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xB1, 0xD5, 0xF8, 0xF8, 0x31, 0x62, 0x6D, 0x01, 0x3B, +0xC5, 0xF8, 0xF8, 0x31, 0x32, 0xB1, 0xE3, 0x6C, 0xA0, 0x6D, 0x19, 0x6D, 0x90, 0x47, 0x94, 0xF8, 0x5E, 0x30, 0x43, 0xB9, +0x94, 0xF8, 0x5C, 0x30, 0x00, 0x2B, 0xD2, 0xD1, 0x08, 0x48, 0x21, 0x46, 0x13, 0xF0, 0x1A, 0xF9, 0xCD, 0xE7, 0x00, 0x23, +0x84, 0xF8, 0x5E, 0x30, 0xC9, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x5C, 0x64, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x54, 0x64, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0x91, +0x58, 0x4D, 0x80, 0x46, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x90, 0xF8, 0x22, 0xA0, +0x03, 0xFB, 0x0A, 0x53, 0x0F, 0x46, 0x1B, 0x6C, 0x16, 0x46, 0x00, 0x2B, 0x00, 0xF0, 0x98, 0x80, 0x50, 0x49, 0x1A, 0x79, +0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5A, 0xDB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x53, 0x18, 0x21, +0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0x1E, 0xFF, 0x04, 0x46, 0x00, 0x28, +0x59, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x55, 0x28, 0x46, 0x21, 0x46, 0x12, 0xF0, 0x11, 0xF8, 0x95, 0xF8, +0x62, 0x20, 0xA3, 0x6C, 0x02, 0x2A, 0x4F, 0xD0, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x92, 0xE8, 0x6D, 0x52, 0xF8, +0x26, 0x1F, 0xB5, 0xF8, 0x60, 0xC0, 0xB2, 0xF8, 0x04, 0xE0, 0x15, 0x68, 0xD9, 0x66, 0x91, 0x88, 0xA3, 0xF8, 0x7C, 0x10, +0x00, 0x22, 0x9D, 0x67, 0x01, 0x21, 0x48, 0x25, 0xA3, 0xF8, 0x70, 0xE0, 0xC3, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x76, 0xC0, +0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0x83, 0xF8, 0x68, 0x50, 0x83, 0xF8, 0x69, 0x10, 0x2E, 0x49, 0xB1, 0xF8, +0xFC, 0x51, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x08, 0x99, 0x01, 0x35, 0xAD, 0xB2, 0xA1, 0xF8, 0xFC, 0x51, 0x99, 0xF8, +0x22, 0x20, 0x2D, 0x01, 0xA3, 0xF8, 0x7E, 0x50, 0x20, 0x46, 0xC4, 0xE9, 0x15, 0x76, 0x22, 0x77, 0x84, 0xF8, 0x1D, 0x80, +0x05, 0x21, 0xFF, 0xF7, 0xE3, 0xFE, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0x2A, 0xA2, 0xD1, 0x20, 0x49, 0x21, 0x48, +0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xDC, 0xFC, 0x01, 0x20, 0x18, 0x21, 0xFF, 0xF7, 0xC4, 0xFE, 0x04, 0x46, 0x00, 0x28, +0xA5, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x91, 0xE8, 0x6D, 0x51, 0xF8, +0x26, 0xEF, 0x83, 0xF8, 0x69, 0x20, 0x89, 0x88, 0xA3, 0xF8, 0x70, 0x10, 0x00, 0x22, 0xB5, 0xF8, 0x60, 0x10, 0xC3, 0xF8, +0x72, 0x00, 0x4F, 0xF0, 0x48, 0x0C, 0xE8, 0x6D, 0x83, 0xF8, 0x6A, 0x20, 0x83, 0xF8, 0x6B, 0x20, 0xB5, 0xF8, 0x60, 0x20, +0xC3, 0xF8, 0x6C, 0xE0, 0x83, 0xF8, 0x68, 0xC0, 0xA3, 0xF8, 0x76, 0x10, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0x20, 0xAD, 0xE7, +0x04, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xCB, 0xDA, 0xC4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, +0x2D, 0xE9, 0xF8, 0x4F, 0xDF, 0xF8, 0x38, 0xB1, 0x49, 0x4C, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xB5, 0x06, 0x46, +0x95, 0xF8, 0x22, 0x70, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0x40, 0x98, 0x46, 0x00, 0x6C, 0x43, 0x4B, 0x8A, 0x46, +0x91, 0x46, 0x00, 0x28, 0x7A, 0xD0, 0x1B, 0x68, 0x02, 0x79, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x62, 0xDB, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x07, 0x43, 0x1A, 0x21, 0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, +0xFF, 0xF7, 0x5C, 0xFE, 0x05, 0x46, 0x00, 0x28, 0x61, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x47, 0x38, 0x46, +0x29, 0x46, 0x11, 0xF0, 0x4F, 0xFF, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xB3, 0xAC, 0x6C, 0x53, 0xF8, 0x26, 0x1F, +0x97, 0xF8, 0x62, 0xC0, 0xB3, 0xF8, 0x04, 0xE0, 0xF8, 0x6D, 0xB7, 0xF8, 0x60, 0x20, 0xA4, 0xF8, 0x76, 0x20, 0x00, 0x23, +0xA4, 0xF8, 0x70, 0xE0, 0xE1, 0x66, 0xC4, 0xF8, 0x72, 0x00, 0x84, 0xF8, 0x6A, 0x30, 0x84, 0xF8, 0x6B, 0x30, 0xBC, 0xF1, +0x00, 0x0F, 0x22, 0xD0, 0xF8, 0x6D, 0xA0, 0x67, 0x6F, 0xF0, 0x37, 0x01, 0x02, 0x23, 0xA4, 0xF8, 0x7C, 0x20, 0x84, 0xF8, +0x68, 0x10, 0x84, 0xF8, 0x69, 0x30, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0xBB, 0x00, 0x27, 0x9B, 0xF8, 0x22, 0x30, +0xA4, 0xF8, 0x80, 0xA0, 0x84, 0xF8, 0x7E, 0x70, 0x84, 0xF8, 0x7F, 0x70, 0x28, 0x46, 0xC5, 0xE9, 0x15, 0x98, 0x2B, 0x77, +0x6E, 0x77, 0x05, 0x21, 0xFF, 0xF7, 0x24, 0xFE, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x6F, 0xF0, 0x37, 0x02, 0x01, 0x23, +0xA1, 0x67, 0xA4, 0xF8, 0x7C, 0xE0, 0x84, 0xF8, 0x68, 0x20, 0x84, 0xF8, 0x69, 0x30, 0xDC, 0xE7, 0x02, 0x2A, 0x9A, 0xD1, +0x0C, 0x49, 0x0D, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x12, 0xFC, 0x01, 0x20, 0x1A, 0x21, 0xFF, 0xF7, 0xFA, 0xFD, +0x05, 0x46, 0x00, 0x28, 0x9D, 0xD1, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xF0, 0xDA, 0xE9, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, +0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x9C, 0xA1, 0xDF, 0xF8, 0x9C, 0x81, 0x4F, 0xF4, 0x1E, 0x76, +0x06, 0xFB, 0x00, 0xA6, 0x05, 0x46, 0x96, 0xF8, 0x22, 0x90, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x09, 0x80, 0x83, 0xB0, +0x00, 0x6C, 0x00, 0x93, 0x0E, 0x1E, 0x17, 0x46, 0x9D, 0xF8, 0x30, 0x40, 0x9D, 0xF8, 0x34, 0xB0, 0x55, 0x4A, 0x0C, 0xBF, +0x1E, 0x23, 0x1D, 0x23, 0x00, 0x28, 0x00, 0xF0, 0x9D, 0x80, 0x12, 0x68, 0x01, 0x79, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, +0xC0, 0xF2, 0x85, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x82, 0x92, 0xF8, 0xC0, 0x24, 0x0A, 0x43, 0x14, 0xBF, +0x01, 0x20, 0x00, 0x20, 0x19, 0x46, 0xFF, 0xF7, 0xAF, 0xFD, 0x03, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x09, 0x88, 0xD0, 0xF8, 0x48, 0x90, 0x01, 0x93, 0x40, 0x46, 0x19, 0x46, 0x11, 0xF0, 0x9E, 0xFE, +0xD9, 0xF8, 0x38, 0x00, 0x01, 0x9B, 0x40, 0x4A, 0x99, 0x6C, 0xB8, 0xF8, 0x60, 0xE0, 0x00, 0x0C, 0x4F, 0xF0, 0x00, 0x0C, +0x46, 0xEA, 0x07, 0x17, 0x00, 0x04, 0xC9, 0xF8, 0x38, 0x00, 0xD8, 0xF8, 0x5C, 0x00, 0x8F, 0x67, 0x81, 0xF8, 0x7C, 0xC0, +0x81, 0xF8, 0x7D, 0xC0, 0x81, 0xF8, 0x7E, 0xC0, 0x81, 0xF8, 0x7F, 0xC0, 0x92, 0xF8, 0x43, 0x70, 0xDF, 0xF8, 0xE8, 0x80, +0xC1, 0xF8, 0x72, 0x00, 0x24, 0x20, 0xB8, 0xF8, 0x04, 0x20, 0xA1, 0xF8, 0x76, 0xE0, 0x81, 0xF8, 0x68, 0x00, 0xD8, 0xF8, +0x00, 0xE0, 0xA1, 0xF8, 0x70, 0x20, 0xB8, 0x06, 0xC1, 0xF8, 0x6C, 0xE0, 0x81, 0xF8, 0x69, 0xC0, 0x81, 0xF8, 0x6A, 0xC0, +0x81, 0xF8, 0x6B, 0xC0, 0xC7, 0xF3, 0x40, 0x12, 0x0B, 0xD5, 0x27, 0x48, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x05, 0x02, +0x52, 0x78, 0x12, 0xF0, 0x20, 0x0F, 0x0C, 0xBF, 0x62, 0x46, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, +0x05, 0xA5, 0x64, 0x05, 0x28, 0x8C, 0x00, 0x9D, 0x44, 0xEA, 0x45, 0x34, 0x04, 0x43, 0x14, 0x43, 0xD8, 0x22, 0xC1, 0xF8, +0x80, 0x40, 0x81, 0xF8, 0x84, 0x20, 0x6E, 0xB1, 0x0E, 0x9A, 0x5A, 0x65, 0x0F, 0x9A, 0x9A, 0x65, 0x59, 0x46, 0x18, 0x46, +0xFF, 0xF7, 0x54, 0xFD, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x12, 0xF8, +0x0B, 0x20, 0x92, 0x01, 0x81, 0xF8, 0x85, 0x20, 0xEA, 0xE7, 0x02, 0x29, 0x7F, 0xF4, 0x78, 0xAF, 0x0E, 0x48, 0x0F, 0x49, +0x01, 0x93, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0x41, 0xFB, 0x01, 0x9B, 0x01, 0x20, 0x77, 0xE7, 0x01, 0x20, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xEC, 0xDB, 0x01, 0x20, 0x6C, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x62, 0x66, 0x17, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, +0x70, 0x79, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xAC, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, +0x90, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x77, 0xD1, 0x03, 0x6C, 0x04, 0x46, 0x89, 0x46, 0x00, 0x2B, 0x79, 0xD0, 0x40, 0x4A, +0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x51, 0xDB, 0x94, 0xF8, 0xC0, 0x24, 0xDF, 0xF8, 0x08, 0x81, +0x13, 0x43, 0xB8, 0xF8, 0x00, 0x10, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xFF, 0xF7, 0xEE, 0xFC, 0x06, 0x46, 0x00, 0x28, +0x54, 0xD0, 0x01, 0x46, 0x20, 0x46, 0x11, 0xF0, 0xE5, 0xFD, 0xB5, 0x6C, 0x00, 0x27, 0x50, 0x23, 0x49, 0x46, 0x85, 0xF8, +0x68, 0x30, 0x85, 0xF8, 0x69, 0x70, 0x85, 0xF8, 0x6A, 0x70, 0x85, 0xF8, 0x6B, 0x70, 0x05, 0xF1, 0x6C, 0x00, 0x06, 0x22, +0x26, 0xF0, 0x90, 0xFD, 0x2B, 0x49, 0xE0, 0x6D, 0xB1, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, 0x60, 0xC0, 0xB8, 0xF8, 0x00, 0x20, +0xB4, 0xF8, 0x60, 0xE0, 0xC5, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA5, 0xF8, 0x76, 0xC0, 0x4F, 0xEA, +0x03, 0x1C, 0xA8, 0x67, 0xA5, 0xF8, 0x7C, 0xE0, 0x18, 0x3A, 0xA1, 0xF8, 0xFC, 0x31, 0x05, 0xF1, 0x80, 0x00, 0xA5, 0xF8, +0x7E, 0xC0, 0x1E, 0x49, 0x26, 0xF0, 0x70, 0xFD, 0xC6, 0xE9, 0x15, 0x77, 0x94, 0xF8, 0x63, 0x30, 0x33, 0x77, 0xFF, 0x23, +0x73, 0x77, 0x30, 0x46, 0x05, 0x21, 0xFF, 0xF7, 0xBB, 0xFC, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x2B, 0xAB, 0xD1, +0x15, 0x49, 0x16, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0x14, 0xF0, 0xB4, 0xFA, 0xDF, 0xF8, 0x58, 0x80, 0x01, 0x20, 0xB8, 0xF8, +0x00, 0x10, 0xFF, 0xF7, 0x99, 0xFC, 0x06, 0x46, 0x00, 0x28, 0xAA, 0xD1, 0xB8, 0xF8, 0x00, 0x10, 0x0E, 0x48, 0x14, 0xF0, +0x2B, 0xF8, 0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x48, 0x19, 0x46, 0x14, 0xF0, 0x24, 0xF8, 0x01, 0x20, 0xBD, 0xE8, +0xF8, 0x83, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE0, 0xDA, 0xD9, 0xE7, 0x38, 0x36, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x2C, 0x2A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0x28, 0x91, 0x15, 0x00, +0x14, 0x91, 0x15, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x33, 0xF8, 0x11, 0x00, 0x70, 0x47, +0xA0, 0x92, 0x15, 0x00, 0x02, 0x4B, 0x40, 0xEA, 0x41, 0x01, 0x58, 0x5C, 0x70, 0x47, 0x00, 0xBF, 0x40, 0x93, 0x15, 0x00, +0xF0, 0xB4, 0x1D, 0x4C, 0x1D, 0x4D, 0x1E, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x02, 0x42, 0x16, 0x46, 0x92, 0xF8, +0x22, 0x40, 0x4F, 0xF4, 0xA4, 0x6C, 0x0C, 0xFB, 0x04, 0x54, 0x56, 0xF8, 0x26, 0x5F, 0xB4, 0xF8, 0x60, 0xC0, 0x02, 0x46, +0xE0, 0x6D, 0xB4, 0x88, 0xA2, 0xF8, 0x9C, 0x40, 0x00, 0x24, 0x54, 0x65, 0xC2, 0xF8, 0x8C, 0x40, 0x3C, 0x68, 0x3E, 0x68, +0x9D, 0xF8, 0x10, 0x70, 0xC2, 0xF8, 0x9E, 0x00, 0x24, 0x02, 0xF6, 0xB2, 0x1B, 0x03, 0xA4, 0xB2, 0x40, 0xF6, 0x08, 0x00, +0x34, 0x43, 0x40, 0xEA, 0xC7, 0x10, 0x43, 0xF0, 0x04, 0x03, 0x09, 0x01, 0xC2, 0xF8, 0x98, 0x50, 0xC2, 0xF8, 0xCC, 0x40, +0xA2, 0xF8, 0xA2, 0xC0, 0xF0, 0xBC, 0xA2, 0xF8, 0xA4, 0x30, 0xA2, 0xF8, 0xA6, 0x10, 0xC2, 0xF8, 0xBC, 0x00, 0x70, 0x47, +0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0xC2, 0x6C, 0x53, 0x6A, 0x13, 0xB3, 0x12, 0x49, +0x12, 0x4B, 0xC9, 0x6E, 0x10, 0xB5, 0x04, 0x46, 0x18, 0x68, 0x63, 0x6A, 0x92, 0x6A, 0x03, 0xF4, 0x60, 0x13, 0xB3, 0xF5, +0x60, 0x1F, 0x42, 0xF8, 0x03, 0x1C, 0x08, 0xD0, 0xB0, 0xF9, 0x00, 0x30, 0x24, 0x68, 0x00, 0x2B, 0x04, 0xDB, 0xE2, 0x6C, +0x53, 0x6A, 0x00, 0x2B, 0xED, 0xD1, 0x10, 0xBD, 0x00, 0x2C, 0xF8, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xF9, 0x22, +0x14, 0xF0, 0x0E, 0xFA, 0xE3, 0x6C, 0xFF, 0xDE, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x04, 0x46, 0x9D, 0xF8, 0x48, 0x00, +0x67, 0x6C, 0x07, 0x90, 0x9B, 0x46, 0x05, 0x28, 0x4F, 0xF0, 0x00, 0x03, 0x06, 0x91, 0x03, 0x92, 0x9A, 0x46, 0x00, 0xF0, +0x12, 0x81, 0xAA, 0x4A, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x04, 0x93, 0xDF, 0xF8, +0xC8, 0x92, 0xA6, 0x48, 0x12, 0xF0, 0xD4, 0xFD, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, +0xC0, 0xF2, 0xF3, 0x80, 0xBB, 0x88, 0xAB, 0x80, 0x7B, 0x7A, 0x6B, 0x72, 0xBB, 0x7A, 0xAB, 0x72, 0x01, 0x23, 0xEB, 0x72, +0xD7, 0xE9, 0x10, 0xC0, 0xFE, 0x6A, 0x79, 0x69, 0x3A, 0x6B, 0xEE, 0x62, 0x00, 0x23, 0x1E, 0x46, 0x69, 0x61, 0x6B, 0x62, +0x19, 0x46, 0x98, 0x46, 0x02, 0x93, 0x05, 0xF1, 0x0C, 0x03, 0xC5, 0xE9, 0x10, 0xC0, 0x2A, 0x63, 0x05, 0x93, 0x01, 0x96, +0x53, 0xE0, 0x9B, 0x45, 0x40, 0xF2, 0xB4, 0x80, 0xAB, 0xEB, 0x03, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0x03, 0x0A, +0x4F, 0xEA, 0x9A, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x03, 0x9E, 0x19, 0x44, 0xB1, 0x42, 0x5A, 0xD8, 0xB8, 0xF1, +0x00, 0x0F, 0x57, 0xD1, 0xDE, 0xF8, 0x24, 0x00, 0x28, 0xB1, 0x87, 0x4E, 0xDE, 0xF8, 0x28, 0x00, 0xF6, 0x6E, 0x40, 0xF8, +0x03, 0x6C, 0xDC, 0x45, 0x65, 0x64, 0x0D, 0xD2, 0xDE, 0xF8, 0x4C, 0x20, 0x22, 0xF4, 0xFF, 0x22, 0x22, 0xF4, 0xC0, 0x62, +0x42, 0xEA, 0x4A, 0x22, 0x42, 0xF4, 0x80, 0x70, 0x62, 0x62, 0x63, 0x46, 0xCE, 0xF8, 0x4C, 0x00, 0x69, 0x62, 0x79, 0x6A, +0x02, 0xF4, 0x60, 0x12, 0xCB, 0x1A, 0xB2, 0xF5, 0x60, 0x1F, 0x7B, 0x62, 0x00, 0xF0, 0xAA, 0x80, 0x77, 0x4A, 0xD9, 0xF8, +0x00, 0x30, 0x11, 0x68, 0x76, 0x4A, 0x91, 0xF8, 0x3E, 0x80, 0x12, 0x68, 0xB3, 0xF9, 0x00, 0x10, 0x23, 0x68, 0x02, 0xF0, +0x3F, 0x02, 0x90, 0x45, 0x94, 0xBF, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x01, 0x08, 0x00, 0x29, 0x5D, 0xDB, 0x01, 0x9A, +0x69, 0x6A, 0x02, 0x94, 0x01, 0x32, 0x01, 0x92, 0x1C, 0x46, 0xD4, 0xF8, 0x4C, 0xE0, 0x62, 0x6A, 0xDE, 0xF8, 0x2C, 0x30, +0x9D, 0xF8, 0x04, 0x00, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC2, 0xF3, 0x49, 0x2C, 0x03, 0xEB, +0x8C, 0x0C, 0x1F, 0xFA, 0x8C, 0xFC, 0xDC, 0x45, 0x97, 0xD3, 0x03, 0x9E, 0x63, 0x46, 0x19, 0x44, 0xB1, 0x42, 0xA4, 0xD9, +0x02, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x02, 0x9B, 0x5B, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x20, 0x1F, +0x41, 0xD0, 0x02, 0x9E, 0xF2, 0x6C, 0x43, 0xF4, 0x60, 0x11, 0x43, 0xF4, 0x60, 0x13, 0x50, 0x73, 0xC5, 0xF8, 0x38, 0x61, +0x73, 0x62, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x41, 0xF4, 0x80, 0x71, 0x00, 0x20, 0x00, 0x2B, 0xD1, 0x64, +0xD0, 0x61, 0x3D, 0xDB, 0x04, 0x9A, 0x92, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x82, 0xF8, 0x50, 0x30, 0x63, 0x6A, 0x03, 0xF4, +0x60, 0x13, 0xB3, 0xF5, 0x60, 0x1F, 0x73, 0xD0, 0x1C, 0x32, 0x16, 0x46, 0x48, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0x14, 0x60, +0x5B, 0x78, 0x13, 0xB9, 0x63, 0x6C, 0x0C, 0x33, 0x2B, 0x61, 0x29, 0x46, 0x30, 0x46, 0x12, 0xF0, 0xE7, 0xFC, 0x05, 0x98, +0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2B, 0x9F, 0xD1, 0x40, 0x49, 0x40, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xBD, 0x32, +0x14, 0xF0, 0x0A, 0xF9, 0x02, 0x9B, 0x96, 0xE7, 0x4F, 0xF0, 0x00, 0x0A, 0x53, 0xE7, 0x02, 0x9E, 0x3B, 0x4B, 0x01, 0x21, +0xD3, 0xF8, 0x58, 0x33, 0x30, 0x46, 0x98, 0x47, 0xF3, 0x6C, 0x75, 0x64, 0x14, 0x33, 0x05, 0x93, 0xD9, 0xF8, 0x00, 0x30, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDA, 0x04, 0x9B, 0xDB, 0x69, 0x9F, 0x42, 0xBD, 0xD0, 0x2F, 0x49, 0x32, 0x48, +0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xEA, 0xF8, 0xB6, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0x0A, 0xAF, 0x2A, 0x49, 0x2E, 0x48, +0x40, 0xF2, 0x27, 0x32, 0x14, 0xF0, 0xE0, 0xF8, 0x02, 0xE7, 0x2C, 0x4B, 0x04, 0x93, 0xF2, 0xE6, 0xD9, 0xF8, 0x00, 0x30, +0xC5, 0xF8, 0x38, 0x41, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, +0xBF, 0xFC, 0x1E, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x0B, 0xB9, 0x3B, 0x69, 0x2B, 0x61, 0x39, 0x46, 0xD7, 0xF8, 0x48, 0x01, +0x12, 0xF0, 0x70, 0xFC, 0x06, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0xA1, 0xE7, 0x04, 0x9B, +0xDB, 0x69, 0xBB, 0x42, 0xE4, 0xD0, 0x14, 0x49, 0x16, 0x48, 0x40, 0xF2, 0xC3, 0x32, 0x14, 0xF0, 0xB3, 0xF8, 0xDD, 0xE7, +0x04, 0x9E, 0x1C, 0x36, 0x30, 0x46, 0x12, 0xF0, 0x9D, 0xFC, 0x87, 0xE7, 0x0F, 0x4B, 0x07, 0x99, 0xD3, 0xF8, 0xBC, 0x33, +0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x02, 0x9B, 0xD5, 0xF8, 0x48, 0x01, 0x05, 0x93, 0x29, 0x46, 0x12, 0xF0, 0x4A, 0xFC, +0x85, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, +0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x64, 0x91, 0x15, 0x00, 0x4C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x0C, 0x46, 0x41, 0x7F, 0x63, 0x7F, 0x99, 0x42, 0x85, 0xB0, 0x05, 0xD1, 0xE3, 0x7E, 0x16, 0x46, 0xC2, 0x7E, 0x9A, 0x42, +0x05, 0x46, 0x03, 0xD0, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xE9, 0x11, 0x73, 0x00, 0x2B, 0x00, 0xF0, +0x8F, 0x80, 0xBB, 0x88, 0x13, 0xF0, 0x08, 0x00, 0xF3, 0xD0, 0x13, 0xF0, 0x02, 0x00, 0xF0, 0xD0, 0x13, 0xF0, 0x01, 0x00, +0x40, 0xF0, 0x86, 0x80, 0xDF, 0xF8, 0x4C, 0x91, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x93, 0x93, 0xF8, 0x4D, 0x20, 0x01, 0x2A, +0xE3, 0xD0, 0xD3, 0xF8, 0x34, 0x80, 0xD8, 0xE9, 0x12, 0xBA, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xDA, 0xF8, 0x20, 0x20, +0x46, 0x4B, 0x12, 0x68, 0x9A, 0x42, 0xD6, 0xD1, 0x45, 0x4A, 0x46, 0x4B, 0x11, 0x68, 0x1A, 0x68, 0x91, 0xF8, 0x3E, 0x30, +0x91, 0xF8, 0x3F, 0x10, 0x02, 0xF0, 0x3F, 0x02, 0x0B, 0x44, 0x9A, 0x42, 0xC8, 0xDD, 0xD8, 0xF8, 0x24, 0x20, 0x54, 0x23, +0x03, 0xFB, 0x06, 0x93, 0x42, 0xF4, 0x60, 0x12, 0x18, 0x6B, 0xC8, 0xF8, 0x24, 0x20, 0xC7, 0xF8, 0x38, 0x81, 0x03, 0x93, +0x03, 0xF0, 0xE0, 0xF8, 0x39, 0x4A, 0x03, 0x9B, 0x12, 0x68, 0x93, 0xF8, 0x4D, 0x10, 0x8A, 0xF8, 0x0D, 0x10, 0x52, 0x78, +0x00, 0x2A, 0x4F, 0xD1, 0xEB, 0x6C, 0x3A, 0x61, 0xD9, 0x6C, 0xCA, 0xE9, 0x06, 0x22, 0x8A, 0x02, 0x44, 0xD5, 0x6B, 0x6C, +0x07, 0xF1, 0x0C, 0x01, 0x19, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0x0A, 0xF1, 0x14, 0x00, 0x09, 0xEB, 0x03, 0x02, +0x49, 0xF8, 0x03, 0x00, 0x01, 0x23, 0xC2, 0xE9, 0x01, 0x13, 0xD8, 0xF8, 0x24, 0x30, 0xBA, 0x88, 0x43, 0xF4, 0x80, 0x73, +0xCA, 0xF8, 0x4C, 0x30, 0x42, 0xF0, 0x01, 0x03, 0xBB, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x50, 0x07, 0x06, 0xD4, +0x11, 0x07, 0x37, 0xD4, 0xA1, 0x6C, 0x4A, 0x6A, 0x42, 0xF0, 0x04, 0x02, 0x4A, 0x62, 0x9B, 0x07, 0x06, 0xD5, 0x54, 0x23, +0x03, 0xFB, 0x06, 0x93, 0x3A, 0x6B, 0x1B, 0x6B, 0x9B, 0x6A, 0x53, 0x61, 0x54, 0x24, 0x04, 0xFB, 0x06, 0x90, 0x04, 0xFB, +0x06, 0x96, 0x1C, 0x30, 0x39, 0x46, 0x12, 0xF0, 0x91, 0xFB, 0x96, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0xF2, 0x62, +0x86, 0xF8, 0x50, 0x30, 0x01, 0x20, 0x68, 0xE7, 0xBB, 0x88, 0x72, 0xE7, 0x01, 0x20, 0x64, 0xE7, 0x07, 0xF1, 0x0C, 0x01, +0x99, 0x61, 0xBA, 0xE7, 0xB8, 0x7A, 0x93, 0xF8, 0x4E, 0x30, 0x7A, 0x7A, 0xB8, 0xF8, 0x22, 0x10, 0x00, 0x93, 0x03, 0x46, +0x38, 0x46, 0xFF, 0xF7, 0x55, 0xFD, 0x07, 0xF1, 0x50, 0x03, 0xCA, 0xF8, 0x1C, 0x30, 0xB6, 0xE7, 0x42, 0xF0, 0x03, 0x03, +0xBB, 0x80, 0xC8, 0xE7, 0xDE, 0xFA, 0xFE, 0xCA, 0xC8, 0x35, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x45, 0x6C, 0x0C, 0x68, 0x6E, 0x7A, 0x60, 0x7F, 0x9D, 0xF8, 0x20, 0x70, +0x86, 0x42, 0x03, 0xD1, 0xAE, 0x7A, 0xE0, 0x7E, 0x86, 0x42, 0x02, 0xD0, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xE6, 0x6C, +0xD5, 0xF8, 0x38, 0xE1, 0xD6, 0xF8, 0x24, 0xC0, 0xDE, 0xF8, 0x4C, 0x80, 0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x82, 0x80, +0xBC, 0xF8, 0x00, 0x90, 0x19, 0xF4, 0x00, 0x4F, 0x1F, 0xFA, 0x89, 0xF0, 0x7A, 0xD1, 0x6F, 0xEA, 0x40, 0x40, 0x6F, 0xEA, +0x50, 0x40, 0xAC, 0xF8, 0x00, 0x00, 0x94, 0xF8, 0x33, 0x90, 0x94, 0xF8, 0x32, 0x00, 0x09, 0xF1, 0x04, 0x09, 0x04, 0x30, +0x84, 0xF8, 0x33, 0x90, 0x84, 0xF8, 0x32, 0x00, 0xF0, 0x6A, 0x00, 0xF1, 0x04, 0x0A, 0xB0, 0x6A, 0x00, 0xF1, 0x04, 0x09, +0xC6, 0xE9, 0x0A, 0x9A, 0x0A, 0xF1, 0x03, 0x00, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, 0x83, 0x42, 0x5C, 0xD9, +0xA3, 0xEB, 0x00, 0x09, 0x1F, 0xFA, 0x89, 0xF9, 0x09, 0xF1, 0x03, 0x09, 0x4F, 0xEA, 0x99, 0x09, 0x00, 0xEB, 0x89, 0x00, +0x80, 0xB2, 0x6B, 0x6A, 0x18, 0x44, 0x90, 0x42, 0xBA, 0xD8, 0x28, 0x4A, 0xDE, 0xF8, 0x24, 0x30, 0x4F, 0xF0, 0x54, 0x0A, +0x0A, 0xFB, 0x07, 0x27, 0x23, 0xF4, 0xC0, 0x13, 0x97, 0xF8, 0x50, 0x20, 0xDF, 0xF8, 0x90, 0xA0, 0x01, 0x3A, 0x87, 0xF8, +0x50, 0x20, 0x43, 0xF4, 0x40, 0x12, 0xCE, 0xF8, 0x24, 0x20, 0x62, 0x6A, 0xDA, 0xF8, 0x00, 0x70, 0xD4, 0xF8, 0x00, 0xE0, +0x22, 0xF4, 0xC0, 0x12, 0x42, 0xEA, 0x49, 0x29, 0x43, 0xF4, 0x40, 0x13, 0x49, 0xF4, 0xF0, 0x0A, 0x43, 0xF4, 0x80, 0x73, +0xC8, 0xF8, 0x4C, 0x30, 0x49, 0xF4, 0xF0, 0x02, 0x00, 0x23, 0x4A, 0xF4, 0x80, 0x7A, 0x06, 0xF1, 0x14, 0x09, 0xC8, 0xF8, +0x1C, 0x90, 0x62, 0x62, 0xC6, 0xF8, 0x4C, 0xA0, 0xB3, 0x61, 0xB3, 0x63, 0x68, 0x62, 0x65, 0x64, 0xC5, 0xF8, 0x38, 0x41, +0xC1, 0xF8, 0x00, 0xE0, 0x7B, 0x78, 0x03, 0xB9, 0x2B, 0x61, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x09, 0x4A, 0xB3, 0x6A, +0xD2, 0x6E, 0x43, 0xF8, 0x03, 0x2C, 0x98, 0xF8, 0x0D, 0x30, 0x01, 0x33, 0x73, 0x73, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, +0xD6, 0xF8, 0x2C, 0xA0, 0x9A, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0xAA, 0xE7, 0x20, 0x62, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, +0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x85, 0xB0, 0xD1, 0xF8, 0x00, 0xB0, 0x9D, 0xF8, 0x38, 0x90, 0xDF, 0xF8, +0x20, 0xA1, 0xDB, 0xF8, 0x44, 0x60, 0xDA, 0xF8, 0x60, 0x43, 0x03, 0x93, 0x0F, 0x46, 0x90, 0x46, 0x59, 0x46, 0x4A, 0x46, +0x05, 0x46, 0xA0, 0x47, 0x00, 0x28, 0x60, 0xD0, 0xE9, 0x6C, 0x03, 0x9B, 0xCA, 0x6A, 0x02, 0xF1, 0x03, 0x0E, 0x2E, 0xF0, +0x03, 0x0E, 0x0E, 0xF1, 0x04, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0x73, 0x45, 0x01, 0xF1, 0x14, 0x0C, 0x54, 0xD8, 0x00, 0x20, +0x72, 0x6A, 0x0E, 0xEB, 0x02, 0x03, 0x43, 0x45, 0x05, 0xD9, 0x34, 0x4A, 0x12, 0x68, 0x02, 0xF0, 0x3F, 0x02, 0x11, 0x2A, +0x5D, 0xD9, 0x32, 0x4A, 0x6C, 0x6A, 0x4F, 0xF0, 0x54, 0x0E, 0x0E, 0xFB, 0x09, 0x22, 0x24, 0xF4, 0xC0, 0x14, 0x92, 0xF8, +0x50, 0xE0, 0x44, 0xEA, 0x40, 0x24, 0x0E, 0xF1, 0xFF, 0x30, 0x82, 0xF8, 0x50, 0x00, 0x44, 0xF4, 0xD0, 0x0E, 0x72, 0x69, +0xCA, 0x61, 0xC6, 0xF8, 0x14, 0xC0, 0x73, 0x62, 0xC5, 0xF8, 0x24, 0xE0, 0xDB, 0xF8, 0x24, 0x20, 0xD6, 0xF8, 0x38, 0xC1, +0x6E, 0x64, 0x22, 0xF4, 0xC0, 0x12, 0x74, 0x46, 0x42, 0xF4, 0x40, 0x10, 0xDB, 0xF8, 0x4C, 0xE0, 0xDC, 0xF8, 0x4C, 0xC0, +0x44, 0xF4, 0x80, 0x74, 0xCC, 0x64, 0x42, 0xF4, 0x40, 0x12, 0x40, 0xF4, 0x80, 0x70, 0x00, 0x24, 0x8C, 0x63, 0xCB, 0xF8, +0x24, 0x20, 0xCE, 0xF8, 0x4C, 0x00, 0x9C, 0xF8, 0x0D, 0x20, 0x43, 0x45, 0x02, 0xF1, 0x01, 0x02, 0x8C, 0xF8, 0x0D, 0x20, +0x16, 0xD9, 0xDA, 0xF8, 0x70, 0x63, 0x03, 0x9B, 0xCD, 0xF8, 0x00, 0x90, 0x42, 0x46, 0x39, 0x46, 0x28, 0x46, 0xB0, 0x47, +0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA3, 0xEB, 0x0E, 0x04, 0xA4, 0xB2, 0x03, 0x34, 0xA0, 0x08, 0x0E, 0xEB, +0x80, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xA1, 0xE7, 0x58, 0x46, 0xFF, 0xF7, 0x53, 0xFC, 0xD6, 0xF8, 0x38, 0x31, 0x1B, 0x68, +0x3B, 0x60, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, +0x54, 0x83, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, +0x05, 0x46, 0x89, 0xB0, 0x6E, 0x6C, 0x9D, 0xF8, 0x50, 0x40, 0x04, 0x91, 0x0F, 0x46, 0x1C, 0x20, 0x54, 0x21, 0x11, 0xFB, +0x04, 0x01, 0xD6, 0xF8, 0x38, 0x01, 0x06, 0x90, 0xAB, 0x48, 0x05, 0x94, 0x41, 0x18, 0x3C, 0x68, 0x01, 0x92, 0x08, 0x46, +0x08, 0xEE, 0x10, 0x1A, 0x07, 0x93, 0xD4, 0xF8, 0x44, 0x80, 0xD4, 0xF8, 0x4C, 0x90, 0x12, 0xF0, 0x41, 0xFA, 0xA5, 0x4B, +0x05, 0x9A, 0xD3, 0xF8, 0x60, 0x33, 0x28, 0x46, 0x21, 0x46, 0x98, 0x47, 0x00, 0x23, 0x02, 0x93, 0x00, 0x28, 0x00, 0xF0, +0xF8, 0x80, 0xDF, 0xF8, 0x98, 0xA2, 0x9F, 0x48, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0x68, 0x92, 0xF8, 0x3E, 0x20, 0x03, 0xF0, +0x3F, 0x03, 0x9A, 0x42, 0x00, 0xF2, 0xFD, 0x80, 0x06, 0x9A, 0x04, 0x9D, 0x53, 0x6A, 0x2D, 0x68, 0x03, 0x90, 0x17, 0x46, +0x23, 0xF4, 0xC0, 0x13, 0xD2, 0x6C, 0x43, 0xF4, 0x40, 0x11, 0x09, 0xF1, 0x14, 0x0C, 0x92, 0xF8, 0x0D, 0xB0, 0xC2, 0xF8, +0x1C, 0xC0, 0x79, 0x62, 0x61, 0x6A, 0x07, 0x9F, 0x43, 0xF4, 0x40, 0x13, 0x21, 0xF4, 0xC0, 0x11, 0x43, 0xF4, 0x80, 0x73, +0x41, 0xF4, 0x40, 0x11, 0xD3, 0x64, 0x61, 0x62, 0x6B, 0x6A, 0x43, 0xF4, 0x80, 0x73, 0xC9, 0xF8, 0x4C, 0x30, 0x02, 0x9B, +0x99, 0x46, 0x4C, 0xE0, 0x9F, 0x42, 0x40, 0xF2, 0x93, 0x80, 0xFA, 0x1A, 0x92, 0xB2, 0x03, 0x32, 0x4F, 0xEA, 0x92, 0x09, +0x03, 0xEB, 0x89, 0x03, 0x9B, 0xB2, 0x72, 0x6A, 0x01, 0x98, 0x1A, 0x44, 0x82, 0x42, 0x53, 0xD8, 0x03, 0x9D, 0xDA, 0xF8, +0x00, 0x00, 0x2D, 0x68, 0x90, 0xF8, 0x3E, 0x00, 0x05, 0xF0, 0x3F, 0x05, 0xA8, 0x42, 0x49, 0xD8, 0xDC, 0xF8, 0x24, 0x00, +0x28, 0xB1, 0x79, 0x4D, 0xDC, 0xF8, 0x28, 0x00, 0xED, 0x6E, 0x40, 0xF8, 0x03, 0x5C, 0xBE, 0x45, 0x66, 0x64, 0x0D, 0xD2, +0xDC, 0xF8, 0x4C, 0x10, 0x21, 0xF4, 0xFF, 0x21, 0x21, 0xF4, 0xC0, 0x61, 0x41, 0xEA, 0x49, 0x21, 0x41, 0xF4, 0x80, 0x70, +0x61, 0x62, 0x73, 0x46, 0xCC, 0xF8, 0x4C, 0x00, 0x72, 0x62, 0xD8, 0xF8, 0x24, 0x20, 0x01, 0xF4, 0x60, 0x11, 0xD3, 0x1A, +0xB1, 0xF5, 0x60, 0x1F, 0xC8, 0xF8, 0x24, 0x30, 0x59, 0xD0, 0x69, 0x4B, 0x25, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x0B, 0xF1, 0x01, 0x0B, 0x00, 0x2B, 0x5F, 0xFA, 0x8B, 0xFB, 0x42, 0xDB, 0x69, 0x6A, 0x02, 0x94, 0x2C, 0x46, 0xD4, 0xF8, +0x4C, 0xC0, 0xDC, 0xF8, 0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0xC1, 0xF3, 0x49, 0x2E, +0x03, 0xEB, 0x8E, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, 0xBE, 0x45, 0xA1, 0xD3, 0x72, 0x6A, 0x01, 0x98, 0x73, 0x46, 0x1A, 0x44, +0x82, 0x42, 0xAB, 0xD9, 0xDD, 0xF8, 0x08, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x7E, 0xD0, 0xD9, 0xF8, 0x4C, 0x10, 0x81, 0xF8, +0x0D, 0xB0, 0xD9, 0xF8, 0x24, 0x30, 0xC6, 0xF8, 0x38, 0x91, 0x43, 0xF4, 0x60, 0x12, 0xC9, 0xF8, 0x24, 0x20, 0x62, 0x6A, +0x43, 0xF4, 0x60, 0x13, 0x02, 0xF4, 0x60, 0x12, 0x43, 0xF4, 0x80, 0x73, 0x00, 0x20, 0xB2, 0xF5, 0x60, 0x1F, 0xCB, 0x64, +0xC8, 0x61, 0x60, 0xD0, 0x48, 0x4B, 0x04, 0x9A, 0x1B, 0x68, 0x14, 0x60, 0x5D, 0x78, 0x00, 0x2D, 0x47, 0xD1, 0x63, 0x6C, +0x0C, 0x33, 0x33, 0x61, 0x2C, 0xE0, 0x00, 0x2D, 0xBA, 0xD1, 0x43, 0x49, 0x43, 0x48, 0x40, 0xF2, 0xF4, 0x52, 0x13, 0xF0, +0x7D, 0xFD, 0xB3, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0x71, 0xE7, 0x05, 0x9A, 0x11, 0x46, 0x37, 0x4A, 0x54, 0x23, 0x03, 0xFB, +0x01, 0x23, 0x3A, 0x49, 0x93, 0xF8, 0x50, 0x20, 0x09, 0x68, 0xC6, 0xF8, 0x38, 0x41, 0x01, 0x3A, 0x83, 0xF8, 0x50, 0x20, +0x4B, 0x78, 0x43, 0xB3, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x54, 0xF9, 0x41, 0x46, 0xD8, 0xF8, 0x48, 0x01, 0x12, 0xF0, +0x0B, 0xF9, 0x04, 0x99, 0x22, 0x68, 0xE3, 0x6C, 0x0A, 0x60, 0x00, 0x22, 0xDA, 0x61, 0x01, 0x25, 0x18, 0xEE, 0x10, 0x0A, +0x31, 0x46, 0x12, 0xF0, 0x23, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x05, 0x46, +0x31, 0x46, 0x18, 0xEE, 0x10, 0x0A, 0x12, 0xF0, 0x17, 0xF9, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, +0xF0, 0x8F, 0x00, 0x25, 0xE6, 0xE7, 0xD8, 0xF8, 0x10, 0x30, 0x33, 0x61, 0xD2, 0xE7, 0x18, 0xEE, 0x10, 0x0A, 0x31, 0x46, +0x12, 0xF0, 0x06, 0xF9, 0x02, 0x9D, 0x28, 0x46, 0x09, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0xEE, +0x10, 0x0A, 0x12, 0xF0, 0x1B, 0xF9, 0x99, 0xE7, 0x06, 0x99, 0x4A, 0x6A, 0xCD, 0x6C, 0x42, 0xF4, 0x60, 0x13, 0xC5, 0xF8, +0x1C, 0x90, 0x4B, 0x62, 0x63, 0x6A, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0x20, 0x17, 0x42, 0xF4, 0x60, 0x12, 0x43, 0xF4, +0x20, 0x13, 0x42, 0xF4, 0x80, 0x72, 0x47, 0xF4, 0x80, 0x77, 0xEA, 0x64, 0x18, 0xEE, 0x10, 0x0A, 0x63, 0x62, 0x31, 0x46, +0xCC, 0xF8, 0x4C, 0x70, 0x12, 0xF0, 0xDC, 0xF8, 0x04, 0x9B, 0x4D, 0x46, 0x1C, 0x60, 0xB4, 0xE7, 0x20, 0x62, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xA4, 0x91, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x82, 0x69, 0x03, 0x32, 0x22, 0xF0, 0x03, 0x02, +0x04, 0x32, 0x93, 0xB2, 0x99, 0x42, 0x04, 0xD9, 0xC8, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x80, 0x08, 0x70, 0x47, 0x00, 0x20, +0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x43, 0x4A, 0x44, 0x4B, 0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, +0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, 0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x3E, 0x48, +0x3C, 0x4D, 0x3E, 0x4F, 0xDF, 0xF8, 0x04, 0x81, 0x30, 0x22, 0x00, 0x21, 0x06, 0x46, 0xEE, 0xF7, 0xE3, 0xFF, 0x05, 0xF1, +0x18, 0x09, 0x3B, 0x68, 0x55, 0xF8, 0x04, 0x0B, 0x4F, 0xF4, 0xAC, 0x72, 0x02, 0xFB, 0x03, 0xF2, 0x00, 0x21, 0xEE, 0xF7, +0xD7, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x58, 0xDD, 0x4F, 0xF0, 0x00, 0x0B, 0xDA, 0x46, 0x55, 0xF8, 0x04, 0x4C, +0x30, 0x4B, 0x5C, 0x44, 0x05, 0x20, 0x04, 0xF1, 0xA8, 0x01, 0x63, 0x64, 0x2E, 0x4B, 0xC4, 0xF8, 0xA8, 0x30, 0x84, 0xF8, +0x97, 0x00, 0x04, 0xF1, 0x94, 0x03, 0x04, 0xF1, 0xAB, 0x00, 0x61, 0x67, 0x18, 0x21, 0x6F, 0xF0, 0x7B, 0x0C, 0x23, 0x66, +0x60, 0x66, 0x4F, 0xF4, 0xC0, 0x63, 0x40, 0xF2, 0x43, 0x10, 0xA1, 0x66, 0x00, 0x21, 0xC4, 0xE9, 0x21, 0x30, 0xC4, 0xE9, +0x0D, 0x11, 0xC4, 0xE9, 0x16, 0x11, 0xC4, 0xE9, 0x1E, 0x11, 0x84, 0xF8, 0x94, 0xC0, 0x84, 0xF8, 0x95, 0x10, 0x84, 0xF8, +0x96, 0x10, 0xA1, 0x62, 0xE1, 0x63, 0xE1, 0x66, 0xC4, 0xF8, 0x80, 0x10, 0x21, 0x67, 0xC4, 0xF8, 0x48, 0x61, 0xC4, 0xF8, +0x0C, 0x80, 0xC4, 0xF8, 0x50, 0x80, 0xF0, 0xF7, 0x7F, 0xF8, 0x80, 0x03, 0xC4, 0xF8, 0xAC, 0x00, 0xF0, 0xF7, 0x7A, 0xF8, +0x4F, 0xF0, 0x01, 0x0C, 0x01, 0x30, 0x0C, 0xFA, 0x00, 0xF0, 0x12, 0x4B, 0xC4, 0xF8, 0xB8, 0x30, 0x01, 0x38, 0x00, 0x21, +0xC4, 0xE9, 0x2C, 0x01, 0x21, 0x46, 0x30, 0x46, 0x12, 0xF0, 0x16, 0xF8, 0x57, 0xF8, 0x04, 0x1C, 0x0A, 0xF1, 0x01, 0x0A, +0x8A, 0x45, 0x0B, 0xF5, 0xAC, 0x7B, 0xA9, 0xDB, 0x4D, 0x45, 0x06, 0xF1, 0x08, 0x06, 0x94, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, +0xEC, 0x57, 0x18, 0x00, 0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x00, 0x01, 0x20, 0x00, +0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0xBE, 0xBA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF8, 0x43, 0x18, 0x4A, 0x19, 0x4B, +0x11, 0x68, 0x18, 0x68, 0x88, 0x42, 0x08, 0xD0, 0xD2, 0xE9, 0x01, 0x54, 0xD2, 0xE9, 0x03, 0x02, 0xC3, 0xE9, 0x00, 0x15, +0xC3, 0xE9, 0x02, 0x40, 0x1A, 0x61, 0x13, 0x4C, 0x13, 0x4F, 0x11, 0x4E, 0x04, 0xF1, 0x30, 0x09, 0x20, 0x46, 0x11, 0xF0, +0xDB, 0xFF, 0x57, 0xF8, 0x04, 0x3B, 0x00, 0x2B, 0x0E, 0xDD, 0x00, 0x25, 0xA8, 0x46, 0x31, 0x68, 0x20, 0x46, 0x29, 0x44, +0x11, 0xF0, 0xD4, 0xFF, 0x57, 0xF8, 0x04, 0x3C, 0x08, 0xF1, 0x01, 0x08, 0x98, 0x45, 0x05, 0xF5, 0xAC, 0x75, 0xF2, 0xDB, +0x08, 0x34, 0x4C, 0x45, 0x06, 0xF1, 0x04, 0x06, 0xE4, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xEC, 0x57, 0x18, 0x00, +0x74, 0x1F, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, 0x8C, 0x1F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x28, 0x82, 0xB0, +0x06, 0x46, 0x00, 0xF0, 0xBD, 0x80, 0x6A, 0x4C, 0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x04, 0xEB, 0x83, 0x04, +0x94, 0xF8, 0x4D, 0x30, 0xE7, 0x6A, 0x65, 0x6B, 0x01, 0x2B, 0x69, 0xD1, 0xD5, 0xE9, 0x12, 0x38, 0x00, 0x22, 0x4F, 0xF4, +0x80, 0x71, 0x6A, 0x62, 0xC8, 0xF8, 0x1C, 0x20, 0xC8, 0xF8, 0x4C, 0x10, 0x00, 0x2B, 0x4C, 0xD0, 0xBA, 0x88, 0x11, 0x07, +0x49, 0xD5, 0xD3, 0xE9, 0x17, 0x21, 0x28, 0x33, 0xC8, 0xF8, 0x34, 0x10, 0xC8, 0xF8, 0x48, 0x20, 0xC8, 0xF8, 0x38, 0x30, +0x2B, 0x7F, 0x58, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x63, 0xBB, 0x55, 0x4A, +0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x23, 0xD5, 0xEB, 0x8B, 0x13, 0xF4, +0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0xC3, 0xB9, 0xD8, 0xF8, +0x24, 0x10, 0x0B, 0x88, 0x9A, 0xB2, 0x1B, 0x04, 0x12, 0xD5, 0xC2, 0xF3, 0x0E, 0x02, 0x0A, 0x80, 0x95, 0xF8, 0x33, 0x20, +0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD8, 0xE9, 0x0A, 0x32, +0x04, 0x3A, 0x04, 0x3B, 0xC8, 0xE9, 0x0A, 0x32, 0x28, 0x46, 0x02, 0xF0, 0x71, 0xFC, 0x3E, 0x4B, 0x08, 0xF1, 0x14, 0x01, +0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x08, 0x46, 0x98, 0x47, 0xD7, 0xF8, 0x48, 0x01, 0x39, 0x46, 0x11, 0xF0, 0x4A, 0xFF, +0x00, 0x23, 0x6B, 0x64, 0x94, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x33, 0x84, 0xF8, 0x50, 0x30, 0xE2, 0x62, 0x02, 0xB0, +0xBD, 0xE8, 0xF0, 0x87, 0x6B, 0x6A, 0xDF, 0xF8, 0xCC, 0x90, 0x20, 0x6B, 0xD5, 0xE9, 0x12, 0xA8, 0x43, 0xF4, 0x60, 0x13, +0x6B, 0x62, 0xC7, 0xF8, 0x38, 0x51, 0x02, 0xF0, 0x37, 0xFC, 0x94, 0xF8, 0x4D, 0x20, 0xD9, 0xF8, 0x00, 0x30, 0x88, 0xF8, +0x0D, 0x20, 0x5B, 0x78, 0x00, 0x2B, 0x34, 0xD1, 0x3B, 0x61, 0x6B, 0x6A, 0xB9, 0x88, 0x43, 0xF4, 0x80, 0x73, 0x41, 0xF0, +0x01, 0x02, 0xC8, 0xF8, 0x4C, 0x30, 0xBA, 0x80, 0xBA, 0xF1, 0x00, 0x0F, 0x09, 0xD0, 0x4D, 0x07, 0x07, 0xD4, 0x08, 0x07, +0x31, 0xD4, 0x23, 0x6B, 0x99, 0x6C, 0x4B, 0x6A, 0x43, 0xF0, 0x04, 0x03, 0x4B, 0x62, 0x93, 0x07, 0x10, 0xD5, 0xD9, 0xF8, +0x00, 0x30, 0x5B, 0x78, 0xA3, 0xB9, 0x08, 0xF1, 0x14, 0x01, 0x23, 0x6B, 0x3A, 0x6B, 0x98, 0x6A, 0x15, 0x4B, 0x50, 0x61, +0xD3, 0xF8, 0x9C, 0x33, 0x32, 0x46, 0x07, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0x39, 0x46, 0x04, 0xF1, 0x1C, 0x00, 0x11, 0xF0, +0xF9, 0xFE, 0xAF, 0xE7, 0x0F, 0x4C, 0x47, 0xE7, 0x07, 0xF1, 0x50, 0x01, 0xE9, 0xE7, 0x94, 0xF8, 0x4E, 0x00, 0xBB, 0x7A, +0x7A, 0x7A, 0x69, 0x8C, 0x00, 0x90, 0x38, 0x46, 0xFF, 0xF7, 0xCA, 0xF8, 0x07, 0xF1, 0x50, 0x03, 0xC8, 0xF8, 0x1C, 0x30, +0xBD, 0xE7, 0x41, 0xF0, 0x03, 0x02, 0xBA, 0x80, 0xCF, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0xD0, 0xF8, 0x4C, 0x90, 0x8B, 0xB0, 0x09, 0xF1, 0x14, 0x03, 0x05, 0x29, 0x04, 0x46, 0x0E, 0x46, 0x00, 0x93, 0x00, 0xF0, +0xAD, 0x81, 0x57, 0x4D, 0x01, 0xEB, 0x41, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x05, 0xEB, 0x83, 0x05, 0x94, 0xF8, 0x1B, 0xB0, +0x94, 0xF8, 0x1D, 0xA0, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x50, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0xDF, 0xF8, 0x40, 0x81, 0xEA, 0x6A, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x79, 0xD0, +0x4A, 0x4F, 0x06, 0xE0, 0xD7, 0xF8, 0x5C, 0x33, 0x30, 0x46, 0x98, 0x47, 0xEA, 0x6A, 0x00, 0x2A, 0x70, 0xD0, 0x63, 0x6A, +0x99, 0x02, 0xF5, 0xD5, 0x03, 0xF4, 0x60, 0x11, 0xB1, 0xF5, 0x20, 0x1F, 0xF0, 0xD0, 0x50, 0x7A, 0x61, 0x7F, 0x88, 0x42, +0xEC, 0xD1, 0x90, 0x7A, 0xE1, 0x7E, 0x88, 0x42, 0xE8, 0xD1, 0xD9, 0xF8, 0x2C, 0x10, 0xB5, 0xF8, 0x48, 0x00, 0x03, 0x31, +0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x89, 0xB2, 0x88, 0x42, 0x00, 0xF2, 0x5D, 0x81, 0x00, 0x20, 0x03, 0x90, 0x05, 0x90, +0x86, 0x46, 0x68, 0x6B, 0x01, 0x90, 0x50, 0x6A, 0x02, 0x90, 0x01, 0x98, 0x95, 0xF8, 0x4F, 0xC0, 0xC0, 0x6C, 0x04, 0x90, +0x03, 0x98, 0xA5, 0xF8, 0x4A, 0xE0, 0x08, 0x44, 0x02, 0x99, 0x05, 0xEB, 0x8C, 0x0E, 0x08, 0x44, 0x4F, 0xEA, 0x8C, 0x01, +0x03, 0x91, 0xDE, 0xF8, 0x38, 0x10, 0x88, 0x42, 0x40, 0xF2, 0x82, 0x81, 0x95, 0xF8, 0x4E, 0x10, 0x61, 0x45, 0xBB, 0xD9, +0x95, 0xF8, 0x4D, 0x10, 0x01, 0x29, 0xB7, 0xD0, 0xDE, 0xF8, 0x3C, 0xE0, 0x70, 0x45, 0xB3, 0xD8, 0x03, 0x9F, 0x17, 0x44, +0xBB, 0x46, 0x01, 0x9F, 0xCB, 0xF8, 0x3C, 0x71, 0x0C, 0xF1, 0x01, 0x0C, 0x02, 0x9F, 0xCB, 0xF8, 0x34, 0x70, 0x85, 0xF8, +0x4F, 0xC0, 0x05, 0x9F, 0x62, 0x64, 0x43, 0xEA, 0x47, 0x23, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xE0, 0x03, 0x63, 0x62, +0xC9, 0xF8, 0x4C, 0x30, 0x04, 0x9B, 0x1F, 0x46, 0x00, 0x9B, 0xFB, 0x61, 0x50, 0x62, 0x95, 0xF8, 0x4C, 0x20, 0x6C, 0x63, +0x4B, 0x1C, 0xDB, 0xB2, 0x9A, 0x42, 0x85, 0xF8, 0x4D, 0x30, 0x0D, 0xD8, 0x10, 0x4B, 0x30, 0x46, 0xD3, 0xF8, 0x5C, 0x33, +0x98, 0x47, 0x07, 0xE0, 0x63, 0x6A, 0x98, 0x02, 0x1C, 0xD4, 0x95, 0xF8, 0x50, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x50, 0x30, +0xD8, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x00, 0x20, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA3, 0x6A, 0xDB, 0x0A, 0x13, 0xF0, 0x06, 0x0F, 0xDD, 0xD0, 0xB0, 0x48, +0x00, 0xEB, 0xC6, 0x00, 0x11, 0xF0, 0x4A, 0xFE, 0xE8, 0x62, 0x00, 0x28, 0x00, 0xF0, 0xEA, 0x80, 0xAC, 0x4F, 0x80, 0xF8, +0x0A, 0xB0, 0x00, 0x23, 0x01, 0x21, 0x3A, 0x68, 0x80, 0xF8, 0x09, 0xA0, 0x03, 0x72, 0x43, 0x60, 0xC1, 0x72, 0xA3, 0x6A, +0xB2, 0xF9, 0x00, 0x20, 0x61, 0x7F, 0x03, 0x91, 0xC3, 0xF3, 0xC1, 0x1B, 0xC3, 0xF3, 0xC7, 0x21, 0x00, 0x2A, 0xC3, 0xF3, +0xC2, 0x23, 0x01, 0x93, 0xC0, 0xF2, 0xD2, 0x80, 0x01, 0x9B, 0x05, 0x2B, 0x00, 0xF0, 0xD9, 0x80, 0xD4, 0xF8, 0x28, 0xA0, +0x63, 0x7F, 0x05, 0x93, 0x0A, 0xF0, 0x7F, 0x03, 0x04, 0x93, 0xCA, 0xF3, 0x40, 0x23, 0x06, 0x93, 0x01, 0x9B, 0x04, 0x2B, +0x3B, 0x68, 0x00, 0xF0, 0xF2, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x01, 0x81, 0x94, 0x4A, 0x05, 0x99, +0x02, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x04, 0x9A, 0x9B, 0x8A, 0x08, 0x93, 0xC2, 0xF3, 0xC1, 0x02, +0x01, 0x32, 0x09, 0x92, 0x0A, 0xF0, 0x07, 0x0A, 0x8D, 0x4B, 0x05, 0x93, 0x8D, 0x4B, 0x9C, 0x46, 0x06, 0x9B, 0x00, 0x27, +0x43, 0xEA, 0xCA, 0x0A, 0x5F, 0xFA, 0x8B, 0xF3, 0x19, 0x46, 0x05, 0xF1, 0x38, 0x0B, 0x04, 0x93, 0x85, 0xF8, 0x4E, 0x10, +0x00, 0x23, 0x31, 0x1D, 0xCD, 0xF8, 0x18, 0x90, 0x07, 0x94, 0xD1, 0x46, 0x85, 0xF8, 0x4F, 0x30, 0xDA, 0x46, 0x1E, 0x46, +0x64, 0x46, 0x8B, 0x46, 0x01, 0x2A, 0xF1, 0xB2, 0x00, 0xF0, 0xA8, 0x80, 0x48, 0x46, 0xA0, 0x47, 0x7E, 0x4B, 0x09, 0x9A, +0x33, 0xF8, 0x1B, 0xC0, 0x08, 0x99, 0x02, 0xFB, 0x0C, 0xFC, 0x00, 0xFB, 0x0C, 0xF0, 0xF8, 0x40, 0x81, 0x42, 0x28, 0xBF, +0x01, 0x46, 0x4A, 0xF8, 0x04, 0x1B, 0x95, 0xF8, 0x4E, 0x10, 0x01, 0x36, 0x8E, 0x42, 0xE5, 0xDD, 0xCA, 0x46, 0x04, 0x99, +0x05, 0x9B, 0x50, 0x46, 0xDD, 0xE9, 0x06, 0x94, 0x98, 0x47, 0x03, 0x9B, 0xD5, 0xF8, 0x38, 0xC0, 0x1E, 0x46, 0x02, 0x9B, +0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x32, 0x09, 0x9B, 0x16, 0x7F, 0xEA, 0x6A, 0x03, 0xFB, 0x06, 0xF6, 0x00, 0xFB, +0x06, 0xF6, 0xFE, 0x40, 0xB6, 0xB2, 0xA5, 0xF8, 0x48, 0x60, 0xE1, 0x7E, 0x63, 0x7F, 0xEF, 0x6B, 0x9E, 0x20, 0x00, 0xFB, +0x03, 0x13, 0x02, 0x99, 0x28, 0x6C, 0x01, 0xEB, 0x83, 0x03, 0x4F, 0xF0, 0x01, 0x0E, 0x93, 0xF8, 0x5A, 0x31, 0x85, 0xF8, +0x4C, 0x30, 0xD9, 0xF8, 0x2C, 0x10, 0x00, 0x9B, 0x53, 0x61, 0x03, 0x31, 0x21, 0xF0, 0x03, 0x01, 0x04, 0x31, 0x00, 0x23, +0x89, 0xB2, 0x51, 0x62, 0xC2, 0xF8, 0x54, 0x01, 0xC2, 0xE9, 0x53, 0xC7, 0xC2, 0xE9, 0x0D, 0x33, 0x93, 0x64, 0x93, 0x61, +0xD3, 0x63, 0x85, 0xF8, 0x4D, 0xE0, 0xD9, 0xF8, 0x2C, 0x00, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x00, 0x04, 0x30, 0x80, 0xB2, +0xB0, 0x42, 0x57, 0xD2, 0x30, 0x1A, 0x80, 0xB2, 0x03, 0x30, 0x83, 0x10, 0x01, 0xEB, 0x83, 0x01, 0x80, 0x08, 0x5B, 0x02, +0x66, 0x6A, 0xA5, 0xF8, 0x4A, 0x00, 0x33, 0x43, 0x23, 0xF4, 0xC0, 0x13, 0x43, 0xF4, 0xD0, 0x03, 0x51, 0x62, 0xC5, 0xE9, +0x0C, 0x44, 0x63, 0x62, 0x62, 0x64, 0xC9, 0xF8, 0x4C, 0x30, 0xFF, 0xE6, 0xA0, 0xEB, 0x01, 0x0E, 0x1F, 0xFA, 0x8E, 0xFE, +0x0E, 0xF1, 0x03, 0x0E, 0x4F, 0xEA, 0xAE, 0x00, 0x05, 0x90, 0x80, 0x00, 0x4F, 0xEA, 0x9E, 0x0E, 0x03, 0x90, 0x98, 0xE6, +0x3D, 0x4D, 0x57, 0xE6, 0x60, 0x62, 0xE8, 0xE6, 0x11, 0xF0, 0x06, 0x0F, 0x7F, 0xF4, 0x2A, 0xAF, 0x3A, 0x49, 0x3B, 0x48, +0x4F, 0xF4, 0xEA, 0x72, 0x13, 0xF0, 0x60, 0xF9, 0x22, 0xE7, 0x09, 0xAB, 0x08, 0xAA, 0x01, 0x99, 0x20, 0x46, 0x02, 0xF0, +0x39, 0xF9, 0x36, 0x4B, 0x05, 0x93, 0x36, 0x4B, 0x94, 0xF8, 0x36, 0x70, 0x09, 0x9A, 0x9C, 0x46, 0x2B, 0x4B, 0x02, 0x93, +0x82, 0x46, 0xC7, 0xF3, 0x40, 0x17, 0x3F, 0xE7, 0x01, 0x9B, 0x04, 0x2B, 0x7F, 0xF4, 0x54, 0xAF, 0x4F, 0xEA, 0xE9, 0x02, +0x00, 0x2E, 0x7F, 0xF4, 0x4F, 0xAF, 0x09, 0x2A, 0x04, 0xBF, 0x09, 0xF0, 0x07, 0x03, 0x43, 0xF0, 0x40, 0x09, 0x47, 0xE7, +0x18, 0x46, 0xAD, 0xE7, 0x95, 0xF8, 0x4D, 0x10, 0x93, 0xE6, 0x04, 0x9A, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x09, 0x4A, 0x1C, +0x00, 0x2B, 0x0A, 0xF0, 0x0F, 0x0A, 0x09, 0x92, 0x14, 0xDB, 0x19, 0x49, 0x05, 0x98, 0x02, 0x91, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x00, 0x13, 0x1B, 0x69, 0x08, 0x93, 0x0E, 0xE7, 0x1A, 0xF0, 0x60, 0x0F, 0x3F, 0xF4, 0xFB, 0xAE, 0x17, 0x49, +0x1A, 0x48, 0x4F, 0xF4, 0xD2, 0x72, 0x13, 0xF0, 0x19, 0xF9, 0xF3, 0xE6, 0x03, 0x29, 0x04, 0xD8, 0xBA, 0xF1, 0x09, 0x0F, +0x0D, 0xD8, 0x09, 0x9A, 0xE3, 0xE7, 0x10, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x9B, 0x12, 0x13, 0xF0, 0x0B, 0xF9, 0x3B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDB, 0xF1, 0xE7, 0x0A, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xCE, 0x72, 0x13, 0xF0, +0xFF, 0xF8, 0xEA, 0xE7, 0x64, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x85, 0x06, 0x13, 0x00, +0x75, 0x06, 0x13, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0x91, 0x15, 0x00, +0x21, 0x3B, 0x13, 0x00, 0x05, 0x3B, 0x13, 0x00, 0x0C, 0x92, 0x15, 0x00, 0xE0, 0x91, 0x15, 0x00, 0xFC, 0x91, 0x15, 0x00, +0xC3, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xC3, 0x72, 0x03, 0xB1, 0x70, 0x47, 0x01, 0x46, 0xD0, 0xF8, 0x48, 0x01, 0x11, 0xF0, +0x83, 0xBC, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xD0, 0xE9, 0x12, 0x67, 0x00, 0x23, 0x4F, 0xF4, 0x80, 0x72, 0x43, 0x62, +0x43, 0x64, 0xFB, 0x61, 0xFA, 0x64, 0x00, 0x2E, 0x00, 0xF0, 0x81, 0x80, 0xD0, 0xF8, 0x2C, 0x80, 0x8A, 0x46, 0x05, 0x46, +0x06, 0xF1, 0x28, 0x09, 0x08, 0xF1, 0x40, 0x01, 0x43, 0x46, 0x06, 0xF1, 0x24, 0x02, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, +0x04, 0x4F, 0x8B, 0x42, 0xF9, 0xD1, 0xEB, 0x8B, 0x9C, 0x04, 0x22, 0xD5, 0x48, 0x4B, 0x49, 0x49, 0x1A, 0x68, 0x6B, 0x7F, +0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x41, 0x61, 0xDB, +0xD8, 0xF8, 0x14, 0x20, 0xD4, 0xF8, 0x9C, 0x30, 0x32, 0x64, 0xD8, 0xF8, 0x24, 0x20, 0x32, 0x65, 0xC3, 0xF3, 0xC2, 0x22, +0x05, 0x2A, 0xF3, 0x63, 0x5D, 0xD0, 0xD8, 0xF8, 0x3C, 0x30, 0x58, 0x07, 0x03, 0xD4, 0xF3, 0x6A, 0x23, 0xF4, 0xC0, 0x73, +0xF3, 0x62, 0x39, 0x4A, 0x2B, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x7B, 0xB1, +0x73, 0x6A, 0x43, 0xF0, 0x10, 0x03, 0x28, 0x46, 0x73, 0x62, 0x02, 0xF0, 0x47, 0xF9, 0xD6, 0xE9, 0x17, 0x23, 0x07, 0xF1, +0x14, 0x00, 0xC7, 0xE9, 0x0D, 0x39, 0xBA, 0x64, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x4A, 0x6B, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, +0x01, 0xFB, 0x03, 0x23, 0x5B, 0x68, 0x99, 0x06, 0xE6, 0xD5, 0xBA, 0xF1, 0x00, 0x0F, 0xE3, 0xD1, 0xEB, 0x8B, 0x13, 0xF4, +0x00, 0x5F, 0xEB, 0x6A, 0xDB, 0x6B, 0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x00, 0x2B, 0xD7, 0xD1, +0x79, 0x6A, 0x0A, 0x88, 0x93, 0xB2, 0x12, 0x04, 0xD2, 0xD5, 0xC3, 0xF3, 0x0E, 0x03, 0x0B, 0x80, 0x95, 0xF8, 0x33, 0x20, +0x95, 0xF8, 0x32, 0x30, 0x04, 0x3A, 0x04, 0x3B, 0x85, 0xF8, 0x33, 0x20, 0x85, 0xF8, 0x32, 0x30, 0xD7, 0xE9, 0x0A, 0x32, +0x04, 0x3A, 0x04, 0x3B, 0xC7, 0xE9, 0x0A, 0x32, 0xBE, 0xE7, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0x9B, 0xD1, +0x12, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0x13, 0xF0, 0x3C, 0xF8, 0x94, 0xE7, 0x03, 0xF4, 0xC0, 0x63, 0xF2, 0x6C, +0x94, 0xF8, 0xA1, 0x10, 0xB3, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x30, 0x4F, 0xF4, 0x00, 0x30, 0x22, 0xF4, +0x40, 0x33, 0x03, 0x43, 0x19, 0xB1, 0x43, 0xF4, 0x80, 0x23, 0xF3, 0x64, 0x8D, 0xE7, 0x23, 0xF4, 0x80, 0x23, 0xF3, 0x64, +0x89, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x05, 0x28, 0x89, 0xB0, 0x81, 0x46, 0x00, 0xF0, 0x79, 0x81, 0xBE, 0x4A, +0x00, 0xEB, 0x40, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x03, 0x93, 0x03, 0x9B, 0xDC, 0x68, 0xBA, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDA, 0x5D, 0xE1, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, 0x80, 0xF2, +0xFE, 0x80, 0x24, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0xFA, 0x80, 0x63, 0x6A, 0x9A, 0x02, 0xF3, 0xD5, 0xB0, 0x4D, 0x2A, 0x68, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x80, 0x81, 0xAE, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0xDB, 0xB2, 0x07, 0xEB, +0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0x63, 0x6A, 0xAA, 0x49, 0x43, 0xF4, 0x60, 0x10, 0x09, 0x68, 0x60, 0x62, +0x49, 0x78, 0x23, 0xF4, 0xC0, 0x13, 0x00, 0x29, 0x40, 0xF0, 0x58, 0x81, 0x43, 0xF4, 0x60, 0x13, 0x43, 0xF4, 0x80, 0x73, +0x00, 0x2A, 0x26, 0x68, 0xEB, 0x64, 0xE9, 0x61, 0xC0, 0xF2, 0x57, 0x81, 0x72, 0x6A, 0x02, 0xF4, 0x60, 0x1A, 0xBA, 0xF5, +0x60, 0x1F, 0x00, 0xF0, 0xEC, 0x80, 0x9D, 0x48, 0x50, 0xF8, 0x39, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0xE6, 0x80, 0x00, 0xEB, +0xC9, 0x00, 0x11, 0xF0, 0xAD, 0xFB, 0xBB, 0x88, 0x83, 0x80, 0x7B, 0x7A, 0x43, 0x72, 0xBB, 0x7A, 0x83, 0x72, 0x01, 0x23, +0xC3, 0x72, 0x72, 0x6A, 0xD6, 0xF8, 0x4C, 0xA0, 0xF9, 0x6A, 0xD7, 0xF8, 0x4C, 0xB1, 0xB5, 0x6C, 0x05, 0x95, 0x04, 0x46, +0xD7, 0xE9, 0x10, 0x03, 0x22, 0xF4, 0xC0, 0x12, 0xE1, 0x62, 0x42, 0xF4, 0x20, 0x12, 0x00, 0x21, 0xC4, 0xE9, 0x10, 0x03, +0xA1, 0x64, 0x3B, 0x6B, 0x72, 0x62, 0xCA, 0xF8, 0x4C, 0x20, 0xC4, 0xF8, 0x4C, 0xB1, 0x06, 0x93, 0xD7, 0xF8, 0x50, 0x31, +0xC4, 0xF8, 0x50, 0x31, 0xD7, 0xF8, 0x54, 0x31, 0xC4, 0xF8, 0x54, 0x31, 0x04, 0xF1, 0x0C, 0x03, 0x0A, 0xF1, 0x14, 0x0C, +0x28, 0x35, 0xC4, 0xE9, 0x0D, 0x11, 0xA1, 0x61, 0xE1, 0x63, 0x61, 0x62, 0x04, 0x93, 0x04, 0xF5, 0x82, 0x73, 0xC4, 0xF8, +0x14, 0xC0, 0x25, 0x63, 0xBC, 0x46, 0x08, 0x46, 0x57, 0x46, 0x07, 0x93, 0xAA, 0x46, 0x8E, 0x46, 0x25, 0x46, 0x0C, 0x46, +0x06, 0xE0, 0x5A, 0x6A, 0xDF, 0x6C, 0xD8, 0xF8, 0x34, 0x00, 0xD8, 0xF8, 0x4C, 0xB1, 0x1E, 0x46, 0xFB, 0x6A, 0x03, 0x33, +0xC2, 0xF3, 0x49, 0x28, 0x23, 0xF0, 0x03, 0x03, 0x03, 0xEB, 0x88, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x18, 0x44, 0x01, 0x31, +0x58, 0x45, 0x02, 0xF4, 0x60, 0x12, 0xC9, 0xB2, 0x06, 0xD9, 0x05, 0xEB, 0x8E, 0x00, 0x0E, 0xF1, 0x01, 0x0E, 0x44, 0x63, +0x5F, 0xFA, 0x8E, 0xFE, 0x05, 0xEB, 0x8E, 0x08, 0x1C, 0x44, 0xC8, 0xF8, 0x3C, 0x61, 0xB2, 0xF5, 0x60, 0x1F, 0x33, 0x68, +0x75, 0x64, 0x6C, 0x62, 0x00, 0xF0, 0x18, 0x81, 0x00, 0x2B, 0xD2, 0xD1, 0x2C, 0x46, 0x98, 0x46, 0x55, 0x46, 0xC4, 0xF8, +0x38, 0x61, 0xBA, 0x46, 0x67, 0x46, 0x03, 0x98, 0x8A, 0xF8, 0x0D, 0x10, 0x90, 0xF8, 0x50, 0x30, 0x03, 0xF1, 0x01, 0x0C, +0x03, 0x46, 0x22, 0x46, 0x1C, 0x30, 0x83, 0xF8, 0x50, 0xC0, 0x39, 0x46, 0x11, 0xF0, 0xA0, 0xFB, 0x53, 0x4B, 0x1B, 0x68, +0x58, 0x78, 0x00, 0x28, 0x40, 0xF0, 0x11, 0x81, 0xD7, 0xF8, 0x38, 0x11, 0xF2, 0x6C, 0xDF, 0xF8, 0x30, 0xC1, 0xC9, 0x6C, +0xD0, 0x61, 0x54, 0x23, 0x03, 0xFB, 0x09, 0xF3, 0x3A, 0x69, 0x5C, 0xF8, 0x03, 0x00, 0x22, 0x61, 0x14, 0x31, 0x04, 0x9A, +0x3A, 0x61, 0x88, 0x42, 0x63, 0x44, 0x00, 0xF0, 0x2A, 0x81, 0x06, 0x9B, 0x07, 0x9A, 0xA3, 0xF1, 0x28, 0x00, 0x05, 0x9B, +0xC0, 0x1A, 0x03, 0xF1, 0x5C, 0x01, 0x2B, 0x18, 0x1C, 0x68, 0x45, 0xF8, 0x04, 0x4B, 0x1B, 0x68, 0x42, 0xF8, 0x04, 0x3B, +0x8D, 0x42, 0xF6, 0xD1, 0x3B, 0x4C, 0x48, 0x46, 0xFC, 0xF7, 0x10, 0xF8, 0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xD7, 0xF8, 0x38, 0x31, 0x04, 0xDB, 0xB3, 0x42, 0x1C, 0xD1, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0x42, 0xFA, 0xD0, +0x36, 0x49, 0x37, 0x48, 0x40, 0xF6, 0x2A, 0x42, 0x12, 0xF0, 0xF2, 0xFE, 0xD7, 0xF8, 0x38, 0x31, 0xB3, 0x42, 0xF0, 0xD0, +0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDA, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x2D, 0x49, 0x2F, 0x48, +0x4F, 0xF4, 0x43, 0x62, 0x12, 0xF0, 0xE0, 0xFE, 0xD8, 0xF8, 0x24, 0x20, 0x46, 0x46, 0x02, 0xF4, 0x60, 0x1A, 0x26, 0x4B, +0x1B, 0x68, 0x5B, 0x78, 0x00, 0x2B, 0x58, 0xD1, 0xD7, 0xF8, 0x38, 0x31, 0xD7, 0xF8, 0x10, 0x80, 0xDB, 0x6C, 0x07, 0xF1, +0x0C, 0x05, 0x03, 0xF1, 0x14, 0x07, 0x1C, 0x4B, 0x04, 0x97, 0x54, 0x24, 0x04, 0xFB, 0x09, 0x34, 0x57, 0x46, 0xDF, 0xF8, +0x88, 0xB0, 0xDF, 0xF8, 0x7C, 0x90, 0xA2, 0x46, 0x03, 0x9C, 0x94, 0xF8, 0x50, 0x10, 0xDB, 0xF8, 0x58, 0x33, 0x01, 0x31, +0x84, 0xF8, 0x50, 0x10, 0x30, 0x46, 0x00, 0x21, 0x98, 0x47, 0x58, 0xB1, 0x13, 0x4B, 0x68, 0x60, 0x1B, 0x68, 0x59, 0x78, +0xDA, 0xF8, 0x00, 0x30, 0x00, 0x29, 0x65, 0xD0, 0xAB, 0x42, 0x00, 0xF0, 0xAD, 0x80, 0x05, 0x46, 0xB7, 0xF5, 0x60, 0x1F, +0x65, 0xD1, 0xC0, 0xF8, 0x04, 0x80, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2C, 0x7F, 0xF4, 0xA8, 0xAE, 0x0A, 0x49, +0x0B, 0x48, 0x40, 0xF6, 0x8B, 0x32, 0x12, 0xF0, 0x99, 0xFE, 0xA0, 0xE6, 0x09, 0x4B, 0x03, 0x93, 0x8B, 0xE6, 0x00, 0xBF, +0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x83, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x64, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x4C, 0x92, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x07, 0xF1, 0x50, 0x01, 0xA4, 0xE6, 0xD7, 0xF8, 0x54, 0x80, 0x07, 0xF1, 0x50, 0x05, 0x00, 0x27, 0xA9, 0xE7, 0x00, 0x2E, +0x7F, 0xF4, 0xA6, 0xAE, 0x49, 0x49, 0x4A, 0x48, 0x40, 0xF6, 0xB6, 0x32, 0x12, 0xF0, 0x6E, 0xFE, 0x9E, 0xE6, 0x03, 0xF4, +0x60, 0x13, 0xB3, 0xF5, 0x20, 0x1F, 0x3E, 0xD0, 0x40, 0xF6, 0x9B, 0x32, 0x42, 0x49, 0x44, 0x48, 0x12, 0xF0, 0x62, 0xFE, +0x43, 0x4B, 0x67, 0x6C, 0x1B, 0x68, 0x2A, 0x68, 0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xB2, 0xF9, 0x00, 0x20, 0xD3, 0xF8, +0x3C, 0x41, 0x00, 0x2A, 0xE5, 0x6C, 0xBF, 0xF6, 0x6F, 0xAE, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x12, 0xB2, 0xF5, 0x60, 0x1F, +0x60, 0xD0, 0x3A, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x64, 0xE6, 0x04, 0x9A, 0x93, 0x42, 0x99, 0xD1, 0xCA, 0xE9, +0x01, 0x11, 0x05, 0x46, 0x96, 0xE7, 0x34, 0x4B, 0x36, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x3F, 0xDB, +0x77, 0x6A, 0x07, 0xF4, 0x60, 0x17, 0x74, 0xE7, 0x20, 0x46, 0x2C, 0x46, 0x04, 0xEB, 0x8E, 0x0E, 0x55, 0x46, 0xC4, 0xF8, +0x38, 0x61, 0xBA, 0x46, 0x98, 0x46, 0x67, 0x46, 0xCE, 0xF8, 0x34, 0x00, 0xE3, 0xE6, 0x27, 0x4B, 0x67, 0x6C, 0x1B, 0x68, +0xDB, 0xB2, 0x07, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x3C, 0x41, 0xE5, 0x6C, 0xCB, 0xE7, 0xB0, 0x6A, 0xA3, 0x7A, 0x62, 0x7A, +0x71, 0x8C, 0xC0, 0xF3, 0xC1, 0x10, 0x00, 0x90, 0x20, 0x46, 0xFE, 0xF7, 0xA1, 0xFB, 0x54, 0x23, 0x1E, 0x49, 0xF2, 0x6C, +0xD7, 0xF8, 0x54, 0xE0, 0x03, 0xFB, 0x09, 0xF3, 0x04, 0xF1, 0x50, 0x00, 0x51, 0xF8, 0x03, 0xC0, 0xD0, 0x61, 0x07, 0xF1, +0x50, 0x02, 0xC4, 0xF8, 0x54, 0xE0, 0x94, 0x45, 0x04, 0x9C, 0x7C, 0x65, 0x7F, 0xF4, 0xE5, 0xAE, 0xC8, 0x50, 0xE2, 0xE6, +0xCA, 0xF8, 0x00, 0x00, 0x05, 0x46, 0x4F, 0xE7, 0x00, 0x2E, 0xBD, 0xD1, 0x0B, 0x49, 0x40, 0xF6, 0x62, 0x42, 0x48, 0x46, +0x12, 0xF0, 0xF2, 0xFD, 0xB6, 0xE7, 0x04, 0x99, 0x01, 0x22, 0xC3, 0xE9, 0x01, 0x12, 0xD0, 0xE6, 0x40, 0xF6, 0xA5, 0x32, +0x04, 0x49, 0x0A, 0x48, 0x12, 0xF0, 0xE6, 0xFD, 0x06, 0x4B, 0x1A, 0x68, 0x63, 0x6A, 0xB2, 0xF9, 0x00, 0x20, 0xFC, 0xE5, +0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x1C, 0x92, 0x15, 0x00, 0x30, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x34, 0x92, 0x15, 0x00, 0x05, 0x28, 0x10, 0xB5, 0x25, 0xD0, 0x14, 0x4A, 0x00, 0xEB, 0x40, 0x03, +0xC3, 0xEB, 0xC3, 0x03, 0x02, 0xEB, 0x83, 0x02, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0F, 0x4B, +0x01, 0x21, 0x19, 0x60, 0x0E, 0x4C, 0x92, 0xF8, 0x50, 0x10, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x31, 0xB9, 0xD2, 0x6A, +0x22, 0xB1, 0x0B, 0x4B, 0xD3, 0xF8, 0x5C, 0x33, 0x98, 0x47, 0x23, 0x68, 0x33, 0xB1, 0x06, 0x4A, 0x01, 0x3B, 0x12, 0x68, +0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x05, 0x4A, 0xDE, 0xE7, 0x00, 0xBF, 0x20, 0x62, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0x03, 0x68, 0x13, 0xF4, +0xE0, 0x3F, 0x1A, 0xD1, 0x9A, 0x04, 0x4C, 0xBF, 0x03, 0xF0, 0x0F, 0x02, 0x03, 0xF0, 0x07, 0x02, 0x02, 0x2A, 0xC3, 0xF3, +0xC1, 0x11, 0x88, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x23, 0xF0, 0xFF, 0x53, 0x98, 0xBF, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, +0xFE, 0x13, 0x42, 0xEA, 0x01, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0x03, 0x60, 0x70, 0x47, +0xC3, 0x6B, 0x00, 0x2B, 0x00, 0xDB, 0x70, 0x47, 0x10, 0xB4, 0x0E, 0x4C, 0x42, 0x6A, 0x24, 0x68, 0xB4, 0xF9, 0x00, 0x40, +0x00, 0x2C, 0x01, 0xDA, 0xDB, 0x03, 0x0B, 0xD5, 0x53, 0x69, 0x23, 0xF4, 0xE0, 0x33, 0x00, 0x24, 0x43, 0xF4, 0x80, 0x43, +0xC4, 0x63, 0x5D, 0xF8, 0x04, 0x4B, 0x53, 0x61, 0xFC, 0xF7, 0xA4, 0xB9, 0x04, 0x49, 0x05, 0x48, 0x5D, 0xF8, 0x04, 0x4B, +0x40, 0xF6, 0xD9, 0x42, 0x12, 0xF0, 0x28, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x92, 0x15, 0x00, +0x05, 0x28, 0x10, 0xB5, 0x17, 0xD0, 0x0D, 0x4C, 0x00, 0xEB, 0x40, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x04, 0xEB, 0x80, 0x04, +0xA1, 0x6A, 0x31, 0xB1, 0xCB, 0x7A, 0x01, 0x3B, 0xDB, 0xB2, 0xCB, 0x72, 0x13, 0xB1, 0x00, 0x23, 0xA3, 0x62, 0x10, 0xBD, +0xD1, 0xF8, 0x48, 0x01, 0x11, 0xF0, 0xE8, 0xF8, 0x00, 0x23, 0xA3, 0x62, 0xF7, 0xE7, 0x02, 0x4C, 0xEC, 0xE7, 0x00, 0xBF, +0x20, 0x62, 0x17, 0x00, 0xC4, 0x63, 0x17, 0x00, 0xF0, 0xB4, 0xC5, 0x6C, 0x42, 0x6A, 0xEB, 0x6C, 0xD0, 0xE9, 0x11, 0x67, +0x22, 0xF4, 0xC0, 0x12, 0x23, 0xF4, 0x60, 0x13, 0x05, 0xF1, 0x14, 0x0C, 0x42, 0xF4, 0x20, 0x14, 0x43, 0xF4, 0x20, 0x12, +0x06, 0xF5, 0x82, 0x73, 0xC6, 0xF8, 0x14, 0xC0, 0x33, 0x63, 0x44, 0x62, 0xEA, 0x64, 0x06, 0xF1, 0x0C, 0x00, 0x07, 0xF1, +0x24, 0x02, 0x06, 0xF5, 0x9C, 0x75, 0x53, 0xF8, 0x04, 0x4B, 0x42, 0xF8, 0x04, 0x4F, 0xAB, 0x42, 0xF9, 0xD1, 0x77, 0xB1, +0x09, 0x4B, 0x1B, 0x68, 0x5B, 0x78, 0x33, 0xB9, 0xD6, 0xF8, 0x38, 0x31, 0xDB, 0x6C, 0x14, 0x33, 0x0B, 0x60, 0xF0, 0xBC, +0x70, 0x47, 0x50, 0x36, 0x0E, 0x60, 0xF0, 0xBC, 0x70, 0x47, 0x01, 0x23, 0x38, 0x46, 0x73, 0x60, 0xF5, 0xE7, 0x00, 0xBF, +0x34, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x47, 0x6A, 0xD0, 0xF8, 0x4C, 0xE0, 0x85, 0xB0, 0x17, 0xF4, 0x00, 0x1C, +0x9D, 0xF8, 0x38, 0x90, 0x04, 0x46, 0x0E, 0xF1, 0x14, 0x08, 0x0D, 0x46, 0x16, 0x46, 0x9A, 0x46, 0x2A, 0xD0, 0x07, 0xF4, +0x60, 0x17, 0xB7, 0xF5, 0x20, 0x1F, 0x40, 0xF0, 0xBB, 0x80, 0xD0, 0xF8, 0x44, 0xB0, 0xBB, 0xF8, 0x04, 0x70, 0x07, 0xF0, +0x03, 0x07, 0x03, 0x2F, 0x40, 0xF0, 0xB2, 0x80, 0xDF, 0xF8, 0x30, 0xC2, 0x83, 0x4F, 0xDC, 0xF8, 0x00, 0xC0, 0x3F, 0x68, +0x9C, 0xF8, 0x3E, 0xC0, 0x07, 0xF0, 0x3F, 0x07, 0xBC, 0x45, 0x00, 0xF2, 0xA5, 0x80, 0xDB, 0xF8, 0x24, 0x70, 0x97, 0x42, +0x40, 0xF2, 0xC1, 0x80, 0x7C, 0x4C, 0xCD, 0xF8, 0x38, 0x90, 0xD4, 0xF8, 0x70, 0x43, 0xA4, 0x46, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x4F, 0x60, 0x47, 0x83, 0x6C, 0x00, 0x2B, 0x00, 0xF0, 0x92, 0x80, 0x5B, 0x6A, 0x13, 0xF0, 0x10, 0x03, 0x00, 0xF0, +0x8D, 0x80, 0x82, 0x88, 0x00, 0x2A, 0x00, 0xF0, 0x8F, 0x80, 0xC3, 0x8B, 0x1F, 0x07, 0x00, 0xF1, 0x8B, 0x80, 0xDE, 0xF8, +0x24, 0x10, 0x00, 0x29, 0x00, 0xF0, 0xB9, 0x80, 0x08, 0x88, 0x83, 0xB2, 0x00, 0x04, 0x00, 0xF1, 0xB4, 0x80, 0x6F, 0xEA, +0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0x0B, 0x80, 0x94, 0xF8, 0x33, 0x20, 0x94, 0xF8, 0x32, 0x30, 0x04, 0x32, 0x04, 0x33, +0x84, 0xF8, 0x32, 0x30, 0x84, 0xF8, 0x33, 0x20, 0xDE, 0xE9, 0x0A, 0x12, 0xD3, 0x1D, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, +0x9B, 0xB2, 0x04, 0x32, 0x04, 0x31, 0xB3, 0x42, 0xCE, 0xE9, 0x0A, 0x12, 0x6D, 0xD8, 0xA2, 0x88, 0x32, 0xB1, 0xE3, 0x8B, +0x1F, 0x07, 0x03, 0xD4, 0x5A, 0x4B, 0xDB, 0x6E, 0x41, 0xF8, 0x03, 0x3C, 0x23, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x36, 0xD0, +0x11, 0x46, 0xDF, 0xF8, 0x70, 0xB1, 0x54, 0x4F, 0x32, 0x46, 0x00, 0x29, 0x2C, 0xD0, 0xE1, 0x8B, 0x0E, 0x07, 0x29, 0xD4, +0x99, 0x88, 0x39, 0xB3, 0xD9, 0x8B, 0x08, 0x07, 0x24, 0xD4, 0x4D, 0x49, 0xDB, 0xF8, 0x00, 0x00, 0x09, 0x68, 0x90, 0xF8, +0x3E, 0x60, 0x01, 0xF0, 0x3F, 0x01, 0x8E, 0x42, 0x1A, 0xD8, 0x5B, 0x6A, 0xBC, 0xF1, 0x00, 0x0F, 0x4C, 0xD1, 0x9B, 0x02, +0x17, 0xD5, 0xCD, 0xF8, 0x00, 0x90, 0xD7, 0xF8, 0x54, 0x63, 0x03, 0x92, 0x53, 0x46, 0x29, 0x46, 0x20, 0x46, 0xB0, 0x47, +0x03, 0x9A, 0x00, 0x28, 0x77, 0xD0, 0x2B, 0x68, 0x00, 0x2B, 0x74, 0xD0, 0x60, 0x6A, 0xA1, 0x88, 0x00, 0xF4, 0x00, 0x1C, +0x00, 0x29, 0xD2, 0xD1, 0xBC, 0xF1, 0x00, 0x0F, 0x47, 0xD1, 0x63, 0x6C, 0xD3, 0xB9, 0x3B, 0x48, 0x11, 0xF0, 0x2C, 0xF8, +0x3A, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x56, 0xDB, 0x54, 0x23, 0x1C, 0x22, 0x37, 0x48, +0x13, 0xFB, 0x09, 0x29, 0x00, 0x22, 0x01, 0x23, 0xAA, 0x80, 0xEB, 0x72, 0x48, 0x44, 0x29, 0x46, 0x65, 0x64, 0x10, 0xF0, +0xF7, 0xFF, 0x01, 0xE0, 0x4F, 0xF0, 0x00, 0x08, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, 0x2C, 0x30, +0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0x9A, 0xD2, 0x25, 0x4B, 0x40, 0x46, 0xD3, 0xF8, +0xBC, 0x33, 0x49, 0x46, 0x98, 0x47, 0x4F, 0xF0, 0x00, 0x08, 0xE9, 0xE7, 0xCD, 0xF8, 0x00, 0x90, 0x99, 0x02, 0x54, 0xBF, +0xD7, 0xF8, 0x50, 0x63, 0xD7, 0xF8, 0x4C, 0x63, 0xAF, 0xE7, 0xFE, 0xF7, 0xD1, 0xF9, 0xDB, 0xF8, 0x38, 0x31, 0x67, 0x6A, +0x1B, 0x68, 0x2B, 0x60, 0x5B, 0xB3, 0xA2, 0x88, 0x07, 0xF4, 0x00, 0x1C, 0x80, 0xE7, 0x63, 0x6C, 0xD3, 0xF8, 0x38, 0x21, +0x03, 0xF1, 0x0C, 0x08, 0xD2, 0x6C, 0x00, 0x21, 0x40, 0x46, 0xD1, 0x61, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDE, 0xF8, +0x2C, 0x30, 0x03, 0x33, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x9B, 0xB2, 0x9E, 0x42, 0xCC, 0xD3, 0x00, 0x29, 0x3F, 0xF4, +0x65, 0xAF, 0xDE, 0xF8, 0x28, 0x10, 0x5D, 0xE7, 0x00, 0x28, 0xA6, 0xD1, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0x92, 0x52, +0x12, 0xF0, 0xD6, 0xFB, 0x9F, 0xE7, 0x67, 0x6A, 0x07, 0xF4, 0x00, 0x1C, 0x8C, 0xE7, 0x07, 0xF4, 0x00, 0x1C, 0x89, 0xE7, +0x54, 0x83, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x8C, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x28, +0x2C, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x0B, 0x23, 0x13, 0x1B, 0x03, 0x00, 0x1B, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x03, 0x0F, +0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x17, 0x4B, 0x1B, 0x68, 0x13, 0xF0, 0x30, 0x0F, 0x0C, 0xBF, 0x01, 0x20, +0x00, 0x20, 0x08, 0xBD, 0x13, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x5F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, +0x0F, 0x4B, 0x1B, 0x68, 0x13, 0xF4, 0x40, 0x3F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x0B, 0x4B, 0x1B, 0x68, +0x13, 0xF4, 0x40, 0x7F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x08, 0xBD, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x01, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xF3, 0x12, 0x12, 0xF0, 0x7E, 0xFB, +0x00, 0x20, 0x08, 0xBD, 0x88, 0x81, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, +0x90, 0xF8, 0x25, 0x30, 0xE3, 0xB1, 0x10, 0xB5, 0x0F, 0x4A, 0x10, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, +0x9C, 0x51, 0x84, 0xB0, 0x04, 0x46, 0x08, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x21, 0x02, 0x22, 0x05, 0x23, 0x94, 0xF8, +0x23, 0x00, 0xCD, 0xE9, 0x00, 0x32, 0xCD, 0xE9, 0x02, 0x11, 0x25, 0x23, 0x40, 0xF6, 0xC4, 0x12, 0xFD, 0xF7, 0x5E, 0xFF, +0x04, 0xB0, 0x10, 0xBD, 0x03, 0x4A, 0xC2, 0xE9, 0x01, 0x33, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x94, 0x64, 0x17, 0x00, 0x03, 0x68, 0x70, 0xB4, 0xC3, 0xF3, 0xC2, 0x24, 0x05, 0x2C, 0x01, 0xD0, 0x70, 0xBC, 0x70, 0x47, +0xC3, 0xF3, 0x00, 0x26, 0x75, 0x00, 0x03, 0xF0, 0x7F, 0x04, 0x35, 0x44, 0x04, 0xEB, 0x44, 0x04, 0x05, 0xEB, 0x44, 0x04, +0xC3, 0xF3, 0x41, 0x25, 0x2C, 0x44, 0x16, 0x4D, 0x35, 0xF8, 0x14, 0x50, 0xC3, 0xF3, 0xC0, 0x14, 0x05, 0xFA, 0x04, 0xF4, +0x01, 0x3A, 0x02, 0xFB, 0x04, 0xF2, 0x8A, 0x42, 0xC3, 0xF3, 0xC1, 0x14, 0xE2, 0xD2, 0x13, 0xF4, 0xE0, 0x3F, 0x06, 0xD0, +0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x00, 0x43, 0x70, 0xBC, 0x03, 0x60, 0x70, 0x47, 0x03, 0xF0, 0x0F, 0x02, 0x02, 0x2A, +0x23, 0xF0, 0xFF, 0x53, 0x8C, 0xBF, 0x4F, 0xF4, 0x80, 0x12, 0x4F, 0xF4, 0x00, 0x22, 0x23, 0xF4, 0xFE, 0x13, 0x42, 0xEA, +0x04, 0x62, 0x13, 0x43, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF4, 0x00, 0x43, 0xE8, 0xE7, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, +0x70, 0xB5, 0x0C, 0x4D, 0x00, 0xEB, 0x40, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x93, 0xF8, 0x2E, 0x20, 0x72, 0xB1, 0x04, 0x46, +0x46, 0x00, 0x58, 0x6A, 0x00, 0x22, 0x83, 0xF8, 0x2E, 0x20, 0x10, 0xB1, 0x21, 0x46, 0xFB, 0xF7, 0x35, 0xFF, 0x34, 0x44, +0x05, 0xEB, 0x84, 0x05, 0x00, 0x23, 0x6B, 0x62, 0x70, 0xBD, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x41, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4F, +0x41, 0x4E, 0x3B, 0x68, 0xDF, 0xF8, 0x0C, 0x81, 0x01, 0x33, 0x00, 0x24, 0x3B, 0x60, 0x35, 0x46, 0xA2, 0x46, 0x4F, 0xF0, +0x01, 0x0B, 0x96, 0xF8, 0x60, 0x10, 0x0B, 0xFA, 0x04, 0xF3, 0x0B, 0x42, 0x5F, 0xFA, 0x83, 0xF9, 0x4D, 0xD1, 0x96, 0xF8, +0x61, 0x10, 0x11, 0xEA, 0x09, 0x0F, 0x30, 0xD0, 0xA8, 0x6A, 0x21, 0xEA, 0x03, 0x03, 0x86, 0xF8, 0x61, 0x30, 0x03, 0x07, +0x4F, 0xD0, 0x33, 0x4B, 0x43, 0xF8, 0x24, 0x00, 0xE0, 0xB2, 0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0x95, 0xF8, 0x2C, 0x30, +0x85, 0xF8, 0x2D, 0x30, 0x49, 0xEA, 0x0A, 0x0A, 0x01, 0x34, 0x04, 0x2C, 0x05, 0xF1, 0x0C, 0x05, 0xD9, 0xD1, 0xBA, 0xF1, +0x00, 0x0F, 0x47, 0xD0, 0x29, 0x4A, 0x2A, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x29, 0x48, 0x01, 0xF5, 0x00, 0x51, +0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x20, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x95, 0xF8, 0x2D, 0x30, 0x00, 0x2B, 0xDE, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x85, 0xF8, +0x2D, 0x30, 0x5B, 0xB9, 0x32, 0x69, 0xA3, 0x1C, 0xE0, 0xB2, 0x52, 0xF8, 0x23, 0x30, 0x17, 0x4A, 0x42, 0xF8, 0x24, 0x30, +0xD8, 0xF8, 0xD0, 0x33, 0x98, 0x47, 0xCD, 0xE7, 0x49, 0xEA, 0x0A, 0x0A, 0xCA, 0xE7, 0xE0, 0xB2, 0x01, 0x93, 0xFF, 0xF7, +0xBD, 0xFE, 0x01, 0x9B, 0x00, 0x28, 0xF5, 0xD0, 0x96, 0xF8, 0x60, 0x10, 0x21, 0xEA, 0x03, 0x01, 0x86, 0xF8, 0x60, 0x10, +0xA3, 0xE7, 0x95, 0xF8, 0x2E, 0x30, 0x00, 0x2B, 0xB2, 0xD1, 0x85, 0xF8, 0x2E, 0xB0, 0x96, 0xF8, 0x60, 0x30, 0x49, 0xEA, +0x03, 0x03, 0x86, 0xF8, 0x60, 0x30, 0xA9, 0xE7, 0xC6, 0xF8, 0x18, 0xA0, 0xBD, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0xA8, 0x64, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4C, 0x94, 0xF8, 0x62, 0x20, 0x4A, 0xB1, 0x94, 0xF8, 0x61, 0x20, 0xA5, 0x69, +0x01, 0x21, 0x01, 0xFA, 0x00, 0xF3, 0x13, 0x43, 0x84, 0xF8, 0x61, 0x30, 0x05, 0xB1, 0x70, 0xBD, 0x0D, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0x0B, 0x4B, 0x0C, 0x48, 0xD3, 0xF8, 0xC8, 0x33, 0xA3, 0x61, 0xBD, 0xE8, +0x70, 0x40, 0x18, 0x47, 0xFF, 0xF7, 0x74, 0xFE, 0x00, 0x28, 0xF3, 0xD1, 0xBD, 0xE8, 0x70, 0x40, 0x06, 0x49, 0x07, 0x48, +0x4F, 0xF4, 0x22, 0x72, 0x12, 0xF0, 0xF4, 0xB9, 0x94, 0x64, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xA8, 0x64, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x93, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x1D, 0x4D, 0x1E, 0x4E, +0x1E, 0x4F, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x2B, 0x68, 0x00, 0x24, 0x01, 0x2C, 0x11, 0xD0, 0x53, 0xF8, +0x24, 0x30, 0x1B, 0xB9, 0x33, 0x69, 0xA2, 0x1C, 0x53, 0xF8, 0x22, 0x30, 0x47, 0xF8, 0x24, 0x30, 0xE0, 0xB2, 0xFF, 0xF7, +0xFB, 0xFE, 0x03, 0x2C, 0x0D, 0xD0, 0x01, 0x34, 0x01, 0x2C, 0x2B, 0x68, 0xED, 0xD1, 0x5B, 0x68, 0x73, 0xB9, 0x33, 0x69, +0xDB, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x01, 0x20, 0xFF, 0xF7, 0xEC, 0xFE, 0xF1, 0xE7, 0x0D, 0x48, 0x08, 0xF0, 0x3C, 0xFC, +0x00, 0x23, 0xB3, 0x61, 0xBD, 0xE8, 0xF8, 0x83, 0xC3, 0xF3, 0x0B, 0x02, 0x00, 0x2A, 0xEE, 0xD1, 0x32, 0x69, 0xD2, 0x68, +0x03, 0xEA, 0x09, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x13, 0x43, 0xC8, 0xF8, 0x00, 0x30, 0xE6, 0xE7, 0xAC, 0x35, 0x17, 0x00, +0x94, 0x64, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0xA8, 0x64, 0x17, 0x00, 0x04, 0x02, 0x32, 0x40, 0x00, 0xF0, 0xFF, 0xFF, +0x1A, 0x4A, 0x1B, 0x4B, 0xF0, 0xB4, 0x02, 0xF1, 0x74, 0x04, 0x94, 0xE8, 0x03, 0x00, 0x16, 0x69, 0xC3, 0xF8, 0xE0, 0x03, +0xF0, 0x6D, 0xA3, 0xF8, 0xE4, 0x13, 0xB6, 0xF8, 0x60, 0x10, 0xC3, 0xF8, 0xE6, 0x03, 0xA3, 0xF8, 0xEA, 0x13, 0x94, 0xE8, +0x03, 0x00, 0xD3, 0xF8, 0xD4, 0x53, 0xA3, 0xF8, 0xF0, 0x13, 0xD1, 0x6E, 0xC3, 0xF8, 0xEC, 0x03, 0xC3, 0xF8, 0xF6, 0x13, +0x0D, 0x4F, 0x0E, 0x48, 0x03, 0xF5, 0x88, 0x64, 0x00, 0x21, 0x82, 0xF8, 0x88, 0x10, 0xC3, 0xF8, 0xBC, 0x43, 0x05, 0xF4, +0x7F, 0x45, 0x03, 0xF5, 0x66, 0x74, 0x4F, 0xF4, 0x00, 0x52, 0xC3, 0xF8, 0xD4, 0x53, 0xC3, 0xF8, 0x9C, 0x13, 0x3C, 0x60, +0xF0, 0xBC, 0x02, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, +0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0xB2, 0x03, 0x68, 0x90, 0x4C, 0xDB, 0xF8, 0x10, 0x20, +0x80, 0x46, 0x53, 0xF8, 0x26, 0x0F, 0xA0, 0x64, 0xD0, 0x6D, 0x9D, 0x88, 0xC4, 0xF8, 0x4E, 0x00, 0x18, 0x68, 0xB8, 0xF8, +0x12, 0x10, 0x9B, 0x88, 0xB2, 0xF8, 0x60, 0x20, 0x60, 0x65, 0x00, 0x27, 0x83, 0xB0, 0x04, 0xF1, 0x5C, 0x00, 0xA4, 0xF8, +0x4C, 0x50, 0xA4, 0xF8, 0x52, 0x20, 0xA4, 0xF8, 0x58, 0x30, 0xA7, 0x61, 0xFE, 0xF7, 0x78, 0xFC, 0x63, 0x6F, 0xD8, 0xF8, +0x00, 0x10, 0x80, 0x4A, 0x91, 0xF8, 0x23, 0xC0, 0xA5, 0x69, 0xDE, 0x1C, 0x42, 0xF2, 0x38, 0x0E, 0x26, 0xF0, 0x03, 0x06, +0x24, 0x23, 0x39, 0x46, 0x04, 0x36, 0x13, 0xFB, 0x0C, 0xE7, 0x06, 0xEB, 0x80, 0x06, 0x4F, 0xEA, 0x40, 0x2E, 0x17, 0x44, +0xB6, 0xB2, 0x89, 0x46, 0x04, 0xF1, 0x5C, 0x02, 0xA4, 0x46, 0x4F, 0xF4, 0x20, 0x10, 0xF2, 0x46, 0x01, 0x97, 0x1C, 0xE0, +0x0F, 0x33, 0x1B, 0x09, 0x1B, 0x02, 0x43, 0xF0, 0x30, 0x03, 0x9B, 0xB2, 0x4A, 0xEA, 0x00, 0x00, 0x0B, 0x43, 0x90, 0x63, +0xC2, 0xF8, 0x24, 0x90, 0xC2, 0xF8, 0x3C, 0x90, 0xA2, 0xF8, 0x58, 0x30, 0xCC, 0xF8, 0x08, 0x20, 0xA5, 0x69, 0x35, 0x44, +0xA5, 0x61, 0x94, 0x46, 0x4F, 0xF4, 0x40, 0x10, 0x01, 0x31, 0x09, 0x29, 0x02, 0xF1, 0x5C, 0x02, 0x22, 0xD0, 0x01, 0x9F, +0x57, 0xF8, 0x04, 0x3B, 0x01, 0x97, 0x00, 0x2B, 0xF4, 0xD0, 0xD8, 0xF8, 0x08, 0x70, 0x06, 0xEB, 0x05, 0x0E, 0xBE, 0x45, +0x16, 0xD8, 0xB3, 0xF5, 0x7C, 0x7F, 0xD3, 0xD9, 0xB3, 0xF5, 0x80, 0x6F, 0x0D, 0xD9, 0xB3, 0xF5, 0x86, 0x4F, 0x45, 0xD8, +0x6F, 0xF4, 0x7C, 0x75, 0x2B, 0x44, 0xC3, 0xF3, 0x07, 0x13, 0x1B, 0x02, 0x43, 0xF4, 0x80, 0x43, 0x43, 0xF0, 0x30, 0x03, +0xC8, 0xE7, 0x44, 0xF2, 0x30, 0x03, 0xC5, 0xE7, 0x00, 0x2D, 0x3B, 0xD0, 0xDC, 0xF8, 0x38, 0x30, 0x03, 0xF4, 0x60, 0x11, +0x00, 0x22, 0xB1, 0xF5, 0x20, 0x1F, 0xCC, 0xF8, 0x08, 0x20, 0x63, 0xD0, 0x4C, 0x49, 0x4D, 0x4A, 0x4D, 0x4E, 0x43, 0xF4, +0x60, 0x13, 0xCC, 0xF8, 0x38, 0x30, 0x0D, 0x68, 0x10, 0x68, 0x04, 0x35, 0xC0, 0xF3, 0x05, 0x20, 0x06, 0xE0, 0x33, 0x68, +0xDB, 0x04, 0x08, 0xD4, 0x0B, 0x68, 0x5B, 0x1B, 0x00, 0x2B, 0x04, 0xDA, 0x13, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x98, 0x42, +0xF3, 0xD0, 0xE3, 0x6B, 0x42, 0x48, 0x43, 0x49, 0x43, 0x4A, 0x04, 0x60, 0x03, 0xF4, 0x7F, 0x43, 0xE3, 0x63, 0x4F, 0xF4, +0x00, 0x50, 0x00, 0x23, 0x08, 0x60, 0x63, 0x60, 0x8B, 0xF8, 0x88, 0x30, 0x62, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0xB3, 0xF5, 0x88, 0x4F, 0x1F, 0xD8, 0x48, 0xF2, 0x30, 0x03, 0x87, 0xE7, 0xD4, 0xF8, 0x98, 0x30, 0x37, 0x4A, 0x35, 0x4E, +0x35, 0x49, 0xC4, 0xF8, 0x94, 0x50, 0x03, 0xF4, 0x7F, 0x43, 0xC4, 0xF8, 0x98, 0x30, 0xA2, 0xF5, 0x79, 0x73, 0xC4, 0xE9, +0x18, 0x55, 0x8B, 0xF8, 0x88, 0x50, 0x4F, 0xF4, 0x00, 0x50, 0x33, 0x60, 0x30, 0x23, 0x08, 0x60, 0xA4, 0xF8, 0xB4, 0x30, +0xC4, 0xF8, 0x80, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF5, 0x0F, 0x3F, 0x2A, 0xD9, 0xB3, 0xF5, 0x11, 0x3F, +0x32, 0xD9, 0x28, 0x4D, 0xAB, 0x42, 0x32, 0xD8, 0xA3, 0xF1, 0x01, 0x13, 0xA3, 0xF5, 0x44, 0x43, 0xC3, 0xF3, 0xC7, 0x33, +0x1B, 0x02, 0x43, 0xF4, 0x40, 0x43, 0x43, 0xF0, 0x30, 0x03, 0x55, 0xE7, 0xDC, 0xF8, 0x3C, 0x30, 0xCC, 0xF8, 0x38, 0x20, +0xCC, 0xF8, 0x04, 0x20, 0x8B, 0xF8, 0x88, 0x20, 0x19, 0x48, 0x1A, 0x49, 0x1A, 0x4A, 0xCC, 0xF8, 0x24, 0x20, 0x03, 0xF4, +0x7F, 0x43, 0xCC, 0xF8, 0x3C, 0x30, 0x4F, 0xF4, 0x00, 0x53, 0xC0, 0xF8, 0x00, 0xC0, 0x0B, 0x60, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0xA3, 0xF5, 0x70, 0x53, 0x01, 0x3B, 0xC3, 0xF3, 0xC7, 0x23, 0x1B, 0x02, 0x43, 0xF4, 0x00, 0x43, 0x43, 0xF0, +0x30, 0x03, 0x31, 0xE7, 0x4C, 0xF2, 0x30, 0x03, 0x2E, 0xE7, 0x4F, 0xF6, 0x30, 0x65, 0x4F, 0xF6, 0x30, 0x77, 0xB3, 0xF1, +0xFF, 0x3F, 0x08, 0xBF, 0x3D, 0x46, 0x2B, 0x46, 0x24, 0xE7, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0x7C, 0x36, 0x17, 0x00, +0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x78, 0x80, 0x32, 0x40, 0xAC, 0x81, 0x32, 0x40, 0x80, 0x81, 0x32, 0x40, +0xA0, 0x61, 0x18, 0x00, 0x00, 0xC4, 0x20, 0x00, 0x94, 0x64, 0x17, 0x00, 0x1C, 0x4A, 0x1D, 0x49, 0x13, 0x68, 0xF0, 0xB4, +0x03, 0xF5, 0xDA, 0x53, 0x1B, 0x4F, 0x1C, 0x4E, 0x1C, 0x4C, 0x1D, 0x4D, 0x18, 0x33, 0x3B, 0x60, 0x40, 0x23, 0x33, 0x60, +0x23, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x23, 0x60, 0x17, 0x68, 0x0C, 0x68, 0x01, 0x23, 0x10, 0x3E, 0x04, 0x37, 0xC4, 0xF3, +0x05, 0x24, 0x85, 0xF8, 0x8C, 0x30, 0x06, 0xE0, 0x33, 0x68, 0xDB, 0x04, 0x08, 0xD4, 0x13, 0x68, 0xDB, 0x1B, 0x00, 0x2B, +0x04, 0xDA, 0x0B, 0x68, 0x03, 0xF0, 0x3F, 0x03, 0x9C, 0x42, 0xF3, 0xD0, 0xC3, 0x6B, 0x0E, 0x4C, 0x0E, 0x4A, 0x0F, 0x49, +0x42, 0x62, 0x03, 0xF4, 0x7F, 0x43, 0xC3, 0x63, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x53, 0x42, 0x60, 0x85, 0xF8, 0x88, 0x20, +0x20, 0x60, 0xF0, 0xBC, 0x0B, 0x60, 0x70, 0x47, 0x20, 0x01, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x40, 0x01, 0x32, 0x40, +0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0xAC, 0x81, 0x32, 0x40, 0xA0, 0x61, 0x18, 0x00, +0x80, 0x81, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4F, 0x0C, 0x23, 0x0E, 0x46, 0x54, 0x25, 0x04, 0x46, 0x15, 0xFB, +0x01, 0x30, 0x05, 0xFB, 0x06, 0x75, 0x38, 0x44, 0xD4, 0xF8, 0x4C, 0x80, 0x10, 0xF0, 0xEC, 0xFB, 0x95, 0xF8, 0x50, 0x30, +0xA2, 0x88, 0x01, 0x3B, 0x85, 0xF8, 0x50, 0x30, 0x22, 0xB9, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFD, 0xF7, 0x22, 0xBA, +0xD8, 0xF8, 0x50, 0x10, 0x32, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFC, 0xF7, 0xF6, 0xBB, 0x20, 0x62, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x00, 0x23, 0x2E, 0x4D, 0x03, 0x60, 0x95, 0xF8, 0x8C, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x37, 0xD1, +0x95, 0xF8, 0x85, 0x30, 0x03, 0x2B, 0x33, 0xD8, 0x29, 0x4E, 0xDF, 0xF8, 0xB4, 0xA0, 0x81, 0x46, 0x4F, 0xF0, 0x03, 0x08, +0x14, 0xE0, 0x95, 0xF8, 0x7E, 0x30, 0xDA, 0xF8, 0x64, 0x73, 0x00, 0x93, 0x2A, 0x6F, 0xB5, 0xF8, 0x7A, 0x30, 0x49, 0x46, +0x20, 0x46, 0xB8, 0x47, 0x07, 0x46, 0x20, 0xBB, 0x95, 0xF8, 0x85, 0x30, 0x08, 0xF1, 0xFF, 0x38, 0x98, 0x45, 0xA6, 0xF1, +0x54, 0x06, 0x17, 0xDB, 0x96, 0xF8, 0x16, 0x31, 0x5F, 0xFA, 0x88, 0xF7, 0x01, 0x2B, 0x85, 0xF8, 0x7E, 0x70, 0x0F, 0xD0, +0xD6, 0xF8, 0x08, 0x41, 0x00, 0x2C, 0xEB, 0xD0, 0x63, 0x6A, 0x9B, 0x02, 0xDB, 0xD4, 0xE3, 0x6C, 0x1B, 0x6D, 0x00, 0x2B, +0xD7, 0xDA, 0x20, 0x46, 0x39, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xEF, 0xE7, 0x00, 0x27, 0x38, 0x46, 0x02, 0xB0, 0xBD, 0xE8, +0xF0, 0x87, 0x0E, 0x4B, 0x64, 0x6C, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0xDB, 0xA3, 0x88, 0x38, 0x46, +0x43, 0xF4, 0x00, 0x73, 0xA3, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x2C, 0xF5, 0xD1, 0x06, 0x49, 0x07, 0x48, +0x40, 0xF2, 0xDF, 0x42, 0x11, 0xF0, 0x88, 0xFF, 0xEE, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0xDF, 0xF8, 0x8C, 0x92, 0x99, 0xF8, 0x7E, 0x80, 0x83, 0xB0, 0x04, 0x46, 0x00, 0x27, 0x40, 0x46, 0x01, 0x97, 0xFB, 0xF7, +0x0D, 0xFE, 0x99, 0xF8, 0x7E, 0x00, 0xFF, 0xF7, 0x15, 0xFA, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x63, 0x6A, 0x9E, 0x02, +0x76, 0xD5, 0x03, 0xF4, 0x60, 0x10, 0xB0, 0xF5, 0x60, 0x1F, 0x65, 0x6C, 0x00, 0xF0, 0xE1, 0x80, 0xB0, 0xF5, 0x40, 0x1F, +0x00, 0xF0, 0xCE, 0x80, 0xAA, 0x88, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x8E, 0x4A, 0x12, 0x68, 0x92, 0xF8, 0x01, 0xC0, +0x00, 0xF0, 0xFF, 0x80, 0x2A, 0x6B, 0x52, 0x69, 0x00, 0x21, 0xC2, 0xF3, 0xC1, 0x1E, 0xC5, 0xE9, 0x0E, 0x11, 0x69, 0x63, +0x0E, 0x46, 0x0A, 0x46, 0x14, 0xE0, 0xD1, 0xF8, 0x4C, 0x31, 0x9A, 0x45, 0x02, 0xF1, 0x01, 0x03, 0x22, 0xD9, 0xDA, 0xB2, +0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x4E, 0x63, 0x56, 0x46, 0xC3, 0xF8, 0x3C, 0x41, 0x20, 0xD0, 0x24, 0x68, +0x34, 0xB3, 0x63, 0x6A, 0x03, 0xF4, 0x60, 0x10, 0xE1, 0x6C, 0xD1, 0xF8, 0x2C, 0xA0, 0xC3, 0xF3, 0x49, 0x2B, 0x0A, 0xF1, +0x03, 0x03, 0x23, 0xF0, 0x03, 0x03, 0x0B, 0xF1, 0x01, 0x0A, 0x03, 0xEB, 0x8A, 0x03, 0x9B, 0xB2, 0x96, 0x45, 0x05, 0xEB, +0x82, 0x01, 0x03, 0xEB, 0x06, 0x0A, 0xD6, 0xD8, 0x05, 0xEB, 0x82, 0x03, 0xB0, 0xF5, 0x60, 0x1F, 0x56, 0x46, 0xC3, 0xF8, +0x3C, 0x41, 0xDE, 0xD1, 0x6B, 0x6A, 0xB3, 0x42, 0x00, 0xF0, 0xCE, 0x80, 0x00, 0x23, 0xC5, 0xE9, 0x0D, 0x33, 0xEB, 0x63, +0x00, 0x2F, 0x49, 0xD0, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x9A, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, +0x00, 0x0F, 0x30, 0xD1, 0x93, 0x6B, 0x9B, 0x02, 0x00, 0xF1, 0x97, 0x80, 0x53, 0x68, 0x00, 0x2B, 0x4B, 0xD1, 0x61, 0x49, +0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0xC3, 0xE9, 0x01, 0xCC, 0x41, 0xF8, 0x08, 0x20, 0x40, 0xE0, +0xA3, 0x6C, 0x3B, 0xB3, 0xE3, 0x8B, 0xE2, 0x6C, 0x13, 0xF4, 0x00, 0x5F, 0xE3, 0x6A, 0xDB, 0x6B, 0x02, 0xF1, 0x14, 0x07, +0x14, 0xBF, 0xC3, 0xF3, 0x00, 0x13, 0xC3, 0xF3, 0xC0, 0x03, 0x01, 0x97, 0x93, 0xB3, 0x52, 0x4B, 0x1B, 0x68, 0x93, 0xF8, +0x01, 0xC0, 0x3A, 0x46, 0x08, 0xEB, 0x48, 0x03, 0x09, 0xEB, 0x83, 0x09, 0xC9, 0xF8, 0x24, 0x70, 0xBC, 0xF1, 0x00, 0x0F, +0xCE, 0xD0, 0x53, 0x68, 0xFB, 0xB9, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x49, 0x4B, 0x43, 0xF8, 0x08, 0x20, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x45, 0x4B, 0x1B, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x44, 0x4B, 0x54, 0x22, 0x08, 0xEB, 0x48, 0x01, +0x09, 0xEB, 0x81, 0x09, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0x22, 0x43, 0xF8, 0x08, 0x20, 0xC9, 0xF8, 0x24, 0x20, 0x43, 0x44, +0xBC, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0xC3, 0xE9, 0x01, 0xCC, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x50, 0x6A, 0x03, 0x88, +0x1D, 0x04, 0x99, 0xB2, 0xC7, 0xD5, 0xC1, 0xF3, 0x0E, 0x01, 0x01, 0x80, 0x94, 0xF8, 0x33, 0x10, 0x94, 0xF8, 0x32, 0x30, +0x32, 0x48, 0x04, 0x39, 0x04, 0x3B, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x32, 0x30, 0xD2, 0xE9, 0x0A, 0x31, 0x04, 0x39, +0x04, 0x3B, 0xC2, 0xE9, 0x0A, 0x31, 0x00, 0x68, 0x3A, 0x46, 0x90, 0xF8, 0x01, 0xC0, 0xB3, 0xE7, 0x2B, 0x4B, 0x01, 0xA9, +0xD3, 0xF8, 0x6C, 0x33, 0x20, 0x46, 0x98, 0x47, 0x26, 0x4A, 0x63, 0x6A, 0x12, 0x68, 0x07, 0x46, 0x92, 0xF8, 0x01, 0xC0, +0x03, 0xF4, 0x60, 0x10, 0x2C, 0xE7, 0x24, 0x4B, 0x21, 0x4E, 0xD3, 0xF8, 0x58, 0x33, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, +0x33, 0x68, 0x01, 0x90, 0x5B, 0x78, 0x07, 0x46, 0xD3, 0xB1, 0x08, 0xB1, 0x6B, 0x6D, 0x43, 0x60, 0xD5, 0xF8, 0x48, 0x01, +0x29, 0x46, 0x10, 0xF0, 0x13, 0xFA, 0x33, 0x68, 0x93, 0xF8, 0x01, 0xC0, 0x58, 0xE7, 0x7B, 0x68, 0x00, 0x2B, 0xB4, 0xD1, +0x15, 0x49, 0x54, 0x23, 0x03, 0xFB, 0x08, 0xF8, 0x01, 0xEB, 0x08, 0x03, 0x01, 0x20, 0xC3, 0xE9, 0x01, 0x70, 0x41, 0xF8, +0x08, 0x20, 0xA8, 0xE7, 0x00, 0x28, 0xE5, 0xD0, 0x2B, 0x69, 0x43, 0x60, 0xE2, 0xE7, 0x05, 0xF1, 0x0C, 0x07, 0xBC, 0xF1, +0x00, 0x0F, 0x03, 0xD0, 0x05, 0xF1, 0x50, 0x02, 0x01, 0x92, 0xF7, 0xE6, 0xD5, 0xF8, 0x38, 0x21, 0xD2, 0x6C, 0x14, 0x32, +0x01, 0x92, 0xF1, 0xE6, 0xD5, 0xF8, 0x38, 0x31, 0xA3, 0x42, 0x7F, 0xF4, 0x2D, 0xAF, 0x05, 0xEB, 0x82, 0x02, 0x56, 0x63, +0x2C, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, +0x70, 0xB5, 0x1E, 0x48, 0x82, 0xB0, 0x90, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x01, 0x92, 0x93, 0xB1, 0x90, 0xF8, 0x7F, 0x30, +0x04, 0x2B, 0x2A, 0xD0, 0x19, 0x4C, 0x01, 0xA8, 0xD4, 0xF8, 0xE8, 0x33, 0x98, 0x47, 0x08, 0xB3, 0xD4, 0xF8, 0xF8, 0x33, +0x98, 0x47, 0xD4, 0xF8, 0xD4, 0x33, 0x01, 0x98, 0x98, 0x47, 0x02, 0xB0, 0x70, 0xBD, 0x13, 0x4A, 0x13, 0x4D, 0xD2, 0xF8, +0x38, 0x14, 0x13, 0x4C, 0x80, 0xF8, 0x88, 0x30, 0xC2, 0xF8, 0x00, 0x34, 0x01, 0xF4, 0x7F, 0x41, 0x02, 0xF5, 0x88, 0x66, +0x02, 0xF5, 0x7F, 0x70, 0x4F, 0xF4, 0x00, 0x53, 0xC2, 0xF8, 0x38, 0x14, 0xC2, 0xF8, 0x20, 0x64, 0x28, 0x60, 0x23, 0x60, +0x02, 0xB0, 0x70, 0xBD, 0xFF, 0xF7, 0x28, 0xFC, 0xE1, 0xE7, 0x04, 0x4B, 0x68, 0x30, 0xD3, 0xF8, 0xF4, 0x33, 0x98, 0x47, +0x02, 0xB0, 0x70, 0xBD, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0x5D, 0x18, 0x00, 0xAC, 0x81, 0x32, 0x40, +0x80, 0x81, 0x32, 0x40, 0xF8, 0xB5, 0x2C, 0x4C, 0x2C, 0x4D, 0x40, 0xF2, 0x74, 0x42, 0x20, 0x46, 0x00, 0x21, 0x26, 0x46, +0xED, 0xF7, 0xF4, 0xF8, 0x4F, 0xF4, 0xE4, 0x73, 0x28, 0x4A, 0x26, 0xF8, 0x44, 0x3F, 0x4F, 0xF6, 0x30, 0x70, 0x48, 0xF2, +0xC8, 0x13, 0x04, 0xF5, 0x77, 0x77, 0x4F, 0xF0, 0x22, 0x0C, 0x04, 0xF2, 0xFD, 0x31, 0xC4, 0xF8, 0x40, 0x24, 0xA4, 0xF8, +0xDC, 0x33, 0xA4, 0xF8, 0xF4, 0x03, 0x04, 0xF5, 0x88, 0x63, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x12, 0xDF, 0xF8, 0x74, 0xE0, +0xC4, 0xF8, 0xB0, 0xC3, 0xC4, 0xE9, 0xEA, 0x71, 0xC4, 0xF8, 0xBC, 0x33, 0xC4, 0xF8, 0x20, 0x34, 0x63, 0x62, 0xA2, 0x63, +0xC4, 0xF8, 0x98, 0x53, 0xC4, 0xF8, 0xFC, 0x53, 0x25, 0x60, 0xC4, 0xF8, 0xA4, 0x03, 0xC4, 0xF8, 0xCC, 0x03, 0xC4, 0xF8, +0x30, 0x04, 0x04, 0xF1, 0x5B, 0x0C, 0x04, 0xF1, 0xB4, 0x03, 0x1E, 0x27, 0x04, 0xF5, 0x7C, 0x74, 0xA3, 0xF1, 0x14, 0x01, +0x5A, 0x1C, 0x43, 0xF8, 0x58, 0x5C, 0x43, 0xF8, 0x40, 0x7C, 0x43, 0xF8, 0x24, 0x0C, 0x43, 0xF8, 0x14, 0xEC, 0x43, 0xF8, +0x4C, 0x1C, 0x43, 0xF8, 0x08, 0x2C, 0x43, 0xE9, 0x12, 0x6C, 0x43, 0xF8, 0x0C, 0x3C, 0x5C, 0x33, 0x9C, 0x42, 0xE9, 0xD1, +0xF8, 0xBD, 0x00, 0xBF, 0x60, 0x5D, 0x18, 0x00, 0xBE, 0xBA, 0xFE, 0xCA, 0x1E, 0xAB, 0xDC, 0xBA, 0xDE, 0xFA, 0xFE, 0xCA, +0x2D, 0xE9, 0xF0, 0x41, 0x13, 0x4A, 0x14, 0x4B, 0x92, 0xF8, 0x7E, 0x40, 0xD3, 0xF8, 0xAC, 0x33, 0x12, 0x4F, 0x00, 0x22, +0x0E, 0x46, 0x21, 0x46, 0x05, 0x46, 0x4F, 0xF0, 0x54, 0x08, 0x98, 0x47, 0x0C, 0x20, 0x18, 0xFB, 0x04, 0x00, 0x38, 0x44, +0x10, 0xF0, 0x5E, 0xF9, 0x22, 0x46, 0x31, 0x46, 0x28, 0x46, 0xFC, 0xF7, 0x77, 0xF9, 0x6B, 0x6A, 0x03, 0xF4, 0x60, 0x13, +0xB3, 0xF5, 0x60, 0x1F, 0x05, 0xD1, 0x08, 0xFB, 0x04, 0x74, 0x6B, 0x6C, 0x63, 0x62, 0x02, 0x23, 0xA3, 0x76, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x90, 0xF8, 0x62, 0x40, 0x87, 0xB0, 0x84, 0xB9, 0x90, 0xF8, 0x64, 0x30, 0x6B, 0xB1, 0x90, 0xF8, 0x6C, 0x30, 0x58, 0x4A, +0x01, 0x93, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x25, 0x95, 0xF8, 0x25, 0x30, 0x13, 0xB1, 0x6B, 0x68, 0x9B, 0x06, +0x02, 0xD4, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x10, 0x22, 0x21, 0x46, 0x02, 0xA8, 0xED, 0xF7, 0x4D, 0xF8, 0x95, 0xF8, +0x23, 0x30, 0x4E, 0x4A, 0x4E, 0x49, 0x00, 0x94, 0x42, 0xF2, 0x34, 0x06, 0x03, 0xEB, 0xC3, 0x03, 0x06, 0xEB, 0x83, 0x03, +0x9E, 0x18, 0x01, 0xF1, 0x08, 0x0B, 0xA6, 0x46, 0x22, 0x46, 0xA2, 0x46, 0x20, 0x46, 0x56, 0xF8, 0x04, 0x3F, 0xB3, 0xF5, +0xFE, 0x0F, 0x1F, 0x46, 0x04, 0xF1, 0x01, 0x08, 0x28, 0xBF, 0x4F, 0xF4, 0xFE, 0x07, 0xF3, 0xB1, 0x42, 0x4C, 0x0B, 0x78, +0xE3, 0x5C, 0x06, 0xAC, 0x04, 0xEB, 0x83, 0x0C, 0x22, 0xFA, 0x03, 0xF9, 0x5C, 0xF8, 0x10, 0x5C, 0x3D, 0x44, 0x55, 0x45, +0x84, 0xBF, 0xAA, 0x46, 0x00, 0x93, 0x19, 0xF0, 0x01, 0x0F, 0x5F, 0xFA, 0x88, 0xF4, 0x38, 0x44, 0x4C, 0xF8, 0x10, 0x5C, +0x07, 0xD1, 0x01, 0x25, 0x05, 0xFA, 0x03, 0xF3, 0x1A, 0x43, 0xAE, 0x44, 0xD2, 0xB2, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x31, +0x8B, 0x45, 0xD2, 0xD1, 0x08, 0x2C, 0x41, 0xD0, 0xA4, 0xEB, 0x0E, 0x04, 0xE4, 0xB2, 0xA4, 0x02, 0x92, 0x01, 0xB0, 0xF5, +0x7D, 0x6F, 0x1E, 0xD8, 0x0F, 0x30, 0x0A, 0xF1, 0x0F, 0x0A, 0xC0, 0xF3, 0x07, 0x13, 0xCA, 0xF3, 0x07, 0x1A, 0x00, 0x21, +0x00, 0x98, 0x1B, 0x06, 0x43, 0xEA, 0x00, 0x33, 0x13, 0x43, 0x23, 0x43, 0x0B, 0x43, 0x01, 0x99, 0x08, 0x46, 0x21, 0x49, +0x4F, 0xF4, 0x1E, 0x72, 0x43, 0xEA, 0x0A, 0x43, 0x02, 0xFB, 0x00, 0x12, 0x43, 0xF0, 0x0F, 0x03, 0xC2, 0xF8, 0x04, 0x32, +0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB0, 0xF5, 0x7D, 0x4F, 0x0D, 0xD9, 0xB0, 0xF5, 0xFD, 0x2F, 0x18, 0xD8, 0x00, 0xF2, +0xFF, 0x70, 0x0A, 0xF2, 0xFF, 0x7A, 0xC0, 0xF3, 0xC7, 0x23, 0xCA, 0xF3, 0xC7, 0x2A, 0x4F, 0xF4, 0x00, 0x41, 0xD7, 0xE7, +0xFF, 0x30, 0x0A, 0xF1, 0xFF, 0x0A, 0xC0, 0xF3, 0x07, 0x23, 0xCA, 0xF3, 0x07, 0x2A, 0x4F, 0xF4, 0x80, 0x41, 0xCD, 0xE7, +0x4F, 0xF4, 0x40, 0x64, 0x00, 0x22, 0xBE, 0xE7, 0x47, 0xF6, 0xFF, 0x73, 0xBA, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x9A, 0x44, +0x03, 0xF5, 0xFE, 0x0A, 0xB0, 0xF5, 0xFE, 0x0F, 0x94, 0xBF, 0x18, 0x18, 0x03, 0xF5, 0xFE, 0x00, 0xC0, 0xF3, 0xC7, 0x33, +0xCA, 0xF3, 0xC7, 0x3A, 0x4F, 0xF4, 0x40, 0x41, 0xB4, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, +0xC0, 0xB2, 0x15, 0x00, 0xA0, 0xB2, 0x15, 0x00, 0x49, 0x4B, 0x4A, 0x4A, 0x4F, 0xF4, 0x80, 0x11, 0x2D, 0xE9, 0xF0, 0x47, +0x19, 0x60, 0x13, 0x68, 0x13, 0xF4, 0x40, 0x1F, 0xFB, 0xD1, 0xDF, 0xF8, 0x34, 0x81, 0x45, 0x4A, 0x98, 0xF8, 0x8C, 0x30, +0x4F, 0xF4, 0x80, 0x11, 0x11, 0x60, 0x00, 0x2B, 0x6E, 0xD0, 0x98, 0xF8, 0x7E, 0x60, 0xDF, 0xF8, 0x20, 0x91, 0x54, 0x23, +0x03, 0xFB, 0x06, 0x93, 0x9A, 0x7E, 0x00, 0x2A, 0x38, 0xD0, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x94, 0x20, 0x46, 0x62, 0x6A, +0x93, 0x88, 0x43, 0xF0, 0x10, 0x03, 0x93, 0x80, 0x1C, 0x30, 0x10, 0xF0, 0x55, 0xF8, 0x37, 0x4B, 0x53, 0xF8, 0x26, 0x00, +0x0F, 0xF0, 0x6A, 0xFF, 0x00, 0x23, 0xA3, 0x76, 0x63, 0x62, 0x06, 0xEB, 0x46, 0x04, 0x08, 0xEB, 0x84, 0x04, 0x94, 0xF8, +0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFB, 0xF7, 0x93, 0xF8, 0x65, 0x62, 0x2D, 0x4A, 0x2E, 0x49, +0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x99, 0x40, 0x22, 0x0A, 0x60, 0x99, 0xF8, +0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x89, 0xF8, 0x50, 0x30, 0x88, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, +0xFE, 0xF7, 0x66, 0xBE, 0xDC, 0x68, 0x62, 0x6A, 0x92, 0x02, 0x2D, 0xD4, 0x54, 0x25, 0xDF, 0xF8, 0x98, 0xA0, 0x20, 0x4F, +0x05, 0xFB, 0x06, 0x95, 0x11, 0xE0, 0xE3, 0x6C, 0x62, 0x6A, 0x19, 0x6D, 0x41, 0xF0, 0x00, 0x41, 0x41, 0xF4, 0x80, 0x01, +0x19, 0x65, 0x93, 0x02, 0x20, 0x46, 0x17, 0xD5, 0xD7, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0xEC, 0x68, 0x00, 0x2B, +0xA9, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE7, 0xDA, 0x00, 0x2C, 0xE5, 0xD1, 0x12, 0x49, +0x12, 0x48, 0x40, 0xF2, 0xB3, 0x72, 0x11, 0xF0, 0x0D, 0xFC, 0xDE, 0xE7, 0xBD, 0xE8, 0xF0, 0x87, 0xD7, 0xF8, 0xE4, 0x33, +0x98, 0x47, 0xA8, 0xE7, 0x5A, 0x69, 0x61, 0x6C, 0x52, 0x6C, 0x8A, 0x42, 0xCC, 0xD1, 0xD2, 0xF8, 0x38, 0x21, 0x12, 0x68, +0x5A, 0x61, 0xC7, 0xE7, 0x80, 0x81, 0x32, 0x40, 0x88, 0x81, 0x32, 0x40, 0x84, 0x81, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, +0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0x91, 0x15, 0x00, +0x94, 0x64, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x69, 0x4F, 0xDF, 0xF8, +0xCC, 0x81, 0x97, 0xF8, 0x7E, 0x60, 0x54, 0x25, 0x05, 0xFB, 0x06, 0x85, 0xAB, 0x7E, 0x53, 0xBB, 0xDF, 0xF8, 0xA0, 0xA1, +0xDF, 0xF8, 0xAC, 0x91, 0x15, 0xE0, 0xD4, 0xF8, 0x4C, 0xC0, 0xDF, 0xF8, 0xA0, 0xE1, 0xDC, 0xF8, 0x50, 0x30, 0x43, 0xF4, +0x80, 0x02, 0x00, 0x2B, 0x20, 0x46, 0x11, 0x46, 0x26, 0xDA, 0x63, 0x6A, 0xCC, 0xF8, 0x50, 0x20, 0x9C, 0x02, 0x23, 0xD5, +0xDE, 0xF8, 0xD8, 0x33, 0x98, 0x47, 0xAB, 0x7E, 0x7B, 0xB9, 0xDA, 0xF8, 0x00, 0x30, 0xEC, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xE2, 0xDA, 0x00, 0x2C, 0xE0, 0xD1, 0x53, 0x48, 0x4F, 0xF4, 0x02, 0x62, 0x49, 0x46, 0x11, 0xF0, 0xAE, 0xFB, +0xD9, 0xE7, 0x54, 0x22, 0x02, 0xFB, 0x06, 0x82, 0x02, 0x2B, 0x54, 0x6A, 0x0C, 0xBF, 0x04, 0xF1, 0x0C, 0x03, 0x04, 0xF1, +0x50, 0x03, 0xDB, 0x6B, 0x00, 0x2B, 0x29, 0xDB, 0xBD, 0xE8, 0xF0, 0x87, 0xDE, 0xF8, 0xE4, 0x33, 0x98, 0x47, 0x06, 0xEB, +0x46, 0x04, 0x07, 0xEB, 0x84, 0x04, 0x94, 0xF8, 0x2E, 0x50, 0x2D, 0xB9, 0x60, 0x6A, 0x18, 0xB1, 0x31, 0x46, 0xFA, 0xF7, +0xD1, 0xFF, 0x65, 0x62, 0x41, 0x4A, 0x42, 0x49, 0x13, 0x68, 0x23, 0xF0, 0x40, 0x03, 0x13, 0x60, 0x54, 0x23, 0x03, 0xFB, +0x06, 0x88, 0x40, 0x22, 0x0A, 0x60, 0x98, 0xF8, 0x50, 0x30, 0x00, 0x22, 0x01, 0x3B, 0x30, 0x46, 0x88, 0xF8, 0x50, 0x30, +0x87, 0xF8, 0x8C, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xFE, 0xF7, 0xA4, 0xBD, 0x18, 0x02, 0x35, 0xD5, 0xA3, 0x88, 0x99, 0x06, +0x13, 0xD4, 0xDF, 0xF8, 0xE0, 0x90, 0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x04, 0x25, 0xA3, 0x88, 0x9A, 0x06, 0x0A, 0xD4, +0xD9, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0x01, 0x3D, 0xF7, 0xD1, 0x2E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x42, 0xDB, 0x97, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x37, 0xD0, 0x2A, 0x49, 0x97, 0xF8, 0x64, 0x30, 0x0A, 0x68, 0x1B, 0x06, +0x22, 0xF0, 0xE0, 0x62, 0x03, 0xF0, 0xE0, 0x63, 0x13, 0x43, 0x0B, 0x60, 0xA3, 0x88, 0x25, 0x4A, 0x43, 0xF0, 0x10, 0x03, +0x52, 0xF8, 0x26, 0x00, 0xA3, 0x80, 0x0F, 0xF0, 0x4F, 0xFE, 0x54, 0x23, 0x03, 0xFB, 0x06, 0x83, 0x00, 0x22, 0x9A, 0x76, +0x5A, 0x62, 0xA2, 0xE7, 0x54, 0x20, 0x00, 0xFB, 0x06, 0x80, 0x1C, 0x30, 0x0F, 0xF0, 0x28, 0xFF, 0x97, 0xF8, 0x87, 0x30, +0x00, 0x2B, 0xE5, 0xD0, 0x17, 0x4A, 0x97, 0xF8, 0x65, 0x00, 0x13, 0x68, 0x11, 0x68, 0xC3, 0xF3, 0x02, 0x63, 0x01, 0x33, +0x83, 0x42, 0x28, 0xBF, 0x03, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x21, 0xF0, 0xE0, 0x61, 0x0B, 0x43, 0x13, 0x60, +0xD2, 0xE7, 0x10, 0x4B, 0x97, 0xF8, 0x7E, 0x00, 0xD3, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xCB, 0xE7, 0xA3, 0x88, 0x9B, 0x06, +0xB9, 0xD4, 0xBD, 0xE8, 0xF0, 0x47, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0x6A, 0x02, 0x11, 0xF0, 0xDD, 0xBA, 0x00, 0xBF, +0x94, 0x64, 0x17, 0x00, 0x3C, 0x91, 0x15, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, +0x54, 0x83, 0x32, 0x40, 0xC4, 0x90, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD4, 0x8E, 0x15, 0x00, +0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x0D, 0x4C, 0x90, 0x22, 0x00, 0x21, 0x20, 0x46, 0xEC, 0xF7, 0x09, 0xFE, 0xFF, 0xF7, +0x09, 0xFD, 0x40, 0xF2, 0xD3, 0x13, 0xE3, 0x66, 0xED, 0xF7, 0xA4, 0xFE, 0x07, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x70, 0x43, +0x18, 0xB1, 0x43, 0xF0, 0x30, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x43, 0xF0, 0x10, 0x43, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, +0x94, 0x64, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x43, 0x2A, 0x4C, 0x65, 0x68, 0x95, 0xB0, 0x00, 0x2D, +0x44, 0xD0, 0x29, 0x4E, 0xA7, 0x68, 0xD6, 0xF8, 0xD8, 0x31, 0x20, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, +0x00, 0x0F, 0x26, 0xD0, 0x01, 0x25, 0x24, 0x49, 0x68, 0x46, 0x50, 0x22, 0x23, 0xF0, 0x66, 0xFD, 0xA3, 0x69, 0x94, 0xF8, +0x62, 0x90, 0x23, 0xB1, 0x1E, 0x4E, 0x1F, 0x48, 0xD6, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xFF, 0xF7, 0xBD, 0xFF, 0xC4, 0xF8, +0x10, 0x80, 0x84, 0xF8, 0x62, 0x90, 0x18, 0x4C, 0x6B, 0x46, 0x22, 0x46, 0x0C, 0xAE, 0x58, 0x69, 0x19, 0x7E, 0x90, 0x62, +0x0C, 0x33, 0xB3, 0x42, 0x82, 0xF8, 0x2C, 0x10, 0x02, 0xF1, 0x0C, 0x02, 0xF5, 0xD1, 0xFD, 0xB9, 0x15, 0xB0, 0xBD, 0xE8, +0xF0, 0x83, 0xFF, 0xF7, 0xA5, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0x10, 0x4B, 0x10, 0x4A, 0x19, 0x69, 0x0B, 0x48, 0xD6, 0xF8, +0xE0, 0x31, 0xA7, 0x60, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x62, 0x60, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, +0xD4, 0xF8, 0x10, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0xC1, 0xD1, 0xFF, 0xF7, 0x8D, 0xFF, 0xC4, 0xF8, 0x10, 0x80, 0xDF, 0xE7, +0x01, 0x4E, 0xE4, 0xE7, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA8, 0x64, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, +0x95, 0x24, 0x13, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x42, 0x6D, 0xC3, 0x69, 0x91, 0xF8, 0x09, 0xC0, 0x9D, 0x68, 0x03, 0x8E, +0x88, 0x46, 0x91, 0x05, 0x02, 0xD5, 0x12, 0xF4, 0x80, 0x60, 0x3B, 0xD0, 0x12, 0x3B, 0x01, 0x2B, 0x05, 0xF1, 0x12, 0x05, +0x3A, 0xDD, 0x28, 0x4A, 0xDF, 0xF8, 0xA0, 0x90, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x0C, 0x2C, 0x40, 0xF2, 0xFD, 0x7E, +0x15, 0xE0, 0x03, 0x2B, 0x2A, 0xDD, 0x6A, 0x88, 0x12, 0xF0, 0x08, 0x06, 0xC2, 0xF3, 0x42, 0x01, 0x24, 0xD1, 0x19, 0xF8, +0x01, 0x20, 0x04, 0x32, 0x9A, 0x42, 0x2B, 0xDC, 0xBC, 0xF8, 0x20, 0x10, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0x11, 0xD0, +0x01, 0x2B, 0x15, 0x44, 0x1A, 0xDD, 0x2C, 0x88, 0xC4, 0xF3, 0x0A, 0x07, 0x77, 0x45, 0x13, 0xD0, 0x14, 0xF4, 0x00, 0x60, +0xE1, 0xD0, 0xBC, 0xF8, 0x20, 0x10, 0x02, 0x22, 0xB9, 0x42, 0xA3, 0xEB, 0x02, 0x03, 0xED, 0xD1, 0x14, 0xF4, 0x00, 0x60, +0x0B, 0xD1, 0x98, 0xF8, 0x0A, 0x30, 0xB3, 0xEB, 0x14, 0x3F, 0x0D, 0xD0, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x22, 0xDB, 0xE7, +0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0x23, 0xC8, 0xF8, 0xDC, 0x30, 0x01, 0x20, 0xF3, 0xE7, 0x30, 0x46, 0xF1, 0xE7, +0x08, 0xF1, 0xE0, 0x04, 0x02, 0x3A, 0xA9, 0x1C, 0x20, 0x46, 0x23, 0xF0, 0xBD, 0xFC, 0xC8, 0xF8, 0xDC, 0x40, 0x01, 0x20, +0xE6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x00, 0x96, 0x15, 0x00, 0x85, 0x4B, 0x86, 0x4A, 0x19, 0x68, 0x43, 0x6D, +0x2D, 0xE9, 0xF0, 0x4F, 0x00, 0x24, 0xC5, 0x69, 0x82, 0xF8, 0x88, 0x40, 0xB1, 0xF9, 0x00, 0x10, 0xA1, 0x42, 0x83, 0xB0, +0xC0, 0xF2, 0xC6, 0x80, 0x9E, 0x01, 0x40, 0xF1, 0xAD, 0x80, 0x00, 0x29, 0xC3, 0xF3, 0xCF, 0x30, 0xC3, 0xF3, 0xC9, 0x33, +0xC0, 0xF2, 0xB3, 0x80, 0x7A, 0x49, 0x10, 0x3B, 0xDB, 0xB2, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0x14, 0x94, 0xF8, +0x25, 0x00, 0x00, 0x28, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0x22, 0x50, 0x54, 0xF8, 0x26, 0x0F, 0x50, 0x67, 0x73, 0x48, +0x73, 0x4E, 0xA4, 0x88, 0x84, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x10, 0x69, 0x07, 0xFB, 0x05, 0x65, 0xA8, 0x42, 0x40, 0xF0, +0x93, 0x80, 0x6F, 0x48, 0x00, 0x68, 0x00, 0xF0, 0x3F, 0x00, 0x09, 0x28, 0x40, 0xF2, 0x8C, 0x80, 0x6C, 0x4C, 0x6D, 0x48, +0x24, 0x68, 0x05, 0x68, 0xD2, 0xF8, 0x68, 0x80, 0xC4, 0xF3, 0x0B, 0x10, 0x04, 0xF0, 0x0F, 0x09, 0xC4, 0xF3, 0x01, 0x4E, +0x24, 0x03, 0x00, 0x90, 0xA2, 0xF8, 0x7C, 0x00, 0x82, 0xF8, 0x7F, 0x90, 0x82, 0xF8, 0x83, 0xE0, 0xC5, 0xF3, 0x03, 0x10, +0x05, 0xF0, 0x07, 0x06, 0x40, 0xF1, 0x8B, 0x80, 0x4F, 0xF0, 0x02, 0x0B, 0x4F, 0xF4, 0x80, 0x64, 0x5F, 0x46, 0x01, 0x94, +0xC5, 0xF3, 0x00, 0x34, 0xC5, 0xF3, 0x42, 0x2C, 0x82, 0xF8, 0x80, 0x70, 0xF7, 0xB2, 0x82, 0xF8, 0x81, 0x00, 0x82, 0xF8, +0x87, 0x40, 0x82, 0xF8, 0x82, 0xC0, 0x82, 0xF8, 0x84, 0x70, 0xB9, 0xF1, 0x00, 0x0F, 0x79, 0xD0, 0x92, 0xF8, 0x86, 0x50, +0xDF, 0xF8, 0x64, 0x91, 0xD9, 0xF8, 0x00, 0x40, 0x00, 0x2C, 0xFB, 0xDA, 0xD9, 0xF8, 0x00, 0x90, 0x50, 0x4C, 0x02, 0x2E, +0x09, 0xEA, 0x04, 0x04, 0x76, 0xD8, 0x4F, 0x4F, 0x00, 0xEB, 0x40, 0x09, 0x57, 0xF8, 0x26, 0x70, 0xD9, 0x44, 0x37, 0xF8, +0x19, 0x90, 0xD8, 0xF8, 0x0C, 0x70, 0xDF, 0xF8, 0x3C, 0xA1, 0xBC, 0x42, 0x28, 0xBF, 0x3C, 0x46, 0x14, 0x67, 0xDA, 0xF8, +0x00, 0xB0, 0x01, 0x9F, 0x98, 0xF8, 0x1C, 0x80, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x03, 0x13, 0x07, 0x43, 0x01, 0x21, +0x47, 0xEA, 0xCE, 0x1E, 0x01, 0xFA, 0x05, 0xF5, 0x4F, 0xEA, 0x1B, 0x67, 0xD3, 0xF8, 0x4C, 0x11, 0x93, 0x66, 0x00, 0x9B, +0x27, 0x2C, 0x4E, 0xEA, 0x0C, 0x1C, 0x4F, 0xEA, 0x87, 0x17, 0x18, 0xFB, 0x05, 0xF8, 0x4C, 0xF4, 0x40, 0x5C, 0x46, 0xEA, +0xC3, 0x06, 0x94, 0xBF, 0x00, 0x24, 0x01, 0x24, 0x47, 0xF0, 0x13, 0x07, 0x18, 0xFB, 0x09, 0xF9, 0x82, 0xF8, 0x88, 0x40, +0xD7, 0x66, 0xA1, 0xF8, 0x82, 0xC0, 0xA1, 0xF8, 0x84, 0x60, 0xA2, 0xF8, 0x7A, 0x90, 0x09, 0xE0, 0xAB, 0x68, 0x59, 0x89, +0xA2, 0xF8, 0x74, 0x10, 0x99, 0x89, 0xA2, 0xF8, 0x76, 0x10, 0xDB, 0x89, 0xA2, 0xF8, 0x78, 0x30, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x10, 0xF4, 0x7C, 0x7F, 0x7F, 0xF4, 0x49, 0xAF, 0x27, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x53, 0x12, 0x07, 0xE0, +0x00, 0x8E, 0x1C, 0x28, 0x3F, 0xF6, 0x36, 0xAF, 0x22, 0x49, 0x24, 0x48, 0x40, 0xF6, 0x46, 0x12, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x4F, 0x11, 0xF0, 0xF9, 0xB8, 0x4F, 0xF0, 0x01, 0x0B, 0x4F, 0xF4, 0x00, 0x74, 0x5F, 0x46, 0x01, 0x94, 0x73, 0xE7, +0xAC, 0x0F, 0xDF, 0xF8, 0x7C, 0x90, 0xC5, 0xF3, 0x01, 0x65, 0x19, 0xF8, 0x04, 0x40, 0x82, 0xF8, 0x85, 0x40, 0x82, 0xF8, +0x86, 0x50, 0x7B, 0xE7, 0x03, 0x3F, 0x00, 0xEB, 0x40, 0x09, 0xC7, 0xF3, 0x46, 0x0A, 0x0B, 0xEB, 0x49, 0x09, 0x4F, 0xF0, +0x03, 0x0B, 0x1B, 0xFB, 0x0A, 0x99, 0xDF, 0xF8, 0x54, 0xA0, 0x3A, 0xF8, 0x19, 0x90, 0x07, 0xF0, 0x01, 0x07, 0x09, 0xFA, +0x07, 0xF9, 0x1F, 0xFA, 0x89, 0xF9, 0x7A, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x08, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x58, 0x83, 0x32, 0x40, 0x5C, 0x83, 0x32, 0x40, +0xFC, 0xFF, 0x0F, 0x00, 0x04, 0x96, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x50, 0x90, 0x15, 0x00, 0xB0, 0x93, 0x15, 0x00, +0x60, 0x83, 0x32, 0x40, 0x64, 0x83, 0x32, 0x40, 0xA8, 0xB2, 0x15, 0x00, 0x70, 0x95, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x4C, +0xD4, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xD4, 0xF8, 0xEC, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, +0x10, 0xB5, 0x03, 0xF0, 0x85, 0xFB, 0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x03, 0xD4, 0x07, 0x4B, 0x00, 0x24, 0x1C, 0x61, +0x10, 0xBD, 0x04, 0x46, 0xED, 0xF7, 0x62, 0xFC, 0x00, 0x28, 0xF6, 0xD0, 0x02, 0x4B, 0x1C, 0x61, 0x10, 0xBD, 0x00, 0xBF, +0x04, 0x00, 0x32, 0x40, 0x94, 0x64, 0x17, 0x00, 0x18, 0x4B, 0x1B, 0x69, 0x63, 0xB3, 0x93, 0xF8, 0x64, 0x20, 0x4A, 0xB3, +0x16, 0x4A, 0x93, 0xF8, 0x6C, 0x30, 0x10, 0x68, 0x15, 0x49, 0x40, 0xF0, 0x10, 0x00, 0x30, 0xB4, 0x10, 0x60, 0x10, 0x68, +0x13, 0x4D, 0x14, 0x4C, 0x40, 0xF4, 0x00, 0x60, 0x10, 0x60, 0x10, 0x68, 0x40, 0xF4, 0x80, 0x50, 0x10, 0x60, 0x2A, 0x68, +0x10, 0x48, 0xC4, 0xF8, 0x50, 0x04, 0x42, 0xF4, 0x00, 0x72, 0x2A, 0x60, 0x0A, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x0A, 0x60, +0x0A, 0x68, 0x10, 0x33, 0xDB, 0xB2, 0x43, 0xEA, 0x83, 0x23, 0x22, 0xF4, 0x00, 0x32, 0xC4, 0xF8, 0x4C, 0x34, 0x30, 0xBC, +0x0A, 0x60, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, +0x24, 0x03, 0x32, 0x40, 0x60, 0x5D, 0x18, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0x08, 0xB5, 0x0F, 0x4B, 0x1B, 0x69, 0x1B, 0xB1, +0x0E, 0x4B, 0xD3, 0xF8, 0xC4, 0x33, 0x98, 0x47, 0x0D, 0x48, 0x0E, 0x4B, 0x02, 0x68, 0x0E, 0x49, 0x22, 0xF4, 0x00, 0x72, +0x02, 0x60, 0x1A, 0x68, 0x22, 0xF0, 0x10, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x00, 0x62, 0x1A, 0x60, 0x1A, 0x68, +0x22, 0xF4, 0x80, 0x52, 0x1A, 0x60, 0x0B, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x0B, 0x60, 0x08, 0xBD, 0x94, 0x64, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x24, 0x03, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x54, 0x83, 0x32, 0x40, 0x43, 0x6C, 0x13, 0xB1, +0x9B, 0x88, 0x9A, 0x05, 0x0C, 0xD4, 0xC3, 0x6A, 0xDB, 0x6B, 0x9B, 0x06, 0x43, 0xBF, 0x91, 0xF8, 0x2D, 0x31, 0x48, 0xF2, +0x07, 0x00, 0x40, 0xEA, 0x43, 0x20, 0xD1, 0xF8, 0x04, 0x02, 0x70, 0x47, 0x01, 0x4B, 0xD8, 0x6E, 0x70, 0x47, 0x00, 0xBF, +0x94, 0x64, 0x17, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, 0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, +0x01, 0x01, 0x88, 0x40, 0x70, 0x47, 0x00, 0xBF, 0xE0, 0x94, 0x15, 0x00, 0x4B, 0x08, 0x03, 0x22, 0x02, 0xFB, 0x03, 0x00, +0x03, 0x4B, 0x33, 0xF8, 0x10, 0x00, 0x01, 0xF0, 0x01, 0x01, 0x88, 0x40, 0x80, 0xB2, 0x70, 0x47, 0x70, 0x95, 0x15, 0x00, +0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4F, 0x84, 0x6A, 0x3D, 0x68, 0x90, 0xF8, 0x1D, 0x80, 0xB5, 0xF9, 0x00, 0xC0, 0xBC, 0xF1, +0x00, 0x0F, 0x16, 0x46, 0x99, 0x46, 0xC4, 0xF3, 0x41, 0x25, 0x12, 0xDB, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x1A, 0x60, +0x04, 0xF0, 0x0F, 0x04, 0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x08, 0x23, 0x04, 0xEB, 0x44, 0x04, 0xDB, 0x68, +0x33, 0x60, 0x05, 0xEB, 0x44, 0x00, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x29, 0x1E, 0xD0, 0x1C, 0x49, 0x1C, 0x48, 0x40, 0xF6, +0xF5, 0x12, 0x10, 0xF0, 0xF5, 0xFF, 0x39, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0xC4, 0xF3, 0x02, 0x12, 0x01, 0x32, 0x00, 0x29, +0x4F, 0xEA, 0x14, 0x13, 0xC9, 0xF8, 0x00, 0x20, 0x04, 0xF0, 0x0F, 0x04, 0xDC, 0xDA, 0x5B, 0x07, 0x11, 0xD4, 0x0B, 0x2C, +0xD8, 0xD9, 0x10, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xFF, 0x12, 0x10, 0xF0, 0xDD, 0xFF, 0xD1, 0xE7, 0xC4, 0xF3, 0x02, 0x12, +0x01, 0x32, 0x1A, 0x60, 0x23, 0x09, 0x5B, 0x07, 0x04, 0xF0, 0x0F, 0x04, 0xED, 0xD5, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, +0xFE, 0x12, 0x10, 0xF0, 0xCD, 0xFF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE2, 0xDB, 0xBC, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0xF8, 0x93, 0x15, 0x00, +0xE0, 0x91, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x14, 0x4E, 0xDF, 0xF8, 0x54, 0xC0, 0x35, 0x69, 0x04, 0x38, 0x31, 0x46, +0x05, 0xF1, 0x08, 0x04, 0x05, 0xF1, 0x18, 0x0E, 0x00, 0x27, 0x50, 0xF8, 0x04, 0x2F, 0x13, 0x09, 0x02, 0xF0, 0x0F, 0x08, +0x03, 0xF4, 0x7F, 0x63, 0x43, 0xEA, 0x08, 0x03, 0x12, 0x0C, 0x8B, 0x62, 0x81, 0xF8, 0x2C, 0x20, 0x25, 0xB1, 0x22, 0x68, +0x02, 0xEA, 0x0C, 0x02, 0x13, 0x43, 0x8B, 0x62, 0x04, 0x34, 0xA6, 0x45, 0x4F, 0x62, 0x01, 0xF1, 0x0C, 0x01, 0xE6, 0xD1, +0x01, 0x23, 0x86, 0xF8, 0x62, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, 0x00, 0xF0, 0xFF, 0xFF, +0x03, 0x4B, 0x02, 0x78, 0x83, 0xF8, 0x64, 0x20, 0x42, 0x78, 0x83, 0xF8, 0x65, 0x20, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, +0x0A, 0x4B, 0x9A, 0x69, 0x8A, 0xB1, 0x30, 0xB4, 0x01, 0xEB, 0x41, 0x02, 0x03, 0xEB, 0x82, 0x02, 0x4C, 0x00, 0x92, 0xF8, +0x2E, 0x50, 0x05, 0xB1, 0x50, 0x62, 0x21, 0x44, 0x03, 0xEB, 0x81, 0x03, 0x01, 0x22, 0x30, 0xBC, 0x83, 0xF8, 0x2D, 0x20, +0x70, 0x47, 0x70, 0x47, 0x94, 0x64, 0x17, 0x00, 0x08, 0x4A, 0x09, 0x4B, 0x11, 0x69, 0x09, 0x4A, 0x10, 0xB4, 0x01, 0xF5, +0x9C, 0x51, 0x08, 0x4C, 0x5C, 0x60, 0x98, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x18, 0x46, 0x08, 0x31, 0xD2, 0xF8, 0xE0, 0x31, +0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x94, 0x64, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x95, 0x24, 0x13, 0x00, +0x08, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, 0xBE, 0x24, +0x8A, 0x42, 0x00, 0xD1, 0x70, 0x47, 0x43, 0x6C, 0x28, 0x30, 0x59, 0x6A, 0xFE, 0xF7, 0xF2, 0xBB, 0x18, 0x88, 0x17, 0x00, +0xF8, 0xB5, 0x0E, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x40, 0xF2, 0xFF, 0x31, 0xB3, 0xF8, +0xBE, 0x24, 0x8A, 0x42, 0x0F, 0xD0, 0xD0, 0xE9, 0x12, 0x67, 0x1D, 0x46, 0x06, 0xF1, 0x3C, 0x04, 0x4C, 0x36, 0x20, 0x46, +0xF9, 0x6A, 0x04, 0x34, 0xFE, 0xF7, 0xD8, 0xFB, 0xB4, 0x42, 0x02, 0xD0, 0xB5, 0xF8, 0xBE, 0x24, 0xF5, 0xE7, 0xF8, 0xBD, +0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x9C, 0x4E, 0xD0, 0xF8, 0x44, 0xB0, 0xC7, 0x6C, 0x96, 0xF8, 0x7E, 0x50, +0x96, 0xF8, 0x87, 0x30, 0x11, 0xF4, 0x00, 0x09, 0x83, 0xB0, 0x04, 0x46, 0x8A, 0x46, 0x3E, 0xD0, 0x7B, 0xBB, 0xDF, 0xF8, +0x58, 0x82, 0x28, 0x46, 0xD8, 0xF8, 0xC0, 0x33, 0x98, 0x47, 0xD8, 0xF8, 0x9C, 0x32, 0x98, 0x47, 0xBB, 0xF8, 0x04, 0x30, +0x99, 0x06, 0x49, 0xD5, 0x13, 0xF0, 0x40, 0x02, 0x69, 0xD0, 0x58, 0x46, 0xFD, 0xF7, 0x14, 0xFE, 0x00, 0x23, 0xDF, 0xF8, +0x4C, 0x82, 0x63, 0x64, 0xB9, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x89, 0x4B, 0x00, 0x22, 0xD3, 0xF8, 0xAC, 0x33, 0x29, 0x46, +0x20, 0x46, 0x98, 0x47, 0x54, 0x20, 0x00, 0xFB, 0x05, 0x80, 0x0C, 0x30, 0x0F, 0xF0, 0xD2, 0xFA, 0xA3, 0x88, 0x00, 0x2B, +0x47, 0xD1, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFC, 0xF7, 0x0B, 0xB9, 0x7F, 0x48, 0x96, 0xF8, 0x64, 0x30, +0x01, 0x68, 0xDF, 0xF8, 0xF0, 0x81, 0x1B, 0x06, 0x21, 0xF0, 0xE0, 0x61, 0x03, 0xF0, 0xE0, 0x63, 0x0B, 0x43, 0x03, 0x60, +0xC7, 0xE7, 0x00, 0x2B, 0xC8, 0xD0, 0x77, 0x48, 0x96, 0xF8, 0x65, 0xE0, 0x01, 0x68, 0x02, 0x68, 0xC1, 0xF3, 0x02, 0x61, +0x4B, 0x1C, 0x73, 0x45, 0x28, 0xBF, 0x73, 0x46, 0x1B, 0x06, 0x03, 0xF0, 0xE0, 0x63, 0x22, 0xF0, 0xE0, 0x6C, 0x43, 0xEA, +0x0C, 0x03, 0x03, 0x60, 0xBB, 0xF8, 0x04, 0x30, 0x99, 0x06, 0xB5, 0xD4, 0x1C, 0x23, 0xDF, 0xF8, 0xC4, 0x81, 0x54, 0x20, +0x10, 0xFB, 0x05, 0x30, 0x40, 0x44, 0x0F, 0xF0, 0x99, 0xFA, 0x58, 0x46, 0xFD, 0xF7, 0xC4, 0xFD, 0x00, 0x23, 0x63, 0x64, +0xB9, 0xF1, 0x00, 0x0F, 0xB1, 0xD1, 0xCA, 0xF3, 0x07, 0x29, 0xB9, 0xF1, 0x04, 0x0F, 0x1F, 0xD9, 0x3B, 0x6D, 0x43, 0xF4, +0x80, 0x33, 0x3B, 0x65, 0xA7, 0xE7, 0x2A, 0x46, 0x51, 0x46, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xFB, 0xF7, +0x9D, 0xBA, 0x3B, 0x6D, 0x00, 0x92, 0x23, 0xF4, 0x00, 0x03, 0x2A, 0xF4, 0x00, 0x0A, 0x58, 0x46, 0x3B, 0x65, 0xCA, 0xF3, +0x07, 0x29, 0xFD, 0xF7, 0xA1, 0xFD, 0x00, 0x9A, 0xDF, 0xF8, 0x64, 0x81, 0x62, 0x64, 0xB9, 0xF1, 0x04, 0x0F, 0xDF, 0xD8, +0xD4, 0xF8, 0x48, 0xA0, 0xB9, 0xF1, 0x00, 0x0F, 0x25, 0xD0, 0x0A, 0xF1, 0x28, 0x0B, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, +0x83, 0x03, 0x09, 0xF1, 0x01, 0x09, 0x59, 0x6A, 0xDA, 0xE9, 0x17, 0x32, 0xBB, 0x64, 0x4F, 0xEA, 0x09, 0x23, 0xC7, 0xE9, +0x0D, 0x2B, 0x3B, 0x65, 0x07, 0xF1, 0x14, 0x02, 0x6B, 0x00, 0x00, 0x29, 0x4B, 0xD0, 0xB9, 0x61, 0x54, 0x20, 0x00, 0xFB, +0x05, 0x88, 0x1D, 0x44, 0x98, 0xF8, 0x50, 0x30, 0x06, 0xEB, 0x85, 0x06, 0x01, 0x33, 0x72, 0x62, 0x88, 0xF8, 0x50, 0x30, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE3, 0x6A, 0x0A, 0xF1, 0x28, 0x0B, 0x03, 0xF1, 0x40, 0x0C, 0x1A, 0x46, 0x0A, 0xF1, +0x24, 0x01, 0x52, 0xF8, 0x04, 0x0B, 0x41, 0xF8, 0x04, 0x0F, 0x62, 0x45, 0xF9, 0xD1, 0xE2, 0x8B, 0x92, 0x04, 0x26, 0xD5, +0x33, 0x4A, 0x34, 0x48, 0x11, 0x68, 0x62, 0x7F, 0xB1, 0xF9, 0x00, 0x10, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, 0x02, 0x02, +0x00, 0x29, 0xD2, 0xF8, 0x4C, 0x21, 0x00, 0x92, 0x29, 0xDB, 0x00, 0x9A, 0x59, 0x69, 0xD2, 0xF8, 0x9C, 0x20, 0xCA, 0xF8, +0x40, 0x10, 0x59, 0x6A, 0xCA, 0xF8, 0x50, 0x10, 0xC2, 0xF3, 0xC2, 0x21, 0x05, 0x29, 0xCA, 0xF8, 0x3C, 0x20, 0x25, 0xD0, +0xDB, 0x6B, 0x5B, 0x07, 0x05, 0xD4, 0xDA, 0xF8, 0x2C, 0x30, 0x23, 0xF4, 0xC0, 0x73, 0xCA, 0xF8, 0x2C, 0x30, 0x20, 0x46, +0xFF, 0xF7, 0xDC, 0xFE, 0x9F, 0xE7, 0x54, 0x21, 0x01, 0xFB, 0x05, 0xF1, 0x1E, 0x48, 0x48, 0xF8, 0x01, 0x20, 0x00, 0x68, +0x40, 0x78, 0x41, 0x44, 0x00, 0x28, 0xA9, 0xD1, 0xC1, 0xE9, 0x01, 0x00, 0xA6, 0xE7, 0x00, 0x2A, 0xD3, 0xD1, 0x19, 0x49, +0x19, 0x48, 0x01, 0x93, 0x40, 0xF2, 0x4B, 0x12, 0x10, 0xF0, 0xFE, 0xFD, 0x01, 0x9B, 0xCA, 0xE7, 0x00, 0x98, 0xDA, 0xF8, +0x4C, 0x10, 0x90, 0xF8, 0xA1, 0x00, 0x02, 0xF4, 0xC0, 0x62, 0xB2, 0xF5, 0x80, 0x6F, 0x14, 0xBF, 0x4F, 0xF4, 0x80, 0x3C, +0x4F, 0xF4, 0x00, 0x3C, 0x21, 0xF4, 0x40, 0x32, 0x42, 0xEA, 0x0C, 0x02, 0x20, 0xB1, 0x42, 0xF4, 0x80, 0x22, 0xCA, 0xF8, +0x4C, 0x20, 0xC1, 0xE7, 0x22, 0xF4, 0x80, 0x22, 0xCA, 0xF8, 0x4C, 0x20, 0xBC, 0xE7, 0x00, 0xBF, 0x94, 0x64, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x54, 0x83, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, 0x10, 0xB5, 0x05, 0x4C, 0x20, 0x46, 0x0F, 0xF0, +0x6F, 0xF9, 0x10, 0xF0, 0x25, 0xFE, 0x01, 0x38, 0xC0, 0xB2, 0xE0, 0x72, 0xA0, 0x72, 0x10, 0xBD, 0x24, 0x65, 0x17, 0x00, +0xC2, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x02, 0x38, 0x85, 0xB0, 0x98, 0xF8, 0x62, 0x30, +0x02, 0x2B, 0x17, 0xD1, 0x4F, 0xF4, 0x1E, 0x79, 0x93, 0x46, 0x0C, 0x46, 0x09, 0xFB, 0x01, 0xF2, 0xBA, 0x49, 0x01, 0x92, +0x8E, 0x18, 0xB0, 0xF8, 0x00, 0xA0, 0x96, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x05, 0x46, 0x41, 0xF2, 0x04, 0x42, +0x07, 0xD0, 0x0A, 0xEA, 0x02, 0x0A, 0xBA, 0xF5, 0x80, 0x5F, 0x5A, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0xEA, +0x02, 0x02, 0x00, 0xF0, 0x6B, 0x81, 0x0A, 0xF0, 0xFC, 0x03, 0xA4, 0x2B, 0x00, 0xF0, 0x75, 0x82, 0x0A, 0xF0, 0x8C, 0x03, +0x88, 0x2B, 0xEF, 0xD1, 0x0A, 0xF4, 0x40, 0x7A, 0xBA, 0xF5, 0x40, 0x7F, 0x0C, 0xBF, 0xEF, 0x8B, 0x2F, 0x8B, 0xA7, 0x4B, +0xA5, 0x49, 0xA7, 0x4A, 0x07, 0xF0, 0x07, 0x07, 0x4F, 0xF4, 0x1E, 0x75, 0xDB, 0x5D, 0x05, 0xFB, 0x04, 0x15, 0xD2, 0x5C, +0x95, 0xF8, 0x2E, 0x31, 0x1A, 0x42, 0xD9, 0xD0, 0x95, 0xF8, 0x31, 0x30, 0x13, 0xF0, 0x0C, 0x0F, 0x00, 0xF0, 0x7E, 0x82, +0x95, 0xF8, 0x32, 0x20, 0x12, 0xF0, 0x06, 0x0F, 0xCE, 0xD1, 0x18, 0x07, 0x95, 0xF8, 0x2F, 0x91, 0x40, 0xF1, 0x8A, 0x82, +0x99, 0x4B, 0x02, 0x22, 0x85, 0xF8, 0x32, 0x20, 0xD3, 0xF8, 0x20, 0x33, 0x31, 0x46, 0x40, 0x46, 0x4A, 0x46, 0x98, 0x47, +0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x7A, 0x82, 0xA9, 0xEB, 0x00, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0x00, 0xF3, 0x74, 0x82, +0x8C, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x24, 0x00, 0x23, 0x1A, 0x46, 0x94, 0xF8, 0x23, 0x00, 0x47, 0xF0, +0x10, 0x01, 0xFC, 0xF7, 0xA9, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x32, 0x30, 0xA4, 0xE7, 0x00, 0x22, 0x0C, 0x21, 0x49, 0x20, +0x0E, 0xF0, 0x58, 0xFC, 0x4F, 0xF0, 0x01, 0x09, 0x86, 0xF8, 0x24, 0x90, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x0E, 0xF0, +0x7F, 0xFC, 0x96, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x58, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x54, 0xD8, 0x96, 0xF8, +0x22, 0x20, 0x77, 0x48, 0x7B, 0x4D, 0xCD, 0xF8, 0x08, 0x90, 0x9E, 0x23, 0xA4, 0x21, 0x11, 0xFB, 0x02, 0x31, 0x07, 0xFB, +0x02, 0x07, 0x4F, 0x23, 0x46, 0x22, 0x13, 0xFB, 0x04, 0x24, 0x71, 0x4A, 0x02, 0xF5, 0x16, 0x73, 0x02, 0xEB, 0xC4, 0x04, +0x01, 0x9A, 0x1A, 0x44, 0x00, 0xEB, 0xC1, 0x0A, 0x91, 0x46, 0xD6, 0xF8, 0x08, 0x32, 0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, +0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x6D, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x2B, 0x68, 0xA4, 0xF1, 0x28, 0x00, 0x01, 0x33, +0xAA, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x2B, 0x60, 0x0F, 0xF0, 0x98, 0xF9, 0xD6, 0xE9, 0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, +0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x99, 0xF8, 0x2B, 0x68, 0x5A, 0x1E, 0x2B, 0xB1, 0x60, 0x4B, 0x2A, 0x60, +0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x21, 0x46, 0x08, 0x36, 0x0A, 0xF1, +0x08, 0x0A, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0x7B, 0xF9, 0x20, 0x46, 0x0F, 0xF0, 0x82, 0xF8, 0x08, 0x34, 0x4C, 0x45, +0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0xDE, 0xFF, 0x4D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x36, 0x96, 0xF8, +0xDE, 0x20, 0x00, 0x2A, 0x40, 0xF0, 0x82, 0x80, 0x0B, 0xF1, 0x0A, 0x05, 0x48, 0x4B, 0xED, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, +0x09, 0xFB, 0x05, 0xF9, 0x03, 0xEB, 0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x73, 0xD0, 0x02, 0x23, 0x0C, 0x21, +0x49, 0x20, 0x0E, 0xF0, 0xD5, 0xFB, 0x4F, 0xF0, 0x01, 0x0A, 0x84, 0xF8, 0x24, 0xA0, 0x05, 0x70, 0x80, 0xF8, 0x01, 0xA0, +0x0E, 0xF0, 0xFC, 0xFB, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xA9, 0x81, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, +0x00, 0xF2, 0xA4, 0x81, 0x94, 0xF8, 0x22, 0x00, 0xCD, 0xF8, 0x08, 0xA0, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x00, 0x33, +0x4F, 0xF0, 0x46, 0x0A, 0x4F, 0x21, 0x11, 0xFB, 0x05, 0xAA, 0x36, 0x4A, 0x2E, 0x4E, 0x2E, 0x49, 0x07, 0xFB, 0x00, 0x67, +0x01, 0xEB, 0xC3, 0x05, 0x30, 0x4E, 0xA2, 0xF5, 0x16, 0x73, 0x03, 0xEB, 0xCA, 0x0A, 0x91, 0x44, 0xD4, 0xF8, 0x08, 0x32, +0x1B, 0xB3, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0x33, 0x68, +0xAA, 0xF1, 0x28, 0x00, 0x01, 0x33, 0xA5, 0xF1, 0x28, 0x01, 0x01, 0x90, 0x33, 0x60, 0x0F, 0xF0, 0x13, 0xF9, 0xD4, 0xE9, +0x82, 0x23, 0x01, 0x98, 0xC7, 0xF8, 0xC8, 0x24, 0xC7, 0xF8, 0xCC, 0x34, 0x0F, 0xF0, 0x14, 0xF8, 0x33, 0x68, 0x5A, 0x1E, +0x2B, 0xB1, 0x1E, 0x4B, 0x32, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x32, 0x28, 0x46, +0x51, 0x46, 0x08, 0x34, 0x08, 0x35, 0x08, 0x37, 0x23, 0xB1, 0x0F, 0xF0, 0xF7, 0xF8, 0x50, 0x46, 0x0E, 0xF0, 0xFE, 0xFF, +0x0A, 0xF1, 0x08, 0x0A, 0xCA, 0x45, 0xC7, 0xD1, 0x40, 0x20, 0x0E, 0xF0, 0x59, 0xFF, 0x0B, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x0B, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x07, 0x48, 0x0B, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x03, +0x01, 0x32, 0x83, 0xF8, 0xDE, 0x20, 0xD1, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, +0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0xA4, 0xB2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x0C, 0x21, 0x49, 0x20, 0x02, 0x92, 0x0E, 0xF0, +0x41, 0xFB, 0x02, 0x9A, 0x86, 0xF8, 0x24, 0x20, 0x04, 0x70, 0x42, 0x70, 0x0E, 0xF0, 0x6A, 0xFB, 0x96, 0xF8, 0x24, 0x30, +0x00, 0x2B, 0x60, 0xD1, 0x96, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x96, 0xF8, 0x22, 0x20, 0xA8, 0x48, 0xCD, 0xF8, +0x08, 0x90, 0xA4, 0x21, 0x9E, 0x23, 0x11, 0xFB, 0x02, 0x33, 0xA6, 0x49, 0xDF, 0xF8, 0xA0, 0xA2, 0x03, 0x94, 0x07, 0xFB, +0x02, 0x19, 0x4F, 0x25, 0x01, 0xEB, 0xC3, 0x07, 0x46, 0x22, 0x01, 0x9B, 0x15, 0xFB, 0x04, 0x25, 0x00, 0xF5, 0x16, 0x72, +0x13, 0x44, 0x3C, 0x46, 0x00, 0xEB, 0xC5, 0x05, 0x1F, 0x46, 0xD6, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, +0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x99, 0x4B, 0x02, 0x9A, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA5, 0xF1, 0x28, 0x00, +0x01, 0x32, 0xA4, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0F, 0xF0, 0x7E, 0xF8, 0xD6, 0xE9, 0x82, 0x21, +0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0x7F, 0xFF, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, +0x32, 0xB1, 0x8B, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD6, 0xF8, 0x30, 0x22, +0x20, 0x46, 0x29, 0x46, 0x08, 0x36, 0x08, 0x34, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0F, 0xF0, 0x5F, 0xF8, 0x28, 0x46, +0x0E, 0xF0, 0x66, 0xFF, 0x08, 0x35, 0xBD, 0x42, 0xC3, 0xD1, 0x40, 0x20, 0x03, 0x9C, 0x0E, 0xF0, 0xC1, 0xFE, 0x7E, 0x4D, +0x21, 0x46, 0xEB, 0x68, 0x40, 0x46, 0x98, 0x47, 0x79, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, +0xDE, 0xA0, 0x0A, 0xF1, 0xFF, 0x3A, 0x5F, 0xFA, 0x8A, 0xFA, 0x83, 0xF8, 0xDE, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, +0x84, 0x80, 0x0B, 0xF1, 0x0A, 0x06, 0x6F, 0x49, 0xF6, 0xB2, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x06, 0xF9, 0x01, 0xEB, +0x09, 0x04, 0x94, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0x71, 0xD0, 0x02, 0x23, 0x52, 0x46, 0x0C, 0x21, 0x49, 0x20, 0x0E, 0xF0, +0xAB, 0xFA, 0x84, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0x0E, 0xF0, 0xD4, 0xFA, 0x94, 0xF8, 0x24, 0x30, +0x00, 0x2B, 0x60, 0xD1, 0x94, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x5C, 0xD8, 0x94, 0xF8, 0x22, 0x10, 0x5E, 0x4A, 0xDF, 0xF8, +0x88, 0xC1, 0xDF, 0xF8, 0x80, 0xA1, 0x02, 0x96, 0x9E, 0x23, 0xA4, 0x20, 0x10, 0xFB, 0x01, 0x30, 0x07, 0xFB, 0x01, 0x27, +0x4F, 0x23, 0x46, 0x21, 0x13, 0xFB, 0x06, 0x13, 0xAC, 0xF5, 0x16, 0x71, 0x02, 0xEB, 0xC0, 0x0B, 0xE1, 0x44, 0x01, 0xEB, +0xC3, 0x03, 0x5E, 0x46, 0xCB, 0x46, 0xB9, 0x46, 0x1F, 0x46, 0xD4, 0xF8, 0x08, 0x22, 0x3A, 0xB3, 0xEF, 0xF3, 0x10, 0x82, +0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x4E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDA, 0xF8, 0x00, 0x20, 0xA7, 0xF1, 0x28, 0x00, +0x01, 0x32, 0xA6, 0xF1, 0x28, 0x01, 0x01, 0x90, 0xCA, 0xF8, 0x00, 0x20, 0x0E, 0xF0, 0xE8, 0xFF, 0xD4, 0xE9, 0x82, 0x21, +0x01, 0x98, 0xC9, 0xF8, 0xC8, 0x24, 0xC9, 0xF8, 0xCC, 0x14, 0x0E, 0xF0, 0xE9, 0xFE, 0xDA, 0xF8, 0x00, 0x20, 0x51, 0x1E, +0x32, 0xB1, 0x40, 0x4B, 0xCA, 0xF8, 0x00, 0x10, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xD4, 0xF8, 0x30, 0x22, +0x30, 0x46, 0x39, 0x46, 0x08, 0x34, 0x08, 0x36, 0x09, 0xF1, 0x08, 0x09, 0x22, 0xB1, 0x0E, 0xF0, 0xC9, 0xFF, 0x38, 0x46, +0x0E, 0xF0, 0xD0, 0xFE, 0x08, 0x37, 0x5F, 0x45, 0xC3, 0xD1, 0x40, 0x20, 0x02, 0x9E, 0x0E, 0xF0, 0x2B, 0xFE, 0xEB, 0x68, +0x31, 0x46, 0x40, 0x46, 0x98, 0x47, 0xD5, 0xF8, 0x0C, 0x32, 0x40, 0x46, 0xDC, 0xE6, 0x96, 0xF8, 0x31, 0x20, 0x12, 0xF0, +0x02, 0x07, 0x16, 0xD0, 0x96, 0xF8, 0x32, 0x30, 0x2B, 0x49, 0x43, 0xF0, 0x01, 0x03, 0x86, 0xF8, 0x32, 0x30, 0x4A, 0x46, +0xD1, 0xF8, 0x20, 0x33, 0x40, 0x46, 0x31, 0x46, 0x98, 0x47, 0x96, 0xF8, 0x32, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x86, 0xF8, +0x32, 0x30, 0x71, 0xE5, 0x96, 0xF8, 0xDE, 0x20, 0xB4, 0xE6, 0x04, 0x23, 0x3A, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, +0x15, 0xFA, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, 0x87, 0x70, 0x0E, 0xF0, 0x3F, 0xFA, 0x61, 0xE5, 0x95, 0xF8, 0x32, 0x30, +0x13, 0xF0, 0x06, 0x04, 0x7F, 0xF4, 0x50, 0xAD, 0x02, 0x26, 0x95, 0xF8, 0x23, 0x00, 0x85, 0xF8, 0x32, 0x60, 0x47, 0xF0, +0x10, 0x01, 0x23, 0x46, 0x22, 0x46, 0xFB, 0xF7, 0x45, 0xFE, 0x85, 0xF8, 0x32, 0x40, 0x41, 0xE5, 0x95, 0xF8, 0x31, 0x30, +0x59, 0x07, 0x7F, 0xF5, 0x87, 0xAD, 0x0B, 0x4B, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x04, 0x30, 0x04, 0x23, 0x80, 0xF8, +0x32, 0x30, 0x00, 0x22, 0x0C, 0x21, 0x4A, 0x20, 0x0E, 0xF0, 0xE8, 0xF9, 0x01, 0x22, 0x04, 0x70, 0x80, 0xF8, 0x01, 0x90, +0x82, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0E, 0xF0, 0x0E, 0xBA, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x05, 0x8E, 0x87, 0xB0, 0xAD, 0xB1, 0x7A, 0x4B, 0xC6, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, +0x11, 0xDB, 0x77, 0x4A, 0x65, 0x6D, 0x12, 0x68, 0x12, 0x78, 0x92, 0x07, 0x03, 0xD5, 0x05, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, +0x77, 0xD0, 0x73, 0x4A, 0xAA, 0x43, 0x0E, 0xD0, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, +0xEB, 0xD1, 0x6F, 0x49, 0x6F, 0x48, 0x4F, 0xF4, 0xD4, 0x72, 0x35, 0x46, 0x10, 0xF0, 0x5A, 0xFA, 0xF1, 0xE7, 0x00, 0x2B, +0xC5, 0xF3, 0xCF, 0x30, 0xC5, 0xF3, 0xC9, 0x31, 0x68, 0xDB, 0x6A, 0x4A, 0x10, 0x39, 0xC9, 0xB2, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x00, 0x00, 0x28, 0x68, 0xD0, 0xD6, 0xF8, 0x08, 0xB0, 0x0D, 0x29, 0xBB, 0xF8, +0x00, 0x00, 0x00, 0x90, 0x69, 0xD9, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x22, 0x13, 0x8C, 0xFF, 0x2B, 0x67, 0xD0, +0x01, 0x92, 0x01, 0x9B, 0xDF, 0xF8, 0x88, 0x81, 0x93, 0xF8, 0x22, 0x90, 0xDF, 0xF8, 0x84, 0xA1, 0x02, 0x91, 0x4F, 0xF4, +0xA4, 0x67, 0x07, 0xFB, 0x09, 0x87, 0xDA, 0xF8, 0xB8, 0x32, 0x97, 0xF8, 0x63, 0x20, 0x58, 0x46, 0x98, 0x47, 0x97, 0xF8, +0x64, 0x30, 0x00, 0x2B, 0xBA, 0xD0, 0x00, 0x9B, 0x13, 0xF0, 0x04, 0x03, 0x03, 0x93, 0x05, 0xD1, 0x02, 0x99, 0x97, 0xF8, +0x63, 0x00, 0x01, 0x22, 0x0C, 0xF0, 0x96, 0xFB, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0x88, 0x98, 0xF8, 0x62, 0x30, +0x00, 0x2B, 0xA7, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0xFC, 0x07, 0x80, 0x2F, 0x4A, 0xD0, 0x50, 0x2F, 0x67, 0xD0, 0x03, 0x9B, +0x00, 0x2B, 0x9D, 0xD1, 0xDA, 0xF8, 0x44, 0x32, 0x29, 0x46, 0x58, 0x46, 0x42, 0x46, 0x98, 0x47, 0x98, 0xF8, 0xC0, 0x34, +0x00, 0x2B, 0x93, 0xD0, 0xD0, 0x2F, 0x91, 0xD1, 0xB1, 0x68, 0x63, 0x6B, 0x22, 0x8E, 0x40, 0x46, 0x0B, 0xF0, 0x5C, 0xFF, +0x8A, 0xE7, 0x37, 0x4A, 0x25, 0xF0, 0x40, 0x05, 0x45, 0xF4, 0x00, 0x55, 0xAA, 0x43, 0x65, 0x65, 0x82, 0xD1, 0x90, 0xE7, +0x10, 0xF4, 0x7C, 0x73, 0x93, 0xD1, 0x32, 0x49, 0x34, 0x48, 0x40, 0xF2, 0xE3, 0x12, 0x1D, 0x46, 0x10, 0xF0, 0xE0, 0xF9, +0x77, 0xE7, 0x25, 0xF0, 0x00, 0x75, 0x65, 0x65, 0x01, 0x25, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x48, +0x00, 0x69, 0xC3, 0xF8, 0x58, 0x02, 0x90, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0xFC, 0x03, 0x80, 0x2B, 0xED, 0xD1, 0xD3, 0x6A, +0x01, 0x93, 0x93, 0xF8, 0x23, 0x20, 0x25, 0xF0, 0xFF, 0x73, 0x10, 0x32, 0x23, 0xF4, 0xC0, 0x33, 0x43, 0xEA, 0xC2, 0x33, +0x63, 0x65, 0x86, 0xE7, 0x04, 0xF1, 0x14, 0x07, 0x01, 0x9A, 0xDA, 0xF8, 0x98, 0x51, 0x05, 0x93, 0x41, 0x46, 0x05, 0xAB, +0x38, 0x46, 0xA8, 0x47, 0xDA, 0xF8, 0x40, 0x32, 0x21, 0x8E, 0x05, 0x46, 0x42, 0x46, 0x05, 0x98, 0x98, 0x47, 0xDA, 0xF8, +0x4C, 0x34, 0x40, 0x46, 0x98, 0x47, 0x00, 0x2D, 0x3F, 0xF4, 0x41, 0xAF, 0xDA, 0xF8, 0xE4, 0x31, 0x3A, 0x46, 0x31, 0x46, +0x40, 0x46, 0x98, 0x47, 0x39, 0xE7, 0x14, 0x4B, 0x5A, 0x7F, 0x07, 0x2A, 0x7F, 0xF4, 0x34, 0xAF, 0x93, 0xF8, 0x24, 0x00, +0x00, 0x28, 0x7F, 0xF4, 0x2F, 0xAF, 0x10, 0x4C, 0x10, 0x4D, 0x58, 0x77, 0xD4, 0xE9, 0x00, 0x12, 0x22, 0xF4, 0x00, 0x72, +0x01, 0x20, 0x11, 0x43, 0x62, 0x60, 0x29, 0x60, 0x83, 0xF8, 0x24, 0x00, 0x05, 0x46, 0x20, 0xE7, 0x38, 0x36, 0x17, 0x00, +0x34, 0x36, 0x17, 0x00, 0x00, 0x20, 0x00, 0x02, 0x70, 0x79, 0x15, 0x00, 0x10, 0x96, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, +0x50, 0x90, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, +0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0xA3, 0x7A, 0xE2, 0x7A, 0x01, 0x33, 0xDB, 0xB2, +0x9A, 0x42, 0xA3, 0x72, 0x00, 0xD3, 0x10, 0xBD, 0x10, 0xF0, 0xF6, 0xF9, 0x00, 0x23, 0xA3, 0x72, 0x10, 0xBD, 0x00, 0xBF, +0x24, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x4C, 0xA3, 0x7A, 0xD3, 0xB9, 0xE3, 0x7A, 0xA3, 0x72, 0xEF, 0xF3, 0x10, 0x83, +0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4C, 0x11, 0x68, 0x23, 0x68, +0x48, 0x1C, 0x23, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, +0x03, 0xB1, 0x62, 0xB6, 0x10, 0xBD, 0x10, 0xF0, 0xCF, 0xF9, 0xE1, 0xE7, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, 0x08, 0xB5, 0x00, 0xF0, 0x29, 0xFC, 0xFF, 0xF7, 0x93, 0xFB, 0xBD, 0xE8, +0x08, 0x40, 0x1A, 0xF0, 0x9F, 0xB8, 0x00, 0xBF, 0x0A, 0x4A, 0x0B, 0x4B, 0x10, 0xB5, 0xD2, 0xE9, 0x20, 0x04, 0xD2, 0xE9, +0x22, 0x12, 0x04, 0x44, 0x0A, 0x44, 0xC3, 0xE9, 0x01, 0x40, 0xC3, 0xE9, 0x03, 0x12, 0x18, 0x60, 0x59, 0x61, 0xFF, 0xF7, +0x7D, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x1A, 0xF0, 0x89, 0xB8, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x68, 0x81, 0xDF, 0xF8, 0x68, 0x91, 0xDF, 0xF8, 0x68, 0xA1, 0xDF, 0xF8, 0x68, 0xB1, +0x4D, 0x4F, 0x87, 0xB0, 0x00, 0x25, 0x3C, 0xE0, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x4E, 0xD8, 0x20, 0x2D, +0x4C, 0xD0, 0x10, 0xF0, 0x8D, 0xF9, 0x00, 0x28, 0x61, 0xD0, 0x1A, 0xF0, 0x81, 0xFC, 0x00, 0x28, 0x5D, 0xD0, 0x62, 0x69, +0x5A, 0x45, 0x0E, 0xD0, 0x43, 0x4B, 0xB9, 0x68, 0x1E, 0x68, 0x53, 0xF8, 0x04, 0x0C, 0x7B, 0x68, 0xCD, 0xE9, 0x02, 0x60, +0xCD, 0xE9, 0x00, 0x31, 0x3F, 0x48, 0x3B, 0x68, 0x21, 0x46, 0x0F, 0xF0, 0x97, 0xFE, 0x20, 0x46, 0x3D, 0x4E, 0x01, 0xF0, +0x41, 0xF9, 0x00, 0x22, 0xD6, 0xF8, 0x94, 0x32, 0x8D, 0xF8, 0x17, 0x20, 0x0D, 0xF1, 0x17, 0x01, 0x20, 0x46, 0x98, 0x47, +0x58, 0xBB, 0x9D, 0xF8, 0x17, 0x30, 0x73, 0xB3, 0x36, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x31, 0xD0, 0x03, 0x2B, +0x02, 0xD1, 0xD6, 0xF8, 0x8C, 0x32, 0x98, 0x47, 0x01, 0x35, 0x01, 0xF0, 0x09, 0xF9, 0x4F, 0xF4, 0x80, 0x33, 0xC9, 0xF8, +0x00, 0x30, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, 0x18, 0xFC, 0x98, 0xF8, 0xB8, 0x30, 0x94, 0xB3, 0x00, 0x2B, +0xB2, 0xD1, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF5, 0x80, 0x1F, 0x01, 0xD8, 0x03, 0x2D, 0xB2, 0xDD, 0x4F, 0xF4, 0x80, 0x10, +0x0E, 0xF0, 0xE4, 0xFB, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, 0xC8, 0x32, 0x20, 0x46, 0x98, 0x47, 0x00, 0x28, +0xD0, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xC4, 0xF8, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0xCD, 0xD1, 0xD6, 0xF8, +0x90, 0x32, 0x98, 0x47, 0xCE, 0xE7, 0x1A, 0x4B, 0x01, 0x22, 0x83, 0xF8, 0x45, 0x20, 0x1A, 0xF0, 0x1B, 0xFC, 0xB0, 0xFA, +0x80, 0xF2, 0x17, 0x49, 0x52, 0x09, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x8D, 0xFE, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x1B, 0xB1, 0x13, 0x4D, 0x95, 0xF8, 0x21, 0x30, 0x3B, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x33, 0x13, 0x60, +0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD5, 0xE9, 0x05, 0x12, 0x28, 0x69, 0xF3, 0xF7, 0x5E, 0xFE, 0x6C, 0x61, 0xEC, 0x61, +0x2C, 0x61, 0xAC, 0x61, 0x85, 0xF8, 0x21, 0x40, 0xEB, 0xE7, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, +0x3C, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x28, 0x96, 0x15, 0x00, +0x30, 0x65, 0x17, 0x00, 0x80, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x7C, 0x80, 0x32, 0x40, 0x80, 0xB6, 0x17, 0x00, +0x0D, 0xF0, 0xAD, 0xBA, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x86, 0xBB, 0x2D, 0xE9, 0xF8, 0x43, 0x30, 0x4D, 0x2C, 0x68, +0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xA2, 0xFB, 0x00, 0x2C, 0x31, 0xD0, 0xDF, 0xF8, 0xC4, 0x90, 0x2C, 0x4F, 0x2E, 0x46, +0x4F, 0xF0, 0x01, 0x08, 0x23, 0x7C, 0xD9, 0x07, 0x02, 0xD4, 0x2B, 0x89, 0x01, 0x33, 0x2B, 0x81, 0x30, 0x46, 0x0E, 0xF0, +0x53, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0xC7, 0xF8, 0x00, 0x80, 0xD9, 0xF8, 0x00, 0x30, +0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, +0x08, 0xB1, 0x00, 0xF0, 0x77, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x33, 0xB1, 0x01, 0x3B, 0x3A, 0x68, 0xC9, 0xF8, 0x00, 0x30, +0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x00, 0x2C, 0xD3, 0xD1, 0xAA, 0x7A, 0xEB, 0x7A, 0x9A, 0x42, 0x20, 0xD0, +0x13, 0x4B, 0x14, 0x48, 0x1B, 0x69, 0x14, 0x4A, 0xC8, 0x33, 0x4F, 0xF4, 0x80, 0x71, 0x03, 0x60, 0x11, 0x60, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4A, 0x0E, 0x4C, 0x11, 0x68, +0x23, 0x68, 0x48, 0x1C, 0x43, 0xF4, 0x80, 0x73, 0x10, 0x60, 0x23, 0x60, 0x28, 0xB1, 0x05, 0x4B, 0x11, 0x60, 0x1B, 0x68, +0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x48, 0x01, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x8C, 0x80, 0x32, 0x40, +0x2D, 0xE9, 0xF8, 0x43, 0x27, 0x4D, 0x2C, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0x30, 0xFB, 0x9C, 0xB3, 0xDF, 0xF8, +0x9C, 0x80, 0xDF, 0xF8, 0x9C, 0x90, 0x00, 0x27, 0x2E, 0x46, 0x27, 0xE0, 0x01, 0x27, 0x30, 0x46, 0x0E, 0xF0, 0xE6, 0xFB, +0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, +0x62, 0x68, 0x01, 0x33, 0x00, 0x21, 0xC9, 0xF8, 0x00, 0x30, 0x21, 0x74, 0x0A, 0xB1, 0xA0, 0x68, 0x90, 0x47, 0xE0, 0x68, +0x08, 0xB1, 0x00, 0xF0, 0x09, 0xFB, 0xD9, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, +0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x2C, 0x68, 0x24, 0xB1, 0x23, 0x7C, 0xDA, 0x07, 0xD5, 0xD4, 0x00, 0x2F, +0xD2, 0xD0, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, 0x0E, 0xF0, +0xCD, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x94, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, 0xBD, 0xE8, +0xF8, 0x83, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x2B, 0x4E, 0x34, 0x68, 0x4F, 0xF4, 0x80, 0x00, 0x0E, 0xF0, 0xD4, 0xFA, +0x00, 0x2C, 0x3F, 0xD0, 0x28, 0x4D, 0x2B, 0x88, 0x00, 0x2B, 0x3B, 0xD0, 0xDF, 0xF8, 0xA4, 0x80, 0xDF, 0xF8, 0xA4, 0x90, +0x37, 0x46, 0x23, 0x7C, 0xD9, 0x07, 0x01, 0xD4, 0x2B, 0x88, 0x6B, 0xB3, 0x38, 0x46, 0x0E, 0xF0, 0x83, 0xFB, 0xEF, 0xF3, +0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, 0x22, 0x7C, +0x01, 0x33, 0xC9, 0xF8, 0x00, 0x30, 0xD3, 0x07, 0x02, 0xD4, 0x2B, 0x88, 0x01, 0x3B, 0x2B, 0x80, 0x63, 0x68, 0x00, 0x22, +0x22, 0x74, 0x0B, 0xB1, 0xA0, 0x68, 0x98, 0x47, 0xE0, 0x68, 0x08, 0xB1, 0x00, 0xF0, 0xA0, 0xFA, 0xD9, 0xF8, 0x00, 0x30, +0x3B, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0xC9, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x34, 0x68, +0x00, 0x2C, 0xCC, 0xD1, 0x0B, 0x4C, 0x94, 0xF8, 0x45, 0x30, 0x0B, 0xB9, 0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0x80, 0x10, +0x0E, 0xF0, 0x68, 0xFA, 0x07, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x2F, 0xFD, 0x00, 0x23, 0x84, 0xF8, 0x45, 0x30, +0xBD, 0xE8, 0xF8, 0x83, 0x24, 0x65, 0x17, 0x00, 0x54, 0x28, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x96, 0x15, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x4E, 0x35, 0x68, 0x95, 0xB1, 0x34, 0x89, 0x01, 0x34, +0xA4, 0xB2, 0x37, 0x46, 0x38, 0x46, 0x0E, 0xF0, 0x2D, 0xFB, 0x6B, 0x68, 0x0B, 0xB1, 0xA8, 0x68, 0x98, 0x47, 0x0F, 0xF0, +0x99, 0xFF, 0x35, 0x68, 0x34, 0x81, 0x01, 0x34, 0xA4, 0xB2, 0x00, 0x2D, 0xF0, 0xD1, 0xBD, 0xE8, 0xF8, 0x40, 0x00, 0xF0, +0xF5, 0xB9, 0x00, 0xBF, 0x24, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x44, 0x4F, 0x06, 0x68, 0x15, 0x88, 0xDF, 0xF8, +0x20, 0x91, 0xDF, 0xF8, 0x20, 0xA1, 0xDF, 0xF8, 0x20, 0xB1, 0x85, 0xB0, 0x4F, 0xF0, 0x00, 0x08, 0xCD, 0xE9, 0x02, 0x02, +0x87, 0xF8, 0x02, 0x80, 0xCD, 0xF8, 0x04, 0x80, 0x4A, 0xE0, 0xC4, 0x1A, 0x2C, 0x44, 0x0C, 0x44, 0x55, 0x1B, 0xA9, 0xB2, +0xA4, 0xB2, 0x00, 0x25, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4A, 0x01, 0x23, 0x13, 0x60, +0xBA, 0xF8, 0x00, 0x30, 0xDB, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x00, 0xC0, 0x00, 0x92, 0x02, 0xEB, 0xC3, 0x00, 0xB2, 0x68, +0x42, 0x60, 0x00, 0x9A, 0x0C, 0xF1, 0x01, 0x0E, 0xC9, 0xF8, 0x00, 0xE0, 0x42, 0xF8, 0x33, 0x10, 0xFA, 0x78, 0x01, 0x33, +0x01, 0x32, 0x88, 0x44, 0xAA, 0xF8, 0x00, 0x30, 0xFA, 0x70, 0x64, 0xBB, 0xC3, 0x78, 0xA7, 0xF8, 0x00, 0x80, 0x43, 0xF0, +0x04, 0x03, 0x01, 0x22, 0xC3, 0x70, 0xBA, 0x70, 0xB8, 0x60, 0xBE, 0xF1, 0x00, 0x0F, 0x38, 0xD0, 0x21, 0x4B, 0xC9, 0xF8, +0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x00, 0x2B, 0x2F, 0xD0, 0x62, 0xB6, 0x00, 0x2C, 0x2C, 0xD0, +0x1C, 0x4B, 0x1A, 0x68, 0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x1A, 0xDB, 0x01, 0x96, 0x21, 0x46, 0x1E, 0x46, +0xF3, 0x68, 0x30, 0x89, 0x01, 0x33, 0x9B, 0xB2, 0x1A, 0x1A, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xAB, 0xDA, 0x00, 0x24, +0xB0, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, 0xE7, 0xD0, 0x0F, 0x4B, 0xC9, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, +0xE0, 0xD1, 0x00, 0x2B, 0xDB, 0xD1, 0xDD, 0xE7, 0x00, 0x2B, 0xE2, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x00, 0x93, 0x4F, 0xF4, +0x17, 0x72, 0x0F, 0xF0, 0xA9, 0xFE, 0x00, 0x9B, 0xD9, 0xE7, 0x02, 0x9B, 0x01, 0x98, 0x1E, 0x60, 0x03, 0x9B, 0x1D, 0x80, +0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x54, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xB0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0x4F, 0xB2, 0xF8, 0x00, 0xA0, 0x06, 0x68, 0xDF, 0xF8, 0x0C, 0xB1, 0x87, 0xB0, 0x4F, 0xF0, +0x00, 0x08, 0xCD, 0xE9, 0x04, 0x02, 0x01, 0x22, 0x0B, 0x46, 0x87, 0xF8, 0x20, 0x20, 0xC1, 0x46, 0xCD, 0xF8, 0x0C, 0x80, +0x39, 0xE0, 0x05, 0x44, 0xAD, 0x1A, 0xA1, 0xEB, 0x0A, 0x03, 0xAD, 0xB2, 0x9B, 0xB2, 0x00, 0x2D, 0x02, 0x93, 0x08, 0xBF, +0x4F, 0xF0, 0x01, 0x09, 0xF2, 0xF7, 0x3C, 0xFC, 0x4F, 0xF0, 0x00, 0x0A, 0x02, 0x9B, 0x04, 0x46, 0x00, 0x28, 0x3A, 0xD0, +0x7A, 0x68, 0x02, 0xB9, 0x38, 0x60, 0xDB, 0xF8, 0x00, 0x00, 0xF9, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x19, 0x44, 0x01, 0x32, +0x00, 0x28, 0xF9, 0x60, 0x7A, 0x60, 0xB1, 0x68, 0x36, 0xDB, 0xCD, 0xF8, 0x00, 0x90, 0x00, 0x22, 0x20, 0x46, 0xF3, 0xF7, +0x6F, 0xFC, 0xB8, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0xC8, 0xF8, 0x04, 0x40, 0xBC, 0x60, 0x05, 0xB3, 0xDB, 0xF8, 0x00, 0x20, +0x73, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x2E, 0xDB, 0x03, 0x96, 0xA0, 0x46, 0x1E, 0x46, 0x2B, 0x46, 0xF2, 0x68, +0x35, 0x89, 0x01, 0x32, 0x92, 0xB2, 0x51, 0x1B, 0x89, 0xB2, 0x03, 0xEB, 0x0A, 0x00, 0x88, 0x42, 0xBB, 0xDA, 0x02, 0x93, +0xF2, 0xF7, 0x02, 0xFC, 0x00, 0x25, 0x02, 0x9B, 0x4F, 0xF0, 0x01, 0x09, 0x04, 0x46, 0x00, 0x28, 0xC4, 0xD1, 0x87, 0xF8, +0x20, 0x00, 0x04, 0x9B, 0x03, 0x98, 0x1E, 0x60, 0x05, 0x9B, 0xA3, 0xF8, 0x00, 0xA0, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x00, 0x29, 0xC6, 0xD1, 0x0B, 0x49, 0x0C, 0x48, 0x02, 0x93, 0x40, 0xF2, 0x9E, 0x22, 0x0F, 0xF0, 0x17, 0xFE, 0xB1, 0x68, +0x02, 0x9B, 0xBC, 0xE7, 0x00, 0x2B, 0xCE, 0xD1, 0x05, 0x49, 0x07, 0x48, 0x02, 0x93, 0x40, 0xF2, 0xB3, 0x22, 0x0F, 0xF0, +0x0B, 0xFE, 0x02, 0x9B, 0xC5, 0xE7, 0x00, 0xBF, 0x30, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xAC, 0x96, 0x15, 0x00, +0xA0, 0x96, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x91, 0x07, 0x68, 0xD9, 0xF8, +0x00, 0x40, 0x1D, 0x88, 0x94, 0xF8, 0x00, 0xC0, 0xDF, 0xF8, 0xFC, 0xA0, 0x85, 0xB0, 0xB1, 0xF5, 0xC8, 0x6F, 0x0E, 0x9E, +0x03, 0x93, 0x06, 0xEB, 0x46, 0x06, 0x28, 0xBF, 0x4F, 0xF4, 0xC8, 0x61, 0xBC, 0xF1, 0x03, 0x0F, 0x08, 0xBF, 0x34, 0x4B, +0x02, 0x90, 0x07, 0xEB, 0x06, 0x16, 0x06, 0xF1, 0x14, 0x06, 0x90, 0x46, 0x08, 0xBF, 0x1E, 0x60, 0x00, 0x20, 0x2C, 0xE0, +0xAE, 0xEB, 0x03, 0x04, 0x2C, 0x44, 0x0C, 0x44, 0x52, 0x1B, 0xA4, 0xB2, 0x91, 0xB2, 0x00, 0x25, 0xBC, 0xF1, 0x03, 0x0F, +0x0D, 0xD1, 0xB1, 0xF5, 0x00, 0x6F, 0x0B, 0x46, 0x28, 0xBF, 0x4F, 0xF4, 0x00, 0x63, 0x43, 0xF0, 0x23, 0x43, 0x4F, 0xF0, +0x04, 0x12, 0xB3, 0x60, 0xF1, 0x60, 0x31, 0x61, 0x72, 0x61, 0x88, 0x44, 0xA4, 0xB3, 0xDA, 0xF8, 0x00, 0x20, 0x7B, 0x68, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xF1, 0x14, 0x0B, 0x1C, 0xDB, 0xBC, 0xF1, 0x03, 0x0F, 0x01, 0xD1, 0xC6, 0xF8, +0x20, 0xB0, 0x38, 0x46, 0x5E, 0x46, 0x1F, 0x46, 0x21, 0x46, 0xD7, 0xE9, 0x02, 0x43, 0x01, 0x33, 0x1F, 0xFA, 0x84, 0xFE, +0x9B, 0xB2, 0xA3, 0xEB, 0x0E, 0x02, 0x05, 0xEB, 0x04, 0x0B, 0x92, 0xB2, 0x4C, 0x19, 0x94, 0x42, 0xC6, 0xF8, 0x04, 0x80, +0xC6, 0xF8, 0x00, 0xB0, 0xC0, 0xDA, 0x00, 0x24, 0xC6, 0xE7, 0x00, 0x2B, 0xE0, 0xD1, 0x4F, 0xF4, 0x4A, 0x72, 0x0D, 0x49, +0x0D, 0x48, 0x01, 0x93, 0x0F, 0xF0, 0x90, 0xFD, 0xD9, 0xF8, 0x00, 0x20, 0x01, 0x9B, 0x92, 0xF8, 0x00, 0xC0, 0xD3, 0xE7, +0xBC, 0xF1, 0x03, 0x0F, 0x02, 0xD1, 0x05, 0x4B, 0x34, 0x62, 0x5E, 0x60, 0x02, 0x9B, 0x1F, 0x60, 0x03, 0x9B, 0x1D, 0x80, +0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0xBF, 0x60, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, +0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x61, 0xB3, 0x0B, 0x8A, 0xDA, 0x07, 0x12, 0xD4, 0x16, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x20, 0x02, 0xE0, 0x0B, 0x8A, 0xDB, 0x07, 0x0A, 0xD4, 0x00, 0x2A, 0x49, 0x68, 0xF9, 0xDA, 0x00, 0x29, +0xF7, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF2, 0xE6, 0x32, 0x0F, 0xF0, 0x29, 0xBD, 0xCB, 0x68, 0x23, 0xF0, 0x03, 0x03, +0x04, 0x33, 0x0E, 0x49, 0x4A, 0x68, 0x9A, 0x42, 0x8A, 0x68, 0x08, 0xBF, 0x0B, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, +0x00, 0x40, 0x83, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x8B, 0x60, 0x70, 0x47, +0x00, 0xF1, 0xA0, 0x03, 0xE9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, +0xEC, 0x34, 0x17, 0x00, 0x18, 0x4B, 0x19, 0x4A, 0x18, 0x68, 0x19, 0x49, 0xDF, 0xF8, 0x7C, 0xC0, 0xF0, 0xB5, 0xD0, 0xE9, +0x00, 0x34, 0x17, 0x4D, 0x13, 0x60, 0x1C, 0x44, 0x2B, 0x60, 0x25, 0x1F, 0x0D, 0x60, 0x15, 0x4E, 0x15, 0x4D, 0x11, 0x68, +0x31, 0x60, 0x29, 0x60, 0xD0, 0xE9, 0x02, 0x10, 0xDF, 0xF8, 0x5C, 0xE0, 0x12, 0x4F, 0x54, 0x60, 0x08, 0x44, 0x69, 0x60, +0x11, 0x4C, 0x93, 0x60, 0x11, 0x4E, 0x03, 0x1F, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, 0x00, 0x10, 0x39, 0x60, 0x6E, 0x61, +0x23, 0x68, 0x10, 0x61, 0x03, 0xF4, 0x00, 0x23, 0x43, 0xF4, 0xF0, 0x23, 0x43, 0xF0, 0x25, 0x03, 0xD1, 0x60, 0x51, 0x61, +0x23, 0x60, 0xF0, 0xBD, 0x30, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0xCC, 0x81, 0x32, 0x40, 0xC8, 0x81, 0x32, 0x40, +0xD0, 0x81, 0x32, 0x40, 0xD4, 0x81, 0x32, 0x40, 0xE4, 0x81, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, 0x05, 0x12, 0x00, 0x0C, +0xE0, 0x81, 0x32, 0x40, 0xDC, 0x81, 0x32, 0x40, 0x10, 0xB4, 0x0A, 0x4C, 0x0A, 0x49, 0x22, 0x68, 0x83, 0x02, 0x03, 0xF4, +0x80, 0x63, 0x22, 0xF4, 0x80, 0x62, 0x13, 0x43, 0x23, 0x60, 0x0B, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0xC0, 0x04, 0x00, 0xF4, +0x00, 0x20, 0x23, 0xF4, 0x00, 0x23, 0x18, 0x43, 0x08, 0x60, 0x70, 0x47, 0x24, 0x03, 0x32, 0x40, 0x0C, 0x01, 0x32, 0x40, +0x90, 0xF8, 0x9C, 0x20, 0xD0, 0xF8, 0x98, 0x30, 0x6A, 0xB9, 0x0E, 0x4A, 0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, +0x02, 0xF0, 0x00, 0x42, 0x0A, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, 0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x08, 0x4A, +0x12, 0x68, 0x22, 0xF0, 0x00, 0x41, 0x8B, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x04, 0x49, 0x38, 0xBF, 0x02, 0xF1, 0x00, 0x42, +0x13, 0x43, 0x0B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0xD0, 0x81, 0x32, 0x40, 0xE0, 0x81, 0x32, 0x40, 0x10, 0xB5, 0x03, 0x8E, +0x82, 0xB0, 0xC3, 0xB1, 0x2D, 0x4B, 0xC4, 0x69, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x38, 0xDB, 0xA3, 0x68, +0x42, 0x6D, 0x1B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0x24, 0x2B, 0x43, 0xD0, 0x94, 0x2B, 0x03, 0xD1, 0x42, 0xF2, 0x02, 0x03, +0x93, 0x43, 0x36, 0xD0, 0xE3, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x04, 0x33, 0x07, 0xE0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x18, 0xDB, 0x00, 0xF1, 0xA0, 0x03, 0x1E, 0x49, 0x0A, 0x69, 0x9A, 0x42, 0x4A, 0x69, 0x08, 0xBF, +0xCB, 0x68, 0xC0, 0xF8, 0x98, 0x30, 0x22, 0xF0, 0x00, 0x44, 0xA3, 0x42, 0x02, 0xF0, 0x00, 0x42, 0x38, 0xBF, 0x02, 0xF1, +0x00, 0x42, 0x13, 0x43, 0x4B, 0x61, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x9E, 0xBF, 0xC3, 0x69, 0x00, 0x2B, +0xE3, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x4F, 0xF4, 0xD7, 0x72, 0x05, 0xE0, 0x00, 0x2C, 0xC4, 0xD1, 0x0E, 0x49, 0x10, 0x48, +0x4F, 0xF4, 0xC2, 0x72, 0x02, 0xB0, 0xBD, 0xE8, 0x10, 0x40, 0x0F, 0xF0, 0x2F, 0xBC, 0x0D, 0x4B, 0x01, 0x90, 0xD3, 0xF8, +0x74, 0x33, 0x98, 0x47, 0x01, 0x98, 0xC1, 0xE7, 0x93, 0x04, 0xBF, 0xD5, 0x08, 0x4B, 0x01, 0x90, 0xD3, 0xF8, 0xFC, 0x33, +0x98, 0x47, 0x01, 0x98, 0xB8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xC8, 0x96, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x29, 0x46, 0xD0, 0x2D, 0xE9, 0xF8, 0x4F, +0x07, 0x46, 0xDF, 0xF8, 0x8C, 0xA0, 0xDF, 0xF8, 0x8C, 0xB0, 0x08, 0x46, 0x1F, 0x49, 0x99, 0x46, 0x4F, 0xF0, 0x00, 0x08, +0xD7, 0xE9, 0x02, 0x45, 0x01, 0x35, 0xAB, 0xB2, 0xA6, 0xB2, 0x9D, 0x1B, 0xAD, 0xB2, 0xAD, 0x1A, 0xA8, 0x42, 0x23, 0xDB, +0xF6, 0x1A, 0x16, 0x44, 0x06, 0x44, 0xB6, 0xB2, 0xA8, 0xB2, 0xC5, 0x1C, 0x4F, 0xEA, 0x98, 0x03, 0xAD, 0x08, 0x14, 0x44, +0x09, 0xEB, 0x83, 0x03, 0x08, 0xD0, 0x1A, 0x46, 0x03, 0xEB, 0x85, 0x05, 0xE3, 0x1A, 0xD4, 0x58, 0x42, 0xF8, 0x04, 0x4B, +0xAA, 0x42, 0xFA, 0xD1, 0xBE, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x7F, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x80, 0x44, 0x00, 0x2B, +0x1F, 0xFA, 0x88, 0xF8, 0x04, 0xDB, 0x30, 0x46, 0x00, 0x22, 0xD1, 0xE7, 0x00, 0x26, 0xDE, 0xE7, 0x00, 0x2F, 0xF8, 0xD1, +0x40, 0xF2, 0x2D, 0x42, 0x58, 0x46, 0x0F, 0xF0, 0xFF, 0xFB, 0x02, 0x49, 0xF1, 0xE7, 0xBD, 0xE8, 0xF8, 0x8F, 0x70, 0x47, +0x70, 0x79, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xEC, 0x96, 0x15, 0x00, 0x38, 0xB5, 0x13, 0x4C, 0x94, 0xF8, 0x21, 0x30, +0xA3, 0xB9, 0x20, 0x61, 0x11, 0x48, 0xE3, 0x69, 0xE2, 0x68, 0x61, 0x69, 0x65, 0x68, 0x90, 0xF8, 0xB9, 0x00, 0x13, 0x44, +0x29, 0x44, 0xA2, 0x68, 0x61, 0x61, 0x01, 0x25, 0xB3, 0xEB, 0x40, 0x2F, 0xE3, 0x61, 0x84, 0xF8, 0x21, 0x50, 0xA2, 0x61, +0x03, 0xD2, 0x38, 0xBD, 0xA3, 0x69, 0x58, 0x60, 0xE8, 0xE7, 0x20, 0x69, 0xF3, 0xF7, 0x90, 0xF9, 0x00, 0x23, 0xC4, 0xE9, +0x04, 0x33, 0xC4, 0xE9, 0x06, 0x33, 0x84, 0xF8, 0x21, 0x30, 0x38, 0xBD, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0xAB, 0x4E, 0xD0, 0xF8, 0x1C, 0xC0, 0x35, 0x68, 0x86, 0xB0, 0x04, 0x46, 0xCD, 0xF8, 0x14, 0xC0, +0xAD, 0xF8, 0x0E, 0x30, 0x2B, 0x78, 0x02, 0x2B, 0x91, 0x46, 0x00, 0xF0, 0xAD, 0x80, 0x01, 0x2B, 0xDF, 0xF8, 0xC4, 0x82, +0x22, 0xD0, 0x01, 0x20, 0x00, 0x23, 0xD8, 0xF8, 0xAC, 0x52, 0x4A, 0x46, 0xCD, 0xE9, 0x00, 0x30, 0x0D, 0xF1, 0x0E, 0x03, +0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0x1F, 0xD0, 0x01, 0x2B, 0x59, 0xD0, 0xD8, 0xF8, +0x98, 0x32, 0x05, 0x99, 0x20, 0x46, 0x2A, 0x46, 0x98, 0x47, 0x0E, 0x9B, 0x63, 0x60, 0x0F, 0x9B, 0x95, 0x48, 0xA3, 0x60, +0x21, 0x46, 0x0D, 0xF0, 0x3F, 0xFF, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xD8, 0xF8, 0xB0, 0x52, 0x00, 0x23, 0x00, 0x93, +0x0D, 0xF1, 0x0E, 0x02, 0x05, 0xA8, 0xA8, 0x47, 0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x05, 0x46, 0xDF, 0xD1, 0xDF, 0xF8, +0x64, 0x92, 0x99, 0xF8, 0x02, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xB9, 0xF8, 0x00, 0x30, 0x7A, 0x68, 0x3A, 0x33, 0xBB, 0x60, +0xD3, 0x78, 0x6F, 0xF3, 0x87, 0x13, 0xD3, 0x70, 0x99, 0xF8, 0x03, 0x30, 0xBB, 0x73, 0x00, 0x23, 0x3B, 0x60, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x7F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x20, 0xA2, 0x7E, 0x48, +0xDA, 0xF8, 0x00, 0x30, 0x39, 0x46, 0x01, 0x33, 0xCA, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x08, 0xFF, 0xD8, 0xF8, 0x44, 0x34, +0x98, 0x47, 0xDA, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x75, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCA, 0xF8, 0x00, 0x30, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0xC9, 0xE9, 0x00, 0x33, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0xA5, 0xD1, 0xF2, 0xF7, +0x15, 0xF9, 0x07, 0x46, 0x00, 0x28, 0x00, 0xF0, 0x92, 0x80, 0x6D, 0x4E, 0x96, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x00, 0xF0, +0x96, 0x80, 0x73, 0x68, 0x81, 0x68, 0x32, 0x68, 0x03, 0xF1, 0x01, 0x0C, 0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, +0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, 0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xC6, 0xF8, +0x04, 0xC0, 0xF3, 0xF7, 0x43, 0xF9, 0x60, 0x4A, 0xF3, 0x68, 0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xF3, 0x60, 0x38, 0x46, +0x00, 0x2A, 0x40, 0xF0, 0xA7, 0x80, 0xD6, 0xE9, 0x01, 0x12, 0xF3, 0xF7, 0xD3, 0xF8, 0x5A, 0x49, 0x0A, 0x78, 0x00, 0x23, +0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0x73, 0x60, 0xF3, 0x60, 0x33, 0x60, 0xB3, 0x60, 0x86, 0xF8, 0x20, 0x30, 0x68, 0xE7, +0x54, 0x4D, 0x42, 0xF2, 0x24, 0x03, 0xEA, 0x58, 0x00, 0x2A, 0x68, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x4A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0xDF, 0xF8, 0x44, 0x81, 0xA8, 0x5A, 0xD8, 0xF8, +0x00, 0x30, 0x02, 0x91, 0x01, 0x33, 0xB0, 0xF5, 0xC3, 0x7F, 0xC8, 0xF8, 0x00, 0x30, 0x48, 0x48, 0xDF, 0xF8, 0x3C, 0xA1, +0x84, 0xBF, 0x00, 0x23, 0xAB, 0x52, 0x0D, 0xF0, 0xD7, 0xFE, 0x45, 0x4A, 0x02, 0x99, 0xD2, 0xF8, 0x00, 0xC0, 0x42, 0xF2, +0x34, 0x0E, 0x07, 0x46, 0x35, 0xF8, 0x0E, 0x30, 0xBB, 0x81, 0x0C, 0xEB, 0xC3, 0x00, 0x04, 0xF1, 0x30, 0x02, 0x42, 0x60, +0x4C, 0xF8, 0x33, 0xA0, 0xDF, 0xF8, 0x08, 0xC1, 0x78, 0x60, 0x95, 0xF8, 0x02, 0xAC, 0x9C, 0xF8, 0x03, 0x00, 0xD8, 0xF8, +0x00, 0x20, 0x01, 0x33, 0x0A, 0xF1, 0x01, 0x0A, 0x01, 0x30, 0x25, 0xF8, 0x0E, 0x30, 0x85, 0xF8, 0x02, 0xAC, 0x8C, 0xF8, +0x03, 0x00, 0x3A, 0xB1, 0x2B, 0x4B, 0x01, 0x3A, 0x1B, 0x68, 0xC8, 0xF8, 0x00, 0x20, 0x0A, 0xB9, 0x00, 0x2B, 0x48, 0xD1, +0x33, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x7F, 0xF4, 0xFE, 0xAE, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x23, 0xD8, 0xF8, 0xB4, 0x52, +0x21, 0xE7, 0x23, 0x7C, 0x29, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0F, 0xF0, 0x2E, 0xF8, 0x20, 0x4B, 0x83, 0xF8, +0x20, 0x70, 0x26, 0x49, 0x4F, 0xF4, 0x80, 0x60, 0x0F, 0xF0, 0x76, 0xF8, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, +0xF9, 0xE6, 0x03, 0x7C, 0xDF, 0xF8, 0x8C, 0x80, 0x43, 0xF0, 0x01, 0x03, 0x03, 0x74, 0xD8, 0xF8, 0x98, 0x32, 0x61, 0x46, +0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x19, 0x4C, +0xD8, 0xF8, 0x44, 0x24, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x0A, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x11, 0x48, 0xF0, 0xF7, 0x31, 0xFE, 0xE0, 0xE6, +0xFF, 0xF7, 0x7E, 0xFE, 0x59, 0xE7, 0x62, 0xB6, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0xA8, 0x56, 0x17, 0x00, 0x30, 0x65, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x9C, 0x4E, 0x17, 0x00, +0x7C, 0x36, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x20, 0x97, 0x15, 0x00, +0x6C, 0x28, 0x17, 0x00, 0xF8, 0x96, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x54, 0x65, 0x17, 0x00, 0x3C, 0x00, 0x00, 0xC0, +0x2D, 0xE9, 0xF0, 0x4F, 0xAE, 0x4B, 0xDF, 0xF8, 0x00, 0xA3, 0xC1, 0x69, 0x9A, 0xF8, 0x32, 0x20, 0x1B, 0x68, 0x87, 0xB0, +0x04, 0x46, 0x05, 0x91, 0xAD, 0xF8, 0x12, 0x20, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0x3F, 0x81, 0x02, 0x2B, 0x77, 0xD0, +0xA6, 0x4A, 0x27, 0x8E, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xBF, 0x80, 0x01, 0x2B, 0xA3, 0x4E, +0x4F, 0xF0, 0x00, 0x03, 0x00, 0xF0, 0x3A, 0x81, 0xCD, 0xE9, 0x00, 0x33, 0x39, 0x46, 0xD6, 0xF8, 0xAC, 0x52, 0x0D, 0xF1, +0x12, 0x03, 0x5A, 0x46, 0x05, 0xA8, 0xA8, 0x47, 0x07, 0xEB, 0x0B, 0x01, 0xCA, 0xF8, 0x1C, 0x10, 0x07, 0x46, 0x00, 0x21, +0x04, 0xF1, 0x58, 0x00, 0xEB, 0xF7, 0x7E, 0xFD, 0x94, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xF0, 0xB8, 0x80, +0x01, 0x2B, 0x00, 0xF0, 0x49, 0x81, 0x02, 0x2B, 0x41, 0xD1, 0xDF, 0xF8, 0x88, 0xA2, 0x9A, 0xF8, 0x02, 0x30, 0x00, 0x2B, +0x3B, 0xD0, 0xBA, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x04, 0x20, 0x3A, 0x33, 0xC8, 0xF8, 0x08, 0x30, 0xD3, 0x78, 0x6F, 0xF3, +0x87, 0x13, 0xD3, 0x70, 0x9A, 0xF8, 0x03, 0x30, 0x88, 0xF8, 0x0E, 0x30, 0x00, 0x23, 0xC8, 0xF8, 0x00, 0x30, 0xEF, 0xF3, +0x10, 0x83, 0xDD, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x83, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0x14, 0xB2, 0x82, 0x48, +0xDB, 0xF8, 0x00, 0x30, 0x41, 0x46, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0x0D, 0xF0, 0x8C, 0xFD, 0xD6, 0xF8, 0x44, 0x34, +0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x79, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x72, 0x4B, 0x1A, 0x68, 0x00, 0x23, 0xCA, 0xE9, 0x00, 0x33, 0x13, 0x78, 0x03, 0x2B, 0x00, 0xF0, +0x9E, 0x81, 0xD6, 0xF8, 0x98, 0x32, 0x05, 0x99, 0x3A, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x6E, 0x4E, 0x42, 0xF2, 0x24, 0x03, 0xF2, 0x58, 0x00, 0x2A, 0x00, 0xF0, 0x60, 0x81, 0xEF, 0xF3, 0x10, 0x83, 0xDF, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x66, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x42, 0xF2, 0x34, 0x02, 0x67, 0x4F, 0xB1, 0x5A, 0x3B, 0x68, +0x66, 0x48, 0x01, 0x33, 0xB1, 0xF5, 0xC3, 0x7F, 0x3B, 0x60, 0x84, 0xBF, 0x00, 0x23, 0xB3, 0x52, 0x0D, 0xF0, 0x92, 0xFD, +0x62, 0x4A, 0x42, 0xF2, 0x34, 0x0E, 0xD2, 0xF8, 0x00, 0xC0, 0x36, 0xF8, 0x0E, 0x30, 0x83, 0x81, 0x0C, 0xEB, 0xC3, 0x01, +0x04, 0xF1, 0x30, 0x02, 0x4A, 0x60, 0x5D, 0x4A, 0x4C, 0xF8, 0x33, 0x20, 0xDF, 0xF8, 0x94, 0xC1, 0x41, 0x60, 0x96, 0xF8, +0x02, 0x1C, 0x9C, 0xF8, 0x03, 0x20, 0x80, 0x46, 0x38, 0x68, 0x01, 0x33, 0x01, 0x31, 0x01, 0x32, 0x26, 0xF8, 0x0E, 0x30, +0x86, 0xF8, 0x02, 0x1C, 0x8C, 0xF8, 0x03, 0x20, 0x30, 0xB1, 0x4C, 0x4B, 0x01, 0x38, 0x1B, 0x68, 0x38, 0x60, 0x08, 0xB9, +0x03, 0xB1, 0x62, 0xB6, 0x46, 0x4B, 0x27, 0x8E, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0xDA, 0x00, 0x2F, +0x00, 0xF0, 0x07, 0x81, 0xB7, 0xF5, 0x40, 0x5F, 0x00, 0xF2, 0x0A, 0x81, 0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, +0x7F, 0xF4, 0x34, 0xAF, 0x3D, 0x4E, 0x39, 0x46, 0xD6, 0xF8, 0xB4, 0x72, 0x00, 0x23, 0x00, 0x93, 0x0D, 0xF1, 0x12, 0x02, +0x05, 0xA8, 0xB8, 0x47, 0x07, 0x46, 0x3C, 0xE7, 0x3F, 0x4A, 0x40, 0x48, 0x53, 0x68, 0x60, 0x66, 0x04, 0xF1, 0x30, 0x00, +0xA0, 0x66, 0x04, 0xF1, 0x68, 0x00, 0x3D, 0x49, 0xC4, 0xF8, 0x6C, 0x90, 0x18, 0x62, 0x3A, 0x23, 0x21, 0x67, 0x63, 0x67, +0x4F, 0xF0, 0x04, 0x11, 0xA3, 0x67, 0x00, 0x23, 0x03, 0x90, 0xE1, 0x67, 0xC4, 0xF8, 0x88, 0x30, 0x10, 0x68, 0x03, 0x99, +0x05, 0x22, 0xF0, 0xF7, 0xC5, 0xF9, 0x34, 0x4A, 0x13, 0x68, 0x18, 0x05, 0xFC, 0xD5, 0x13, 0x68, 0x59, 0x03, 0x03, 0xD5, +0x11, 0x68, 0x41, 0xF0, 0x80, 0x61, 0x11, 0x60, 0x1A, 0x05, 0x21, 0xD5, 0xEF, 0xF3, 0x05, 0x80, 0x2D, 0x49, 0x41, 0xF2, +0x4C, 0x12, 0x8B, 0x58, 0x43, 0xF0, 0x00, 0x63, 0x8B, 0x50, 0x00, 0x28, 0x40, 0xF0, 0xF3, 0x80, 0xEF, 0xF3, 0x10, 0x83, +0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1C, 0x4B, 0x25, 0x48, 0x19, 0x68, 0x00, 0x25, +0x4A, 0x1C, 0x1A, 0x60, 0x45, 0x61, 0x2A, 0xB1, 0x15, 0x4A, 0x19, 0x60, 0x13, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, +0x1F, 0x4D, 0x2B, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x1E, 0x4B, 0x18, 0x68, 0xA9, 0xF1, 0x14, 0x01, 0x00, 0xF5, 0x0B, 0x70, +0x0D, 0xF0, 0xAC, 0xFC, 0x01, 0x23, 0x2B, 0x60, 0xEF, 0xF7, 0x2E, 0xFD, 0x31, 0xE7, 0x0A, 0xF1, 0x40, 0x00, 0x0F, 0xF0, +0x67, 0xF9, 0x05, 0x4B, 0x1B, 0x68, 0x81, 0x46, 0x1B, 0x78, 0x00, 0xF1, 0x3C, 0x0B, 0xB5, 0xE6, 0x39, 0x46, 0xD6, 0xF8, +0xB0, 0x72, 0x8C, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0xA8, 0x56, 0x17, 0x00, 0x7C, 0x36, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA0, 0x56, 0x17, 0x00, 0x54, 0x60, 0x17, 0x00, +0x3C, 0x00, 0x00, 0xC0, 0x60, 0x65, 0x17, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, 0x00, 0xA3, 0x4C, 0x11, 0x07, 0x40, +0x00, 0x00, 0x07, 0x40, 0x48, 0x35, 0x17, 0x00, 0x54, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xB0, 0xDE, 0x17, 0x00, +0x54, 0x65, 0x17, 0x00, 0xF1, 0xF7, 0x92, 0xFE, 0x83, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0xDF, 0xF8, 0x38, 0xA1, 0x9A, 0xF8, +0x20, 0x30, 0x00, 0x2B, 0x41, 0xD0, 0xDA, 0xF8, 0x04, 0x30, 0x81, 0x68, 0xDA, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x01, 0x0C, +0x4F, 0xEA, 0x0C, 0x63, 0x21, 0xF0, 0xFE, 0x41, 0x03, 0xF0, 0xFE, 0x43, 0x0B, 0x43, 0x00, 0x21, 0x83, 0x60, 0x00, 0x91, +0x3A, 0x23, 0x04, 0xF1, 0x30, 0x01, 0xCA, 0xF8, 0x04, 0xC0, 0xF2, 0xF7, 0xBF, 0xFE, 0x3C, 0x4A, 0xDA, 0xF8, 0x0C, 0x30, +0x92, 0xF8, 0xB8, 0x20, 0x3A, 0x33, 0xCA, 0xF8, 0x0C, 0x30, 0x58, 0x46, 0x00, 0x2A, 0x63, 0xD1, 0xDA, 0xE9, 0x01, 0x12, +0xF2, 0xF7, 0x4E, 0xFE, 0x35, 0x49, 0x0A, 0x78, 0x00, 0x23, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x70, 0xCA, 0xF8, 0x04, 0x30, +0xCA, 0xF8, 0x0C, 0x30, 0xCA, 0xF8, 0x00, 0x30, 0xCA, 0xF8, 0x08, 0x30, 0x8A, 0xF8, 0x20, 0x30, 0x12, 0xE0, 0x23, 0x7C, +0x2D, 0x48, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x0E, 0xF0, 0x00, 0xFE, 0x2B, 0x4B, 0x83, 0xF8, 0x20, 0xB0, 0x2B, 0x49, +0x4F, 0xF4, 0x80, 0x60, 0x0E, 0xF0, 0x48, 0xFE, 0x23, 0x7C, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0x27, 0x4B, 0x1B, 0x68, +0x1B, 0x78, 0x02, 0x2B, 0x3F, 0xF4, 0x5D, 0xAE, 0x9A, 0xE6, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, 0x21, 0x52, 0x0F, 0xF0, +0x2F, 0xF8, 0x9C, 0xE6, 0x21, 0x49, 0x23, 0x48, 0x40, 0xF2, 0x23, 0x52, 0x0F, 0xF0, 0x28, 0xF8, 0x95, 0xE6, 0x23, 0x7C, +0x20, 0x4E, 0x05, 0x99, 0x43, 0xF0, 0x01, 0x03, 0x23, 0x74, 0xD6, 0xF8, 0x98, 0x32, 0x20, 0x46, 0x98, 0x47, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1A, 0x4C, 0xD6, 0xF8, 0x44, 0x24, +0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x90, 0x47, 0x23, 0x68, 0x01, 0x46, 0x33, 0xB1, 0x14, 0x4A, 0x01, 0x3B, 0x12, 0x68, +0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x12, 0x48, 0xF0, 0xF7, 0xEF, 0xFB, 0x6E, 0xE6, 0xFF, 0xF7, 0x3C, 0xFC, +0x9C, 0xE7, 0x10, 0x4B, 0x00, 0x22, 0x5A, 0x61, 0x1E, 0xE7, 0x0F, 0x4A, 0xE8, 0xE6, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, +0x9C, 0x4E, 0x17, 0x00, 0x0C, 0x97, 0x15, 0x00, 0x30, 0x65, 0x17, 0x00, 0x20, 0x97, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x34, 0x97, 0x15, 0x00, 0x44, 0x97, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0xFC, 0x96, 0x15, 0x00, 0x48, 0x35, 0x17, 0x00, 0x60, 0x65, 0x17, 0x00, 0x0D, 0x4B, 0xC1, 0x69, +0xD3, 0xF8, 0x98, 0x32, 0x10, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x98, 0x47, 0x0A, 0x48, 0x03, 0x68, 0x53, 0xB1, 0x23, 0x7C, +0x43, 0xF0, 0x01, 0x03, 0x00, 0x22, 0x23, 0x74, 0x62, 0x60, 0x21, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x0D, 0xF0, 0xA0, 0xBB, +0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x19, 0xBB, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x24, 0x65, 0x17, 0x00, +0x0C, 0x4A, 0x0D, 0x49, 0x93, 0x68, 0x09, 0x68, 0x8B, 0x42, 0x11, 0xD0, 0x51, 0x68, 0x23, 0xF0, 0x00, 0x40, 0x09, 0x1A, +0x9F, 0x29, 0x0C, 0xD8, 0x11, 0x68, 0x03, 0xF0, 0x00, 0x43, 0x88, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x0B, 0x43, +0x93, 0x60, 0x23, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xEC, 0x34, 0x17, 0x00, 0xD4, 0x81, 0x32, 0x40, +0x1E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x04, 0x46, 0x21, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, +0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x63, 0x6D, 0x03, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x25, 0xD0, 0x23, 0x8E, 0x53, 0xB1, +0x62, 0x6D, 0x02, 0xF0, 0x7C, 0x02, 0x08, 0x2A, 0x0D, 0xD0, 0x0C, 0x2A, 0x19, 0xD0, 0x04, 0x2A, 0x09, 0xD0, 0x04, 0x3B, +0x23, 0x86, 0x00, 0x23, 0x10, 0x4A, 0x23, 0x74, 0x84, 0xF8, 0x9C, 0x30, 0xE4, 0x60, 0x62, 0x60, 0x10, 0xBD, 0x08, 0x3B, +0x23, 0x86, 0xF4, 0xE7, 0x0C, 0x4B, 0x42, 0x69, 0x9A, 0x42, 0xD9, 0xD0, 0x0B, 0x49, 0x0C, 0x48, 0x40, 0xF2, 0x14, 0x62, +0x0E, 0xF0, 0x98, 0xFF, 0xD2, 0xE7, 0x0C, 0x3B, 0x23, 0x86, 0xE6, 0xE7, 0x23, 0x8E, 0x04, 0x3B, 0x9B, 0xB2, 0x23, 0x86, +0xD5, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x3D, 0x48, 0x13, 0x00, 0x0D, 0xF0, 0xAD, 0xBA, +0x70, 0x79, 0x15, 0x00, 0x64, 0x97, 0x15, 0x00, 0x06, 0x4B, 0x07, 0x4A, 0x4F, 0xF4, 0x80, 0x31, 0x19, 0x60, 0x13, 0x68, +0x23, 0xF4, 0x80, 0x33, 0x13, 0x60, 0x4F, 0xF4, 0x80, 0x10, 0x0D, 0xF0, 0x7F, 0xBA, 0x00, 0xBF, 0x7C, 0x80, 0x32, 0x40, +0x80, 0x80, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4D, 0x22, 0x4E, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x84, 0xB0, +0x38, 0xD0, 0xDF, 0xF8, 0x88, 0x80, 0x1F, 0x4F, 0xDF, 0xF8, 0x84, 0x90, 0x20, 0xE0, 0x6B, 0x69, 0x1D, 0x48, 0x23, 0xF0, +0x00, 0x44, 0x21, 0x46, 0x62, 0x69, 0xBA, 0x42, 0x0A, 0xD0, 0xD6, 0xF8, 0x00, 0xE0, 0xD9, 0xF8, 0x00, 0xA0, 0xCD, 0xE9, +0x00, 0xC3, 0xCD, 0xE9, 0x02, 0xEA, 0xEB, 0x68, 0x0E, 0xF0, 0xD4, 0xFC, 0x20, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0x01, 0x23, +0x84, 0xF8, 0x9C, 0x30, 0xD8, 0xF8, 0xC0, 0x32, 0x20, 0x46, 0x98, 0x47, 0x6B, 0x69, 0x32, 0x68, 0x93, 0x42, 0x11, 0xD0, +0xD5, 0xF8, 0x10, 0xC0, 0x23, 0xF0, 0x00, 0x41, 0xAC, 0xEB, 0x01, 0x02, 0x9F, 0x2A, 0x03, 0xF0, 0x00, 0x43, 0xD4, 0xD8, +0xEA, 0x68, 0x91, 0x42, 0x88, 0xBF, 0x03, 0xF1, 0x00, 0x43, 0x13, 0x43, 0x6B, 0x61, 0xCD, 0xE7, 0x04, 0xB0, 0xBD, 0xE8, +0xF0, 0x87, 0x00, 0xBF, 0xEC, 0x34, 0x17, 0x00, 0xE4, 0x81, 0x32, 0x40, 0x0D, 0xF0, 0xAD, 0xBA, 0x90, 0x97, 0x15, 0x00, +0x88, 0x1A, 0x17, 0x00, 0xE0, 0x81, 0x32, 0x40, 0x00, 0xB5, 0x10, 0x4A, 0x10, 0x4B, 0x12, 0x68, 0x89, 0xB0, 0x08, 0x33, +0x03, 0x92, 0x53, 0xF8, 0x08, 0x2C, 0x04, 0x92, 0x53, 0xF8, 0x04, 0x2C, 0x05, 0x92, 0x1B, 0x68, 0x06, 0x93, 0x01, 0xA8, +0x00, 0x21, 0xEB, 0xF7, 0x73, 0xFA, 0x03, 0x9B, 0x03, 0xF0, 0x0F, 0x03, 0x02, 0x2B, 0x02, 0xD0, 0x09, 0xB0, 0x5D, 0xF8, +0x04, 0xFB, 0x01, 0xA8, 0x0E, 0xF0, 0x8C, 0xFF, 0x09, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xBF, 0xB0, 0x10, 0x34, 0x40, +0xB4, 0x10, 0x34, 0x40, 0x38, 0xB5, 0xD0, 0xF8, 0xFC, 0x31, 0x04, 0x46, 0x00, 0xF5, 0xFE, 0x75, 0x4B, 0xB1, 0x28, 0x46, +0x0D, 0xF0, 0xDE, 0xFA, 0x01, 0x21, 0xFA, 0xF7, 0x2B, 0xF9, 0xD4, 0xF8, 0xFC, 0x31, 0x00, 0x2B, 0xF5, 0xD1, 0x4F, 0xF4, +0x1E, 0x72, 0x00, 0x21, 0x20, 0x46, 0xEA, 0xF7, 0xF9, 0xF9, 0x23, 0x46, 0x04, 0xF1, 0x48, 0x01, 0x21, 0x22, 0x83, 0xF8, +0xA4, 0x21, 0x83, 0xF8, 0xA5, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xF8, 0xD1, 0xFF, 0x23, 0x84, 0xF8, 0x22, 0x30, 0x38, 0xBD, +0x2D, 0xE9, 0xF0, 0x43, 0x49, 0x48, 0x4A, 0x4F, 0x83, 0xB0, 0x81, 0x46, 0x0D, 0xF0, 0x72, 0xFA, 0x07, 0xF5, 0x0C, 0x75, +0x00, 0x26, 0x40, 0xF2, 0x16, 0x38, 0xA5, 0xF5, 0x0C, 0x71, 0x08, 0x46, 0x01, 0x91, 0xFF, 0xF7, 0xC7, 0xFF, 0x01, 0x99, +0x48, 0x46, 0x0D, 0xF0, 0x67, 0xFA, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x5E, 0xFA, 0x04, 0xF1, 0x28, 0x00, +0x08, 0x34, 0x0D, 0xF0, 0x59, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xE4, 0xD1, +0x38, 0x4D, 0x40, 0xF2, 0x52, 0x48, 0xA5, 0xF1, 0x28, 0x04, 0x20, 0x46, 0x0D, 0xF0, 0x4A, 0xFA, 0x04, 0xF1, 0x28, 0x00, +0x08, 0x34, 0x0D, 0xF0, 0x45, 0xFA, 0xAC, 0x42, 0xF5, 0xD1, 0x4F, 0x36, 0x46, 0x45, 0x04, 0xF5, 0x1E, 0x75, 0xEE, 0xD1, +0x2F, 0x48, 0x30, 0x4D, 0x30, 0x4C, 0x00, 0xF1, 0x30, 0x06, 0xFF, 0xF7, 0x97, 0xFF, 0x41, 0xF6, 0xF8, 0x12, 0x4F, 0xF0, +0x00, 0x08, 0x41, 0xF6, 0x64, 0x11, 0x41, 0xF6, 0xD0, 0x03, 0xBD, 0x50, 0x06, 0xF5, 0x12, 0x70, 0x86, 0xF8, 0x00, 0x80, +0x4F, 0xF0, 0x20, 0x62, 0x7C, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x84, 0xFF, 0x41, 0xF6, 0x58, 0x30, 0x41, 0xF6, 0x70, 0x41, +0x07, 0xF8, 0x00, 0x80, 0x41, 0xF6, 0xDC, 0x32, 0x05, 0xF1, 0x40, 0x00, 0x78, 0x50, 0x41, 0xF6, 0x48, 0x33, 0x04, 0xF5, +0xA4, 0x61, 0xB9, 0x50, 0x06, 0xF5, 0x98, 0x60, 0x1C, 0x4A, 0xFA, 0x50, 0xFF, 0xF7, 0x6E, 0xFF, 0x41, 0xF6, 0xD0, 0x52, +0x41, 0xF6, 0xE8, 0x61, 0x41, 0xF6, 0x54, 0x63, 0x18, 0x48, 0x07, 0xF8, 0x02, 0x80, 0xC6, 0xF8, 0xE0, 0x04, 0x04, 0xF5, +0x24, 0x62, 0x06, 0xF5, 0xE7, 0x60, 0x05, 0xF1, 0x80, 0x06, 0x7E, 0x50, 0xFA, 0x50, 0xFF, 0xF7, 0x59, 0xFF, 0x42, 0xF2, +0x60, 0x16, 0x11, 0x4A, 0x42, 0xF2, 0xCC, 0x00, 0x42, 0xF2, 0x48, 0x01, 0x42, 0xF2, 0x38, 0x03, 0xC0, 0x35, 0x04, 0xF5, +0x76, 0x64, 0xBD, 0x51, 0x3C, 0x50, 0x07, 0xF8, 0x01, 0x80, 0xFA, 0x50, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xBF, +0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x48, 0x80, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, 0x04, 0x38, 0x18, 0x00, +0xC0, 0x8C, 0x17, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x02, 0x0C, 0x00, 0x00, 0x03, 0x0D, 0x2D, 0xE9, 0xF0, 0x41, +0x05, 0x46, 0x79, 0x48, 0x95, 0xF8, 0x19, 0x80, 0x0E, 0x46, 0x0D, 0xF0, 0x11, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0xE1, 0x80, +0x6B, 0x7F, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x80, 0x73, 0x4F, 0x05, 0xF1, 0x12, 0x02, 0x11, 0x68, 0x2B, 0x68, +0x92, 0x88, 0x62, 0x85, 0xC4, 0xF8, 0x26, 0x10, 0x63, 0x60, 0x28, 0x7E, 0x6E, 0x4B, 0x6F, 0x4A, 0x6F, 0x49, 0x10, 0x28, +0x38, 0xBF, 0x10, 0x20, 0x20, 0x77, 0x28, 0x8A, 0xA0, 0x82, 0xA8, 0x68, 0x20, 0x61, 0x68, 0x68, 0xE0, 0x60, 0xE8, 0x68, +0xA0, 0x61, 0xE0, 0x1B, 0xC0, 0x10, 0x03, 0xFB, 0x00, 0xF3, 0xDB, 0xB2, 0x68, 0x7E, 0x84, 0xF8, 0x22, 0x00, 0x33, 0x70, +0x4F, 0xF4, 0x80, 0x70, 0x84, 0xF8, 0x23, 0x30, 0x0E, 0xF0, 0xC6, 0xFB, 0x62, 0x48, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, +0x08, 0x03, 0x4F, 0xF4, 0xC8, 0x31, 0x93, 0xF8, 0xC0, 0x24, 0xA1, 0x60, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x32, +0x83, 0xF8, 0xC2, 0x24, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, 0xE8, 0x11, 0x04, 0xF5, 0xF4, 0x72, 0x23, 0x46, 0x04, 0xF5, +0xFD, 0x75, 0x22, 0xF8, 0x02, 0x1F, 0xAA, 0x42, 0xFB, 0xD1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF8, 0x00, 0xEB, +0x08, 0x05, 0x00, 0x22, 0x31, 0x78, 0x84, 0xF8, 0x30, 0x20, 0xD5, 0xF8, 0xB0, 0x54, 0x4F, 0x4A, 0x02, 0xEB, 0x81, 0x12, +0x29, 0x07, 0xC4, 0xF8, 0x48, 0x21, 0x4D, 0x49, 0x56, 0xBF, 0x08, 0xF5, 0x95, 0x62, 0x04, 0xF1, 0xB0, 0x02, 0x12, 0x18, +0xC4, 0xF8, 0xB4, 0x20, 0x0A, 0x69, 0xA2, 0xF5, 0x74, 0x22, 0xA2, 0xF5, 0x10, 0x72, 0x04, 0xF1, 0x48, 0x01, 0xC3, 0xF8, +0xA0, 0x21, 0x08, 0x33, 0x8B, 0x42, 0xFA, 0xD1, 0xEA, 0x06, 0x03, 0xD5, 0x63, 0x68, 0x43, 0xF0, 0x08, 0x03, 0x63, 0x60, +0x08, 0xF1, 0xE4, 0x08, 0x40, 0x44, 0x21, 0x46, 0x0D, 0xF0, 0x4C, 0xF9, 0x3D, 0x4B, 0xC4, 0xF8, 0x04, 0x32, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x3A, 0x4B, 0xE0, 0x6A, 0x1A, 0x68, +0x01, 0x25, 0x51, 0x19, 0x19, 0x60, 0x84, 0xF8, 0x25, 0x50, 0x08, 0xB1, 0x80, 0xF8, 0x25, 0x50, 0x21, 0xB1, 0x33, 0x49, +0x1A, 0x60, 0x0B, 0x68, 0x00, 0x2A, 0x42, 0xD0, 0xF6, 0xB2, 0x0D, 0x2E, 0x07, 0xD8, 0x4F, 0xF4, 0x1E, 0x73, 0x2C, 0x4A, +0x06, 0xFB, 0x03, 0x76, 0x13, 0x69, 0xC6, 0xF8, 0x58, 0x32, 0x00, 0x20, 0x84, 0xF8, 0x5C, 0x02, 0xBD, 0xE8, 0xF0, 0x81, +0x1F, 0x48, 0x0D, 0xF0, 0x61, 0xF9, 0x00, 0x28, 0x34, 0xD0, 0x2A, 0x46, 0xE0, 0x62, 0xC4, 0x62, 0xA9, 0x7F, 0x52, 0xF8, +0x12, 0x3F, 0x95, 0xF8, 0x1D, 0xC0, 0xC0, 0xF8, 0x26, 0x30, 0x01, 0x23, 0x8B, 0x40, 0x91, 0x88, 0x41, 0x85, 0x01, 0x3B, +0x41, 0x8D, 0x16, 0x4F, 0x1B, 0x02, 0x1B, 0xB2, 0x21, 0xEA, 0x03, 0x01, 0x09, 0xB2, 0x41, 0x85, 0xB5, 0xF8, 0x16, 0xE0, +0xAE, 0xEB, 0x0C, 0x2C, 0x03, 0xEA, 0x0C, 0x03, 0xA0, 0xEB, 0x07, 0x0E, 0xDF, 0xF8, 0x3C, 0xC0, 0x4F, 0xEA, 0xEE, 0x0E, +0x0B, 0x43, 0x0C, 0xFB, 0x0E, 0xF1, 0x4F, 0xF0, 0xFF, 0x0C, 0x43, 0x85, 0x80, 0xF8, 0x23, 0x10, 0xA0, 0xF8, 0x20, 0xC0, +0x2A, 0xE7, 0x00, 0x2B, 0xBA, 0xD0, 0x62, 0xB6, 0xB8, 0xE7, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x48, 0x21, 0x46, +0x0D, 0xF0, 0xE2, 0xF8, 0x01, 0x20, 0xBD, 0xE7, 0xF8, 0x87, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xAF, 0x16, 0x37, 0x61, +0xEC, 0x97, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x04, 0x39, 0x18, 0x00, 0x00, 0x10, 0x50, 0x40, +0x0F, 0xCC, 0xFF, 0xFF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x33, 0x4F, 0xDF, 0xF8, +0xE4, 0x80, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x74, 0x4F, 0xF4, 0xA4, 0x63, 0x94, 0xF8, 0x22, 0x60, 0x03, 0xFB, +0x06, 0x83, 0x05, 0x46, 0x93, 0xF8, 0xC0, 0x24, 0x22, 0xB1, 0x93, 0xF8, 0xC2, 0x24, 0x01, 0x3A, 0x83, 0xF8, 0xC2, 0x24, +0x29, 0x4A, 0x2A, 0x49, 0x2B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0E, 0xF0, 0xD5, 0xFA, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, +0x06, 0x80, 0xE4, 0x30, 0x21, 0x46, 0x0D, 0xF0, 0xF3, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x21, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x21, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0x11, 0x68, 0xD8, 0x6A, +0x4E, 0x1C, 0x4F, 0xF0, 0x00, 0x0C, 0x16, 0x60, 0x83, 0xF8, 0x25, 0xC0, 0xD8, 0xB1, 0x80, 0xF8, 0x25, 0xC0, 0x96, 0xB9, +0xFF, 0xF7, 0xE4, 0xFD, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x75, 0x16, 0x48, 0xE9, 0x6A, 0x0D, 0xF0, 0x80, 0xF8, +0x20, 0x46, 0xFF, 0xF7, 0xD9, 0xFD, 0x21, 0x46, 0x12, 0x48, 0xBD, 0xE8, 0xF0, 0x41, 0x0D, 0xF0, 0x77, 0xB8, 0x0E, 0x48, +0x11, 0x60, 0x02, 0x68, 0x41, 0xB1, 0xD8, 0x6A, 0xE6, 0xE7, 0x00, 0x2E, 0xEE, 0xD0, 0x0A, 0x4B, 0x11, 0x60, 0x1A, 0x68, +0x00, 0x29, 0xE9, 0xD1, 0x02, 0xB1, 0x62, 0xB6, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x73, 0xD8, 0x6A, 0x00, 0x28, +0xE0, 0xD0, 0xD5, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x00, 0x98, 0x15, 0x00, 0xDC, 0x97, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0xF8, 0x87, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x78, 0xDF, 0xF8, +0x14, 0x81, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0xF6, 0x08, 0xEB, 0x06, 0x07, 0x38, 0x36, 0x87, 0xF8, 0x9A, 0x10, +0x90, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x98, 0x30, 0x03, 0x78, 0x87, 0xF8, 0x99, 0x30, 0x46, 0x44, 0x05, 0x46, 0x48, 0x22, +0x30, 0x46, 0x00, 0x21, 0x97, 0xF8, 0x22, 0x90, 0xE9, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x98, 0x30, 0x04, 0x2B, 0x55, 0xD8, +0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x3F, 0x54, 0x03, 0x27, 0x00, 0x21, 0xF0, 0x29, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x04, 0x83, 0x03, 0xF1, 0x80, 0x02, 0x20, 0xF0, 0x7F, 0x40, 0xC3, 0xF8, 0x80, 0x00, 0x00, 0x23, 0x53, 0x60, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0x01, 0x22, 0xD5, 0xE9, 0x02, 0x40, 0x29, 0x69, 0x83, 0xF8, 0x9B, 0x20, 0x6A, 0x69, +0xC3, 0xF8, 0xB0, 0x60, 0xC3, 0xE9, 0x27, 0x40, 0xC3, 0xE9, 0x29, 0x12, 0x2A, 0x79, 0x83, 0xF8, 0xAC, 0x20, 0xBD, 0xE8, +0xF8, 0x83, 0x20, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x39, 0x19, 0xA3, 0xD3, 0xE9, 0x00, 0x23, 0x99, 0xF8, +0x62, 0x00, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x04, 0x81, 0x02, 0x28, 0xC1, 0xE9, 0x20, 0x23, 0xD7, 0xD1, 0x15, 0xA3, +0xD3, 0xE9, 0x00, 0x23, 0xC1, 0xE9, 0x20, 0x23, 0xD1, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, 0xAA, 0x69, +0xC3, 0xF8, 0x88, 0x20, 0xEA, 0x69, 0xC3, 0xF8, 0x8C, 0x20, 0x2A, 0x6A, 0xC3, 0xF8, 0x90, 0x20, 0x00, 0x20, 0x6A, 0x6A, +0xC3, 0xF8, 0x94, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xBC, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x83, +0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x20, 0x01, 0xB3, 0xE7, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x36, 0x5C, 0x36, 0x5C, +0x36, 0x5C, 0x36, 0x5C, 0x37, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x00, 0x23, 0x01, 0x22, 0x80, 0xF8, 0x30, 0x20, 0x80, 0xF8, 0x9B, 0x30, 0xC0, 0xF8, 0xB0, 0x30, 0x70, 0x47, 0x00, 0xBF, +0x2D, 0xE9, 0xF0, 0x47, 0xD1, 0xF8, 0xFC, 0xA1, 0x82, 0xB0, 0xBA, 0xF1, 0x00, 0x0F, 0x32, 0xD0, 0x00, 0x24, 0xDF, 0xF8, +0x6C, 0x80, 0x0D, 0x46, 0x06, 0x46, 0x91, 0x46, 0x27, 0x46, 0x10, 0xE0, 0x80, 0xF8, 0x5D, 0x70, 0xD8, 0xF8, 0x98, 0x33, +0xC1, 0x7E, 0x01, 0x34, 0x98, 0x47, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, 0x4C, 0x45, 0x1F, 0xD0, 0xD5, 0xF8, 0xFC, 0xA1, +0xBA, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x30, 0x46, 0x01, 0x97, 0xF8, 0xF7, 0x6B, 0xFA, 0x03, 0x46, 0x50, 0x46, 0x9B, 0xB1, +0x15, 0xF0, 0x34, 0xFC, 0x03, 0x46, 0x01, 0xAA, 0x29, 0x46, 0x30, 0x46, 0x63, 0xB1, 0xD8, 0xF8, 0x10, 0x30, 0x98, 0x47, +0x01, 0x9B, 0x3B, 0xB9, 0x00, 0x28, 0xD9, 0xD1, 0x05, 0xF5, 0xFE, 0x70, 0x0C, 0xF0, 0xC2, 0xFF, 0xD4, 0xE7, 0x54, 0x46, +0x20, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x9B, 0x68, 0x93, 0xF8, 0x62, 0x20, +0x7A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x62, 0xB1, 0x93, 0xF8, 0x6D, 0x20, 0x4A, 0xB1, 0x93, 0xF8, 0x6E, 0x20, 0x08, 0x2A, +0x05, 0xD8, 0x01, 0x23, 0x93, 0x40, 0x01, 0x3B, 0x02, 0x4A, 0x1B, 0x02, 0x13, 0x60, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, +0x2C, 0x00, 0x32, 0x40, 0x10, 0xB5, 0x90, 0xF8, 0xC0, 0x34, 0x04, 0x46, 0x00, 0x2B, 0x2D, 0xD1, 0x23, 0x6C, 0x1B, 0xB1, +0x1B, 0x4B, 0x20, 0x46, 0x1B, 0x6B, 0x98, 0x47, 0x63, 0x68, 0xD8, 0x07, 0x1A, 0xD5, 0x19, 0x4A, 0x11, 0x68, 0x89, 0x01, +0x17, 0xD5, 0x23, 0xF0, 0x01, 0x03, 0x63, 0x60, 0x16, 0x4A, 0x41, 0xF2, 0x14, 0x33, 0xD3, 0x5C, 0x01, 0x2B, 0x41, 0xF2, +0x13, 0x33, 0x8C, 0xBF, 0x01, 0x21, 0x00, 0x21, 0xD1, 0x54, 0x12, 0x4B, 0x93, 0xF8, 0xB6, 0x30, 0x23, 0xB1, 0x11, 0x4B, +0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x0C, 0xD0, 0x10, 0xBD, 0x12, 0x68, 0x92, 0x01, 0xFB, 0xD4, 0x0D, 0x4A, 0x92, 0xF8, +0x24, 0x20, 0x00, 0x2A, 0xF6, 0xD0, 0xDE, 0xE7, 0x0A, 0xF0, 0x34, 0xF8, 0xCE, 0xE7, 0xF8, 0xF7, 0x1D, 0xFD, 0x09, 0x4A, +0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, +0x00, 0x40, 0x1E, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, +0x19, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x18, 0x22, 0x80, 0x46, 0x00, 0x21, 0xE9, 0xF7, 0x72, 0xFE, 0x40, 0x46, 0x0C, 0xF0, +0xFF, 0xFE, 0x08, 0xF1, 0x08, 0x00, 0x14, 0x4C, 0x14, 0x4F, 0x0C, 0xF0, 0xF9, 0xFE, 0x04, 0xF5, 0xA4, 0x56, 0x45, 0x46, +0x4F, 0xF4, 0xA4, 0x62, 0x00, 0x21, 0x20, 0x46, 0xE9, 0xF7, 0x60, 0xFE, 0x7F, 0x23, 0xD7, 0xF8, 0x50, 0x24, 0x24, 0x63, +0x05, 0x21, 0x84, 0xF8, 0x62, 0x10, 0x84, 0xF8, 0x65, 0x30, 0x84, 0xF8, 0x66, 0x30, 0xE2, 0x62, 0x21, 0x46, 0x28, 0x46, +0x04, 0xF5, 0xA4, 0x64, 0x0C, 0xF0, 0xE2, 0xFE, 0xB4, 0x42, 0xE5, 0xD1, 0xFF, 0x23, 0x88, 0xF8, 0x10, 0x30, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x06, 0x4B, +0x9C, 0x68, 0x3C, 0xB1, 0x05, 0x4D, 0xD5, 0xF8, 0x5C, 0x34, 0x20, 0x46, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xF8, 0xD1, +0x38, 0xBD, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAC, 0x4D, 0x8D, 0xB0, +0x2C, 0x68, 0x05, 0x90, 0x88, 0x46, 0x17, 0x46, 0x04, 0x93, 0x00, 0x2C, 0x00, 0xF0, 0xA4, 0x80, 0x00, 0x2A, 0x40, 0xF0, +0x9E, 0x80, 0xAC, 0x68, 0x00, 0x2C, 0x00, 0xF0, 0x42, 0x81, 0x05, 0x9B, 0xA4, 0x48, 0x1A, 0x68, 0x9B, 0x88, 0x06, 0x92, +0x4F, 0xF0, 0x00, 0x09, 0x07, 0x93, 0xCB, 0x46, 0xBA, 0x46, 0xE7, 0x6D, 0xB4, 0xF8, 0x60, 0x60, 0x94, 0xF8, 0xC0, 0x34, +0x39, 0x46, 0x32, 0x46, 0x0E, 0xF0, 0x76, 0xF8, 0x94, 0xF8, 0xC0, 0x34, 0x9A, 0x48, 0x1B, 0xB9, 0x8B, 0xEA, 0x07, 0x0B, +0x89, 0xEA, 0x06, 0x09, 0x24, 0x68, 0x00, 0x2C, 0xEB, 0xD1, 0x57, 0x46, 0x00, 0x2F, 0x00, 0xF0, 0x99, 0x80, 0x95, 0x4B, +0x95, 0x48, 0x49, 0xF4, 0x40, 0x74, 0xDD, 0xE9, 0x06, 0x12, 0x1C, 0x60, 0xC0, 0xF8, 0x00, 0xB0, 0x5B, 0x46, 0xCD, 0xE9, +0x00, 0x97, 0x91, 0x48, 0x0E, 0xF0, 0x58, 0xF8, 0x8B, 0x48, 0x0C, 0xF0, 0xBF, 0xFE, 0x05, 0x99, 0x8E, 0x4A, 0x80, 0xF8, +0x62, 0x80, 0x04, 0x46, 0x8D, 0x4B, 0x82, 0x1A, 0x08, 0x68, 0xE0, 0x65, 0x52, 0x11, 0x89, 0x88, 0xA4, 0xF8, 0x60, 0x10, +0x03, 0xFB, 0x02, 0xF2, 0xD3, 0xB2, 0x40, 0xF6, 0x47, 0x21, 0x40, 0xF6, 0x43, 0x22, 0xA1, 0x60, 0xE2, 0x60, 0x86, 0x49, +0x86, 0x4A, 0x21, 0x61, 0x62, 0x61, 0x40, 0xF2, 0xFF, 0x31, 0x00, 0x22, 0x84, 0xF8, 0xC0, 0x74, 0xA4, 0xF8, 0xBE, 0x14, +0x84, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x4C, 0x30, 0x22, 0x64, 0x84, 0xF8, 0x84, 0x20, 0x17, 0xB1, 0xEA, 0x7C, 0x01, 0x32, +0xEA, 0x74, 0xB8, 0xF1, 0x02, 0x0F, 0x00, 0xF0, 0x89, 0x80, 0xB8, 0xF1, 0x04, 0x0F, 0x00, 0xF0, 0xC3, 0x80, 0xB8, 0xF1, +0x00, 0x0F, 0x00, 0xF0, 0x9C, 0x80, 0x6B, 0x7C, 0xAA, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x78, 0xDD, 0x74, 0x48, 0x75, 0x4E, +0xD0, 0xE9, 0x00, 0x12, 0x42, 0xF4, 0x80, 0x72, 0x11, 0x43, 0x42, 0x60, 0x31, 0x60, 0x01, 0x2B, 0x4D, 0xD0, 0x00, 0x2F, +0x52, 0xD1, 0x04, 0x9A, 0x94, 0xF8, 0x63, 0x30, 0x6E, 0x48, 0x13, 0x70, 0x21, 0x46, 0x0C, 0xF0, 0x29, 0xFE, 0x04, 0xF5, +0x99, 0x66, 0x04, 0xF5, 0x9E, 0x69, 0x30, 0x46, 0x0C, 0xF0, 0x1E, 0xFE, 0x06, 0xF1, 0x28, 0x00, 0x08, 0x36, 0x0C, 0xF0, +0x19, 0xFE, 0x4E, 0x45, 0xF5, 0xD1, 0x04, 0xF5, 0xA3, 0x60, 0x0C, 0xF0, 0x13, 0xFE, 0x00, 0x24, 0x03, 0xE0, 0x63, 0x4B, +0x1B, 0x78, 0x23, 0xB3, 0x01, 0x24, 0xAA, 0x7C, 0x6B, 0x7C, 0x61, 0x49, 0x13, 0x44, 0x00, 0x20, 0x01, 0x2B, 0x08, 0x60, +0x04, 0xDC, 0xFF, 0xF7, 0x91, 0xFE, 0xAA, 0x7C, 0x6B, 0x7C, 0x13, 0x44, 0x04, 0x99, 0x09, 0x78, 0x4F, 0xF4, 0x80, 0x70, +0xCD, 0xE9, 0x02, 0x71, 0xCD, 0xE9, 0x00, 0x28, 0x58, 0x49, 0x59, 0x4A, 0x0E, 0xF0, 0x22, 0xF8, 0x20, 0x46, 0x0D, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x9B, 0x8B, 0xEA, 0x03, 0x0B, 0x07, 0x9B, 0x89, 0xEA, 0x03, 0x09, 0x5F, 0xE7, 0xAC, 0x68, +0x00, 0x2C, 0x7C, 0xD0, 0xEB, 0x7C, 0x02, 0x2B, 0x7F, 0xF4, 0x37, 0xAF, 0xD2, 0xE7, 0x4F, 0x4A, 0x13, 0x68, 0x43, 0xF0, +0x01, 0x03, 0x13, 0x60, 0x00, 0x2F, 0xAC, 0xD0, 0xB8, 0xF1, 0x00, 0x01, 0x18, 0xBF, 0x01, 0x21, 0x94, 0xF8, 0x63, 0x00, +0x09, 0xF0, 0x22, 0xFD, 0x48, 0x4B, 0x84, 0xF8, 0xC1, 0x04, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x9C, 0xDA, +0xFF, 0x28, 0x9A, 0xD1, 0x44, 0x49, 0x45, 0x48, 0x40, 0xF2, 0x0B, 0x22, 0x0E, 0xF0, 0x1A, 0xFA, 0x93, 0xE7, 0x00, 0x2A, +0x8D, 0xD0, 0x83, 0xE7, 0xAA, 0x7C, 0x00, 0x2A, 0x00, 0xF0, 0xA8, 0x80, 0x39, 0x46, 0x3F, 0x48, 0x0A, 0x33, 0x4F, 0xF4, +0x1E, 0x76, 0x06, 0xFB, 0x03, 0x03, 0x01, 0x32, 0x01, 0x20, 0xAA, 0x74, 0x83, 0xF8, 0x25, 0x00, 0x11, 0xB1, 0x3A, 0x4B, +0xC4, 0xE9, 0x07, 0x34, 0x39, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x80, 0x31, 0x98, 0x47, 0x6B, 0x7C, 0x64, 0xE7, 0x36, 0x4B, +0x36, 0x49, 0xD3, 0xF8, 0xCC, 0x31, 0xE3, 0x61, 0xFF, 0x23, 0x84, 0xF8, 0x6C, 0x30, 0x34, 0x4A, 0x6B, 0x7C, 0x24, 0x62, +0xA4, 0xF8, 0x8A, 0x80, 0xC4, 0xF8, 0xB8, 0x40, 0xC4, 0xF8, 0xB4, 0x10, 0x01, 0x33, 0x92, 0xF8, 0x04, 0x21, 0xDB, 0xB2, +0x6B, 0x74, 0x00, 0x2A, 0x3F, 0xF4, 0x4C, 0xAF, 0x2C, 0x4A, 0xC4, 0xF8, 0xA4, 0x40, 0xC4, 0xE9, 0x24, 0x88, 0xC4, 0xF8, +0x98, 0x80, 0xC4, 0xF8, 0xA0, 0x20, 0x41, 0xE7, 0x2A, 0x7C, 0xFF, 0x2A, 0x17, 0xD1, 0xAA, 0x68, 0x2B, 0x74, 0x00, 0x2A, +0x4C, 0xD0, 0x14, 0x49, 0x24, 0x4B, 0x4E, 0x68, 0x12, 0x6C, 0x13, 0x48, 0x0B, 0x60, 0x33, 0x43, 0x03, 0x60, 0x00, 0x2A, +0x3F, 0xF4, 0x2F, 0xAF, 0x1B, 0x4B, 0x10, 0x7E, 0x1B, 0x6D, 0x98, 0x47, 0x29, 0xE7, 0x05, 0x98, 0x01, 0xF0, 0x4E, 0xFE, +0xEA, 0xE6, 0x01, 0x24, 0x6E, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x14, 0x98, 0x15, 0x00, 0x1C, 0x00, 0x32, 0x40, +0x18, 0x00, 0x32, 0x40, 0x2C, 0x98, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x19, 0x9C, 0x8F, 0xC1, 0x32, 0xE4, 0x05, 0x00, +0x22, 0xF3, 0x02, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x08, 0x88, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, +0x2C, 0x00, 0x32, 0x40, 0x74, 0x98, 0x15, 0x00, 0xC8, 0x98, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x50, 0x98, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0xB1, 0x7F, 0x13, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xD5, 0x65, 0x12, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x81, 0x66, 0x12, 0x00, 0xDC, 0xFF, 0xFF, 0x7F, 0x10, 0x4E, 0x11, 0x4A, +0x09, 0x92, 0x40, 0xF6, 0x85, 0x12, 0xD6, 0xF8, 0xE8, 0x30, 0x0A, 0x92, 0x98, 0x47, 0x73, 0x6C, 0x0D, 0xF1, 0x23, 0x01, +0x09, 0xA8, 0x98, 0x47, 0x00, 0x28, 0xB6, 0xD1, 0x63, 0x68, 0x32, 0x6D, 0x9D, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x80, 0x03, +0x63, 0x60, 0x90, 0x47, 0x6B, 0x7C, 0xD3, 0xE6, 0x01, 0xF0, 0x32, 0xFE, 0xAA, 0x7C, 0x94, 0xF8, 0x63, 0x30, 0x94, 0xF8, +0xC0, 0x14, 0x50, 0xE7, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x00, 0x85, 0x09, 0x2D, 0xE9, 0xF0, 0x4F, 0x02, 0x46, 0x6A, 0x4D, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xF3, 0x8B, 0xB0, 0xEF, 0x18, 0x04, 0x90, 0x39, 0x46, 0x66, 0x48, 0x06, 0x93, +0x0C, 0xF0, 0x4A, 0xFD, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xDD, 0x80, 0x04, 0x2B, 0x00, 0xF0, 0x98, 0x80, +0xDF, 0xF8, 0x98, 0xA1, 0x60, 0x4C, 0x00, 0x2B, 0x00, 0xF0, 0x89, 0x80, 0x9A, 0xF8, 0x12, 0x30, 0x9A, 0xF8, 0x11, 0x20, +0x1A, 0x44, 0x01, 0x2A, 0x5E, 0xD0, 0x0A, 0xB9, 0x5B, 0x4B, 0x1A, 0x60, 0x06, 0x9E, 0xD4, 0xF8, 0xD8, 0x31, 0x06, 0xF1, +0x18, 0x00, 0x28, 0x44, 0x98, 0x47, 0x06, 0xF1, 0x28, 0x00, 0xD4, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x04, 0x9A, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0x3A, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0x05, 0x26, 0x93, 0xF8, 0x63, 0x00, 0x0A, 0xF0, 0x02, 0xFA, 0x4B, 0x4B, 0x1A, 0x69, +0xBA, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x1A, 0x61, 0x00, 0x21, 0x4F, 0xF4, 0xA4, 0x62, 0x38, 0x46, 0xE9, 0xF7, 0x22, 0xFC, +0x04, 0x99, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0xD4, 0xF8, 0x50, 0xC4, 0x01, 0x91, 0x4F, 0xF4, 0xA4, 0x60, +0x00, 0xFB, 0x01, 0x55, 0x7F, 0x24, 0x00, 0x93, 0x3F, 0x49, 0xC5, 0xF8, 0x2C, 0xC0, 0x13, 0x44, 0x4F, 0xF4, 0x80, 0x70, +0x3D, 0x4A, 0x2F, 0x63, 0x85, 0xF8, 0x62, 0x60, 0x85, 0xF8, 0x65, 0x40, 0x85, 0xF8, 0x66, 0x40, 0x0D, 0xF0, 0xC2, 0xFE, +0x39, 0x48, 0x39, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x0C, 0xF0, 0x91, 0xBC, 0x93, 0xF8, 0xC1, 0x04, 0x01, 0x21, +0x09, 0xF0, 0x2E, 0xFC, 0x9A, 0xF8, 0x13, 0x30, 0x01, 0x3B, 0x8A, 0xF8, 0x13, 0x30, 0xB9, 0xE7, 0x31, 0x4A, 0xDA, 0xF8, +0x08, 0x60, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0x90, 0xDF, 0xF8, 0xC8, 0x80, 0xD2, 0xE9, 0x00, 0x01, 0x21, 0xF0, +0x10, 0x0C, 0x4C, 0xEA, 0x00, 0x00, 0xC2, 0xF8, 0x04, 0xC0, 0xCE, 0xF8, 0x00, 0x00, 0xB0, 0x6B, 0xB6, 0x8F, 0xC9, 0xF8, +0x00, 0x00, 0xC8, 0xF8, 0x00, 0x60, 0x00, 0x2B, 0x88, 0xD1, 0x13, 0x68, 0x21, 0xF4, 0x88, 0x71, 0x0B, 0x43, 0x51, 0x60, +0xCE, 0xF8, 0x00, 0x30, 0x80, 0xE7, 0x9A, 0xF8, 0x11, 0x20, 0x9A, 0xF8, 0x12, 0x30, 0x01, 0x3A, 0xD2, 0xB2, 0x8A, 0xF8, +0x11, 0x20, 0x71, 0xE7, 0xEA, 0xF7, 0x50, 0xFC, 0x00, 0x28, 0x40, 0xF0, 0x28, 0x81, 0xDF, 0xF8, 0x60, 0xA0, 0x12, 0x4C, +0x9A, 0xF8, 0x10, 0x00, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x53, 0x5A, 0x68, 0x19, 0x6C, 0x22, 0xF0, 0x80, 0x02, +0x5A, 0x60, 0x09, 0xB1, 0x63, 0x6D, 0x98, 0x47, 0x9A, 0xF8, 0x12, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x0D, 0x81, 0x0E, 0x48, +0x0E, 0x49, 0x42, 0x68, 0x0E, 0x4E, 0x01, 0x60, 0x0A, 0x43, 0x32, 0x60, 0xFF, 0x21, 0x9A, 0xF8, 0x11, 0x20, 0x8A, 0xF8, +0x10, 0x10, 0x49, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x08, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, +0x94, 0x64, 0x17, 0x00, 0xB8, 0x98, 0x15, 0x00, 0xDC, 0x98, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, +0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x04, 0x9E, 0xDF, 0xF8, +0x28, 0xA2, 0x7F, 0x49, 0x9A, 0xF8, 0x12, 0x20, 0x7E, 0x4C, 0xDF, 0xF8, 0x20, 0xB2, 0x06, 0xF1, 0x0A, 0x08, 0x08, 0xEB, +0x88, 0x03, 0x4F, 0xF4, 0x1E, 0x70, 0xC8, 0xEB, 0x03, 0x13, 0x4F, 0xF0, 0xA4, 0x0C, 0x00, 0xFB, 0x08, 0x18, 0x46, 0x33, +0x9E, 0x20, 0xCD, 0xE9, 0x08, 0x7A, 0x1C, 0xFB, 0x06, 0x06, 0x01, 0x3A, 0x00, 0x20, 0x01, 0xEB, 0xC3, 0x03, 0x03, 0x93, +0x8A, 0xF8, 0x12, 0x20, 0x88, 0xF8, 0x25, 0x00, 0x05, 0x90, 0x05, 0xEB, 0xC6, 0x06, 0xB9, 0x46, 0xD8, 0xF8, 0x08, 0x32, +0x9D, 0xF8, 0x14, 0x70, 0x3B, 0xB1, 0x03, 0x99, 0xD4, 0xF8, 0x84, 0x33, 0x4F, 0xF0, 0x80, 0x42, 0x28, 0x39, 0x38, 0x46, +0x98, 0x47, 0xD8, 0xF8, 0x30, 0x32, 0x33, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x03, 0x99, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, +0x98, 0x47, 0xD9, 0xF8, 0xF0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x30, 0x46, 0x0C, 0xF0, 0x55, 0xFC, 0xA6, 0xF1, +0x28, 0x0A, 0x07, 0x90, 0x50, 0x46, 0x0C, 0xF0, 0x4F, 0xFC, 0x07, 0x99, 0x02, 0x46, 0x5B, 0x48, 0x0D, 0xF0, 0xA0, 0xFD, +0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x58, 0x4A, 0x01, 0x23, 0x13, 0x60, 0xDB, 0xF8, 0x00, 0x20, +0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x38, 0x46, 0x98, 0x47, +0xD4, 0xF8, 0x84, 0x33, 0x51, 0x46, 0x38, 0x46, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, +0x4B, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x66, 0xD1, 0x05, 0x9B, 0x03, 0x9A, +0x01, 0x33, 0x08, 0x32, 0x05, 0x2B, 0x05, 0x93, 0x08, 0xF1, 0x08, 0x08, 0x06, 0xF1, 0x08, 0x06, 0x09, 0xF1, 0x08, 0x09, +0x03, 0x92, 0xA1, 0xD1, 0x04, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x53, 0xDD, 0xE9, 0x08, 0x7A, 0xD3, 0xF8, +0x18, 0x35, 0x00, 0x2B, 0x4F, 0xD0, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0x30, 0x46, 0x0C, 0xF0, 0x04, 0xFC, +0x01, 0x46, 0x38, 0x48, 0x0D, 0xF0, 0x56, 0xFD, 0xEF, 0xF3, 0x10, 0x83, 0xD9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x33, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x20, 0xD4, 0xF8, 0x84, 0x33, 0x01, 0x32, 0xCB, 0xF8, 0x00, 0x20, 0x31, 0x46, +0x4F, 0xF0, 0x80, 0x42, 0x05, 0x20, 0x98, 0x47, 0xDB, 0xF8, 0x00, 0x30, 0x3B, 0xB1, 0x2A, 0x4A, 0x01, 0x3B, 0x12, 0x68, +0xCB, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x00, 0x2A, 0x43, 0xD1, 0x9A, 0xF8, 0x12, 0x20, 0x00, 0x2A, 0x3C, 0xD0, 0x9A, 0xF8, +0x11, 0x30, 0x13, 0x44, 0x01, 0x2B, 0x7F, 0xF4, 0x71, 0xAE, 0x23, 0x49, 0xDA, 0xF8, 0x08, 0x00, 0x22, 0x4E, 0xD1, 0xE9, +0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x4B, 0x60, 0x1A, 0x43, 0x20, 0x49, 0x20, 0x4B, 0x32, 0x60, 0x86, 0x6B, 0x82, 0x8F, +0x0E, 0x60, 0x1A, 0x60, 0x5E, 0xE6, 0xD9, 0xF8, 0xC8, 0x34, 0x00, 0x2B, 0x7F, 0xF4, 0x68, 0xAF, 0xA6, 0xF1, 0x28, 0x0A, +0x72, 0xE7, 0x62, 0xB6, 0x96, 0xE7, 0x06, 0x9B, 0x03, 0xF5, 0xA3, 0x66, 0x2E, 0x44, 0xB5, 0xE7, 0x01, 0xF0, 0x4E, 0xFC, +0x9A, 0xF8, 0x12, 0x30, 0xF4, 0xE6, 0x00, 0x20, 0xEA, 0xF7, 0x2C, 0xFB, 0x12, 0x4B, 0x1A, 0x68, 0xD2, 0x05, 0x7F, 0xF5, +0xD0, 0xAE, 0x4F, 0xF4, 0x80, 0x72, 0xC3, 0xF8, 0x80, 0x20, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0xC6, 0xE6, +0x01, 0xF0, 0x5E, 0xFC, 0x2C, 0xE6, 0x62, 0xB6, 0xB9, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x88, 0x98, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0xA0, 0x98, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, +0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0xE1, 0x00, 0xE0, 0x00, 0x88, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x2E, 0x78, 0x95, 0xF8, 0x29, 0x80, 0x4F, 0x4C, 0x00, 0xFB, +0x08, 0xF0, 0xC6, 0xEB, 0x06, 0x17, 0x00, 0xEB, 0xC7, 0x07, 0x27, 0x44, 0x4F, 0xF0, 0x78, 0x0A, 0x1A, 0xFB, 0x06, 0x0A, +0x87, 0xF8, 0x3A, 0x12, 0x0A, 0xF5, 0xEC, 0x79, 0x95, 0xF8, 0x28, 0x30, 0x87, 0xF8, 0x38, 0x32, 0xA1, 0x44, 0x87, 0xF8, +0x39, 0x62, 0x48, 0x46, 0x48, 0x22, 0x00, 0x21, 0xE9, 0xF7, 0x46, 0xFA, 0x97, 0xF8, 0x38, 0x32, 0x37, 0x01, 0x05, 0x2B, +0x0C, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x41, 0x51, 0x0B, 0x41, 0x6A, 0x03, 0x0A, 0xF5, 0x0A, 0x70, 0x20, 0x44, 0x10, 0x22, +0x05, 0xF1, 0x08, 0x01, 0x20, 0xF0, 0xC2, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, +0xC2, 0x03, 0x23, 0x44, 0x00, 0x20, 0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, +0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x02, 0x22, 0x44, 0x23, 0x44, 0x92, 0xF8, 0x38, 0x12, 0x05, 0x29, 0x4F, 0xF0, 0x01, 0x00, +0x0C, 0xBF, 0xC3, 0xF8, 0xAC, 0x94, 0xC3, 0xF8, 0xA8, 0x94, 0x4F, 0xF4, 0xA4, 0x63, 0x82, 0xF8, 0x3B, 0x02, 0x03, 0xFB, +0x08, 0xF8, 0xD5, 0xE9, 0x02, 0x01, 0xD5, 0xE9, 0x04, 0x23, 0xBF, 0x1B, 0x08, 0xEB, 0xC7, 0x07, 0x3C, 0x44, 0xC4, 0xE9, +0x8F, 0x01, 0xC4, 0xE9, 0x91, 0x23, 0x2B, 0x79, 0x84, 0xF8, 0x4C, 0x32, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0xF0, 0x90, 0xFA, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF3, 0xBA, 0x1B, 0x03, 0xEB, 0xC2, 0x03, 0x23, 0x44, 0x20, 0xF0, 0x7F, 0x40, +0x00, 0x21, 0xC3, 0xE9, 0x88, 0x01, 0xC5, 0xE7, 0x4F, 0xF4, 0xA4, 0x60, 0xBB, 0x1B, 0x00, 0xFB, 0x08, 0xF0, 0x00, 0xEB, +0xC3, 0x00, 0x20, 0x44, 0xA9, 0x69, 0xC0, 0xF8, 0x28, 0x12, 0xE9, 0x69, 0xC0, 0xF8, 0x2C, 0x12, 0x29, 0x6A, 0xC0, 0xF8, +0x30, 0x12, 0x00, 0x22, 0x69, 0x6A, 0xC0, 0xF8, 0x34, 0x12, 0x00, 0x23, 0xC0, 0xE9, 0x88, 0x23, 0xAC, 0xE7, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x08, 0xF2, 0x05, 0xA1, 0xD1, 0xE9, 0x00, 0x01, 0xBB, 0x1B, 0x02, 0xEB, 0xC3, 0x03, 0x23, 0x44, +0xC3, 0xE9, 0x88, 0x01, 0x9E, 0xE7, 0x00, 0xBF, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x36, 0x5C, 0x18, 0x88, 0x17, 0x00, +0x78, 0x22, 0x10, 0xB4, 0xC1, 0xEB, 0x01, 0x13, 0xD0, 0xF8, 0xA8, 0x44, 0x02, 0xFB, 0x01, 0x01, 0x00, 0xEB, 0xC3, 0x03, +0x01, 0xF5, 0xEC, 0x71, 0x00, 0x22, 0x8C, 0x42, 0x83, 0xF8, 0x3B, 0x22, 0x06, 0xD0, 0xD0, 0xF8, 0xAC, 0x34, 0x8B, 0x42, +0x1C, 0xD0, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0x3B, 0x32, 0xC0, 0xF8, 0xA8, 0x24, 0x00, 0xF5, 0xEC, 0x71, +0x7B, 0xB9, 0x90, 0xF8, 0xB3, 0x32, 0x00, 0xF5, 0x14, 0x71, 0x53, 0xB9, 0x90, 0xF8, 0x2B, 0x33, 0x00, 0xF5, 0x32, 0x71, +0x2B, 0xB9, 0x90, 0xF8, 0xA3, 0x33, 0x00, 0xF5, 0x50, 0x71, 0x00, 0x2B, 0xE1, 0xD0, 0xC0, 0xF8, 0xA8, 0x14, 0xE2, 0xE7, +0x90, 0xF8, 0x1B, 0x34, 0x00, 0x22, 0xC0, 0xF8, 0xAC, 0x24, 0x43, 0xB9, 0x90, 0xF8, 0x93, 0x34, 0x00, 0x2B, 0xD8, 0xD0, +0x00, 0xF5, 0x86, 0x63, 0xC0, 0xF8, 0xAC, 0x34, 0xD3, 0xE7, 0x00, 0xF5, 0x6E, 0x73, 0xF9, 0xE7, 0x70, 0xB5, 0xD0, 0xF8, +0xE4, 0x40, 0x54, 0xB1, 0x05, 0x4E, 0x05, 0x46, 0x21, 0x46, 0xD6, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x28, 0x46, 0x98, 0x47, +0x24, 0x68, 0x00, 0x2C, 0xF6, 0xD1, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x04, 0x4A, 0x05, 0x4B, 0x11, 0x69, 0xD3, 0xF8, +0xE0, 0x31, 0x01, 0xF5, 0x1C, 0x51, 0x28, 0x30, 0x10, 0x31, 0x18, 0x47, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x0B, 0x4B, 0x1A, 0x78, 0x02, 0xB9, 0x70, 0x47, 0x5B, 0x68, 0x1B, 0x07, 0xFB, 0xD4, 0x43, 0x68, 0x70, 0xB5, 0x04, 0x46, +0x03, 0xB1, 0x70, 0xBD, 0x06, 0x4D, 0x28, 0x30, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x50, 0x34, 0x20, 0x46, +0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF0, 0xB4, 0xA0, 0xF8, +0xD2, 0x10, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x1F, 0x4D, +0x1F, 0x4B, 0x2E, 0x68, 0x9A, 0x7C, 0x77, 0x1C, 0x01, 0x2A, 0x2F, 0x60, 0x2B, 0xD9, 0x1D, 0x4C, 0x1A, 0x7D, 0x4F, 0xF4, +0xA4, 0x6C, 0x0C, 0xFB, 0x02, 0x42, 0xB2, 0xF8, 0xD2, 0x40, 0xA1, 0x42, 0x1C, 0xD3, 0x9B, 0x68, 0x5B, 0xB1, 0x01, 0x21, +0xB3, 0xF8, 0xD2, 0x20, 0x83, 0xF8, 0xD5, 0x10, 0xB2, 0xFB, 0xF4, 0xF2, 0x83, 0xF8, 0xD4, 0x20, 0x1B, 0x68, 0x00, 0x2B, +0xF4, 0xD1, 0x12, 0x4A, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x23, 0x43, 0x13, 0x60, 0x2F, 0xB1, 0x0A, 0x4B, 0x2E, 0x60, +0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x0C, 0x46, +0xDD, 0xE7, 0x90, 0xF8, 0x63, 0x20, 0x1A, 0x75, 0x40, 0xF2, 0x01, 0x13, 0x0C, 0x46, 0xA0, 0xF8, 0xD4, 0x30, 0xE2, 0xE7, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, +0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x21, 0x04, 0x46, 0x82, 0xB0, 0x03, 0x23, 0x00, 0x22, 0x58, 0x20, 0x0B, 0xF0, 0xEA, 0xFC, +0x3B, 0x4F, 0xFF, 0x22, 0x7B, 0x6D, 0x8D, 0xF8, 0x07, 0x20, 0x05, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x98, 0x47, 0xB4, 0xF8, +0xB6, 0x14, 0x94, 0xF8, 0xB4, 0x04, 0x10, 0xF0, 0xED, 0xF9, 0x94, 0xF8, 0xB5, 0x24, 0xB4, 0xF8, 0xB8, 0x64, 0xB4, 0xF8, +0xBA, 0x14, 0x84, 0xF8, 0xC5, 0x21, 0x04, 0x2A, 0x08, 0xBF, 0x03, 0x22, 0x03, 0x46, 0xC4, 0xF8, 0x90, 0x01, 0xA4, 0xF8, +0x94, 0x61, 0xA4, 0xF8, 0x96, 0x11, 0x84, 0xF8, 0xC4, 0x21, 0x00, 0x28, 0x50, 0xD0, 0x1B, 0x79, 0x84, 0xF8, 0xBC, 0x34, +0x7B, 0x6C, 0x0D, 0xF1, 0x07, 0x01, 0x04, 0xF2, 0xB4, 0x40, 0x98, 0x47, 0x9D, 0xF8, 0x07, 0x10, 0x68, 0x70, 0xA9, 0x70, +0x06, 0x46, 0x94, 0xF8, 0x63, 0x00, 0x28, 0x70, 0x94, 0xF8, 0x62, 0x30, 0x2B, 0xBB, 0x84, 0xF8, 0x8A, 0x30, 0x7E, 0xBB, +0xFB, 0x6C, 0x94, 0xF8, 0x6C, 0x80, 0x98, 0x47, 0xD7, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x28, 0x00, 0x98, 0x47, 0x1A, 0x4A, +0x1A, 0x49, 0xD7, 0xF8, 0xE0, 0x31, 0x09, 0x69, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x08, 0x28, 0x04, 0xF1, 0x18, 0x00, +0xD8, 0xF8, 0x08, 0x20, 0x11, 0x44, 0x98, 0x47, 0x01, 0x23, 0x84, 0xF8, 0x78, 0x60, 0x84, 0xF8, 0x8B, 0x30, 0x28, 0x46, +0x0B, 0xF0, 0xBE, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x02, 0x2B, 0xF7, 0xD1, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, +0x00, 0x2E, 0xF2, 0xD1, 0xFB, 0x6C, 0x98, 0x47, 0x0A, 0x4B, 0x01, 0x22, 0x5A, 0x72, 0xEC, 0xE7, 0xD7, 0xF8, 0xBC, 0x31, +0x20, 0x46, 0x98, 0x47, 0x28, 0x46, 0x0B, 0xF0, 0xA7, 0xFC, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1B, 0x79, 0xFF, 0xDE, +0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xD8, 0x9C, 0x17, 0x00, 0x07, 0x4A, 0x93, 0x7C, +0x51, 0x7C, 0x0B, 0x44, 0x01, 0x2B, 0x06, 0xD1, 0x90, 0x68, 0x90, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x18, 0xBF, 0x00, 0x20, +0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x05, 0x4A, 0x06, 0x49, 0x93, 0x7C, 0x50, 0x7C, +0x03, 0x44, 0x00, 0x22, 0x01, 0x2B, 0x0A, 0x60, 0x01, 0xDC, 0xFF, 0xF7, 0x65, 0xB9, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, +0x2C, 0x00, 0x32, 0x40, 0x13, 0x4B, 0x00, 0x22, 0x02, 0x70, 0x9B, 0x68, 0x03, 0xB3, 0x10, 0xB4, 0x01, 0x46, 0x01, 0x24, +0x10, 0x46, 0x08, 0xE0, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0xC0, 0x24, 0x72, 0xB9, 0x01, 0x30, 0x1B, 0x68, +0x7B, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF2, 0xD0, 0x93, 0xF8, 0x64, 0x20, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, +0xC0, 0x24, 0x00, 0x2A, 0xF1, 0xD0, 0x0C, 0x70, 0x1B, 0x68, 0x00, 0x2B, 0xEF, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x18, 0x46, 0x70, 0x47, 0x00, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x04, 0x23, 0x04, 0x46, 0xFF, 0x22, 0x00, 0x21, 0x87, 0x20, +0x0B, 0xF0, 0x16, 0xFC, 0x04, 0x60, 0xBD, 0xE8, 0x10, 0x40, 0x0B, 0xF0, 0x41, 0xBC, 0x00, 0xBF, 0x11, 0xF4, 0x00, 0x01, +0x70, 0xB5, 0x04, 0x46, 0x16, 0xD0, 0x00, 0x25, 0x2A, 0x4B, 0x80, 0xF8, 0x78, 0x50, 0x19, 0x69, 0x29, 0x48, 0x2A, 0x4B, +0x80, 0xF8, 0x24, 0x50, 0x40, 0xF2, 0x01, 0x72, 0x01, 0xF5, 0x1C, 0x51, 0x44, 0x61, 0x82, 0x83, 0xD3, 0xF8, 0xE0, 0x31, +0x10, 0x31, 0x0C, 0x30, 0x98, 0x47, 0x84, 0xF8, 0x6B, 0x50, 0x70, 0xBD, 0x90, 0xF8, 0x6B, 0x30, 0x21, 0x4A, 0x01, 0x33, +0xDB, 0xB2, 0x12, 0x68, 0x80, 0xF8, 0x6B, 0x30, 0x52, 0x78, 0x9A, 0x42, 0x25, 0xD0, 0x90, 0xF8, 0x64, 0x30, 0xC3, 0xB9, +0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, 0x1C, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x15, 0x4B, 0x1A, 0x7A, +0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x14, 0x4A, 0x17, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x01, 0x21, 0x99, 0x83, 0x90, 0x47, +0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x0E, 0x4B, 0x90, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0x94, 0x34, +0x10, 0x49, 0x22, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x80, 0xF8, 0x6B, 0x10, 0x4F, 0xF4, 0x80, 0x60, 0x0D, 0x49, +0x0D, 0xF0, 0x74, 0xFA, 0x05, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, +0x00, 0x10, 0x50, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, +0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x99, 0x71, 0x13, 0x00, 0xF0, 0x98, 0x15, 0x00, 0x30, 0xB4, 0x01, 0x25, +0x00, 0x24, 0x1D, 0x70, 0x14, 0x70, 0x04, 0x28, 0x20, 0xD8, 0xDF, 0xE8, 0x00, 0xF0, 0x03, 0x18, 0x09, 0x05, 0x14, 0x00, +0x00, 0x21, 0x19, 0x70, 0x01, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x09, 0x78, 0x10, 0x29, 0x0F, 0xD0, 0x20, 0x29, +0x01, 0xD1, 0x02, 0x21, 0x19, 0x70, 0x03, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x04, 0x23, 0x13, 0x70, 0x30, 0xBC, +0x70, 0x47, 0x02, 0x23, 0x13, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x21, 0x19, 0x70, 0xF0, 0xE7, 0x05, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0x30, 0xBC, 0x03, 0x49, 0x03, 0x48, 0xAD, 0x22, 0x0D, 0xF0, 0x50, 0xBC, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x22, 0x4A, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, +0x23, 0xB1, 0x13, 0x68, 0xC3, 0xF3, 0x0F, 0x33, 0x96, 0x2B, 0x36, 0xD9, 0x96, 0x20, 0x1E, 0x49, 0x1E, 0x4B, 0x0A, 0x68, +0x18, 0x81, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, 0x25, 0xD9, 0x96, 0x22, +0x19, 0x49, 0x5A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x96, 0x2A, +0x15, 0xD9, 0x96, 0x22, 0x14, 0x49, 0x9A, 0x81, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0x22, 0xB1, 0x0A, 0x68, 0xC2, 0xF3, +0x0F, 0x32, 0x96, 0x2A, 0x03, 0xD9, 0x96, 0x22, 0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, +0xDA, 0x81, 0x1A, 0x82, 0x70, 0x47, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, 0xE6, 0xE7, 0x0A, 0x68, 0xC2, 0xF3, 0x0F, 0x32, +0xD6, 0xE7, 0x10, 0x68, 0xC0, 0xF3, 0x0F, 0x30, 0xC5, 0xE7, 0x00, 0xBF, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, +0x98, 0x9C, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x0B, 0x4C, 0x34, 0x22, 0x00, 0x21, +0x20, 0x46, 0xE8, 0xF7, 0x0B, 0xFF, 0x09, 0x48, 0x09, 0x4A, 0x0A, 0x49, 0x22, 0x60, 0x01, 0x25, 0x00, 0x23, 0xE5, 0x77, +0x02, 0x60, 0x63, 0x82, 0x63, 0x60, 0xD1, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x05, 0x4B, 0x63, 0x62, 0x38, 0xBD, 0x00, 0xBF, +0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x88, 0x1A, 0x17, 0x00, 0x7D, 0x71, 0x13, 0x00, +0x38, 0xB5, 0x51, 0x4D, 0x51, 0x4C, 0xAB, 0x78, 0x13, 0xB9, 0xD4, 0xF8, 0xE4, 0x30, 0x98, 0x47, 0xFF, 0xF7, 0xD4, 0xFF, +0xFF, 0xF7, 0x6A, 0xF8, 0xFE, 0xF7, 0xF8, 0xFC, 0x09, 0xF0, 0xDC, 0xFC, 0x07, 0xF0, 0x78, 0xFD, 0x08, 0xF0, 0xAA, 0xFE, +0xD4, 0xF8, 0x8C, 0x33, 0x98, 0x47, 0xAB, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x82, 0x80, 0xFD, 0xF7, 0x61, 0xFA, 0x45, 0x4D, +0x2B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x7D, 0xD4, 0x03, 0xF0, 0x70, 0xFD, 0x09, 0xF0, 0x7C, 0xFE, 0x63, 0x6E, 0x98, 0x47, +0xD4, 0xF8, 0x7C, 0x31, 0x98, 0x47, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0xEF, 0xF7, 0x0D, 0xF8, 0x3C, 0x4B, +0x93, 0xF8, 0xFA, 0x30, 0x00, 0x2B, 0x62, 0xD1, 0xD4, 0xF8, 0xE4, 0x34, 0x98, 0x47, 0x39, 0x4A, 0x29, 0x68, 0x13, 0x68, +0x38, 0x48, 0x39, 0x4D, 0xC3, 0xF3, 0x15, 0x03, 0x43, 0xF0, 0x20, 0x73, 0x13, 0x60, 0x8B, 0x78, 0x02, 0x68, 0xDC, 0x06, +0x4C, 0xBF, 0x22, 0xF0, 0x00, 0x42, 0x42, 0xF0, 0x00, 0x42, 0x02, 0x60, 0x32, 0x4A, 0x33, 0x4C, 0x33, 0x48, 0x13, 0xF0, +0x01, 0x0F, 0x13, 0x68, 0x14, 0xBF, 0x43, 0xF4, 0x80, 0x23, 0x23, 0xF4, 0x80, 0x23, 0x13, 0x60, 0x22, 0x68, 0x2F, 0x4B, +0x42, 0xF0, 0x00, 0x62, 0x22, 0x60, 0x02, 0x68, 0x2D, 0x4C, 0x22, 0xF4, 0x70, 0x02, 0x42, 0xF4, 0x00, 0x12, 0x02, 0x60, +0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x62, 0x42, 0xF4, 0xC0, 0x62, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0x60, 0x52, 0x42, 0xF4, +0x00, 0x52, 0x1A, 0x60, 0x1A, 0x68, 0x22, 0xF4, 0xE0, 0x32, 0x42, 0xF4, 0x40, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, +0x60, 0x22, 0x1A, 0x60, 0x2B, 0x68, 0x20, 0x4A, 0x23, 0x40, 0x43, 0xF4, 0xBB, 0x63, 0xA0, 0xF5, 0x66, 0x70, 0x43, 0xF0, +0x04, 0x03, 0x2B, 0x60, 0x03, 0x68, 0xA5, 0xF1, 0xF6, 0x55, 0xA5, 0xF5, 0x32, 0x25, 0x23, 0x40, 0x43, 0xF0, 0x3F, 0x03, +0xA5, 0xF6, 0xFF, 0x15, 0x03, 0x60, 0x15, 0x60, 0x4B, 0x78, 0x2B, 0xB1, 0xD2, 0xF8, 0x24, 0x31, 0x43, 0xF0, 0x40, 0x03, +0xC2, 0xF8, 0x24, 0x31, 0x38, 0xBD, 0x12, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x9B, 0xE7, 0xFD, 0xF7, 0xD5, 0xF9, 0x7C, 0xE7, +0x03, 0x20, 0xEE, 0xF7, 0x8B, 0xFC, 0x7D, 0xE7, 0x3C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, +0x2C, 0x19, 0x17, 0x00, 0xF0, 0x00, 0x32, 0x40, 0x80, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, +0x40, 0x04, 0x32, 0x40, 0x34, 0x04, 0x32, 0x40, 0x2C, 0x04, 0x32, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x32, 0x40, +0x80, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x1C, 0x46, 0x05, 0x8C, 0x93, 0xF8, 0x62, 0x30, 0xD2, 0xF8, 0x20, 0x90, +0x87, 0x69, 0xD0, 0xF8, 0x1C, 0xB0, 0x89, 0xB0, 0x16, 0x46, 0xAD, 0x02, 0xDD, 0xE9, 0x12, 0x20, 0xD3, 0xB9, 0xB4, 0xF8, +0x68, 0xC0, 0xBC, 0xF1, 0x00, 0x0F, 0x15, 0xD0, 0xD2, 0x8B, 0xB3, 0x6A, 0x0C, 0xFB, 0x02, 0xF2, 0x05, 0x92, 0x18, 0x07, +0x05, 0xFB, 0x0C, 0xF2, 0x06, 0x92, 0x19, 0xD0, 0x00, 0x23, 0xB7, 0xEB, 0x09, 0x0A, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x93, +0x05, 0x9B, 0x03, 0xF5, 0xC8, 0x73, 0xC4, 0xE9, 0x1F, 0xA3, 0x74, 0xE0, 0x00, 0x28, 0x40, 0xF0, 0xC1, 0x80, 0x06, 0x95, +0x4F, 0xF0, 0x01, 0x0A, 0xD0, 0x8B, 0xB2, 0x6A, 0x0A, 0xFB, 0x00, 0xF0, 0x12, 0x07, 0x05, 0x90, 0x40, 0xF0, 0x32, 0x81, +0xF2, 0x6A, 0xDF, 0xF8, 0x94, 0xC2, 0xDF, 0xF8, 0xD4, 0x82, 0xDC, 0xF8, 0x00, 0x30, 0x9F, 0x48, 0xC2, 0xF3, 0x03, 0x12, +0x23, 0xF0, 0x7F, 0x03, 0x18, 0xF8, 0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xB3, 0x6A, +0x99, 0x4A, 0xC3, 0xF3, 0xC0, 0x13, 0x41, 0xEA, 0x03, 0x51, 0x4F, 0xF0, 0x00, 0x43, 0x01, 0x60, 0x13, 0x60, 0xBF, 0xF3, +0x4F, 0x8F, 0x00, 0xBF, 0x13, 0x68, 0x58, 0x00, 0xFC, 0xD5, 0x93, 0x4B, 0x19, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x00, 0x29, +0xC0, 0xF2, 0xB4, 0x80, 0x8E, 0x4A, 0x12, 0x68, 0x1F, 0xFA, 0x82, 0xFA, 0xB2, 0x6A, 0x12, 0x07, 0x40, 0xF0, 0xA3, 0x80, +0xF2, 0x6A, 0x8C, 0x49, 0x88, 0x48, 0xD1, 0xF8, 0x00, 0xC0, 0xC2, 0xF3, 0x03, 0x12, 0x2C, 0xF0, 0x7F, 0x0C, 0x18, 0xF8, +0x02, 0x20, 0x02, 0xF0, 0x7F, 0x02, 0x42, 0xEA, 0x0C, 0x02, 0x0A, 0x60, 0xB2, 0x6A, 0xC2, 0xF3, 0xC0, 0x12, 0x08, 0x31, +0x12, 0x05, 0x42, 0xF0, 0x18, 0x02, 0x4F, 0xF0, 0x00, 0x46, 0x02, 0x60, 0x0E, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x00, 0xBF, +0x0A, 0x68, 0x56, 0x00, 0xFC, 0xD5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x77, 0x4A, 0x94, 0xF8, +0x62, 0x30, 0x16, 0x68, 0x00, 0x22, 0xB6, 0xB2, 0xAA, 0xEB, 0x06, 0x0A, 0x07, 0x92, 0xB7, 0xEB, 0x09, 0x09, 0x19, 0xEB, +0x0A, 0x0A, 0x00, 0x2B, 0x84, 0xD0, 0x4F, 0xEA, 0xE5, 0x79, 0x2A, 0x46, 0x4B, 0x46, 0x38, 0x46, 0x59, 0x46, 0x1F, 0xF0, +0x67, 0xFB, 0xBA, 0x1B, 0x02, 0x92, 0x07, 0x9A, 0x00, 0xFB, 0x09, 0xF3, 0x6B, 0xEB, 0x02, 0x02, 0x05, 0xFB, 0x01, 0x33, +0x03, 0x92, 0xA0, 0xFB, 0x05, 0x01, 0x19, 0x44, 0xDD, 0xE9, 0x02, 0x23, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x38, 0xBF, +0xCD, 0xE9, 0x02, 0x01, 0x64, 0x4B, 0x06, 0x9A, 0x1B, 0x68, 0xDD, 0xE9, 0x02, 0x67, 0xB6, 0x18, 0x99, 0x01, 0x34, 0xD4, +0x05, 0x9B, 0xF1, 0x1A, 0xA1, 0xF5, 0xC8, 0x71, 0x5F, 0x4F, 0x60, 0x4B, 0x3E, 0x69, 0x1B, 0x68, 0xF6, 0x1A, 0x0E, 0x44, +0xE9, 0xF7, 0xDC, 0xFD, 0x3B, 0x69, 0xF3, 0x1A, 0xA3, 0xF5, 0x86, 0x53, 0x0C, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0x63, 0x6A, +0xB8, 0xBF, 0x76, 0x19, 0xB3, 0x42, 0x24, 0xD0, 0x57, 0x4B, 0x1A, 0x6A, 0xA2, 0x42, 0x43, 0xD0, 0x56, 0x4D, 0x31, 0x46, +0xD5, 0xF8, 0xE0, 0x31, 0x04, 0xF1, 0x18, 0x00, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x30, 0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, +0xF0, 0x4F, 0x18, 0x47, 0x90, 0xF8, 0x02, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x01, 0xD1, 0x90, 0xF8, 0x03, 0xA0, 0x05, 0xFB, +0x0A, 0xF0, 0x06, 0x90, 0x36, 0xE7, 0x4B, 0x49, 0x05, 0x9B, 0xC9, 0x1A, 0xA1, 0xEB, 0x0A, 0x0A, 0x0A, 0xEB, 0x06, 0x01, +0xC6, 0xE7, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0B, 0x68, 0x58, 0x00, 0x88, 0xD4, 0x45, 0x49, 0x45, 0x48, 0x4F, 0xF4, +0xBE, 0x72, 0x0D, 0xF0, 0xD7, 0xF9, 0x00, 0x22, 0x94, 0xF8, 0x62, 0x30, 0x07, 0x92, 0xAA, 0xF5, 0xFA, 0x7A, 0x4F, 0xF4, +0xFA, 0x76, 0x82, 0xE7, 0x12, 0x68, 0x51, 0x00, 0x3F, 0xF5, 0x48, 0xAF, 0x3B, 0x49, 0x3C, 0x48, 0x4F, 0xF4, 0xBE, 0x72, +0x0D, 0xF0, 0xC4, 0xF9, 0x4F, 0xF4, 0xFA, 0x7A, 0x2F, 0x4B, 0x41, 0xE7, 0x30, 0x4A, 0x66, 0x62, 0x12, 0x68, 0x92, 0x01, +0xB6, 0xD4, 0x36, 0x4A, 0x36, 0x4D, 0x12, 0x68, 0x93, 0xF8, 0x24, 0x10, 0x41, 0xF2, 0x13, 0x30, 0xC2, 0xF3, 0x07, 0x42, +0x2A, 0x54, 0x00, 0x29, 0x32, 0xD1, 0x32, 0x4A, 0x32, 0x49, 0x12, 0x68, 0x09, 0x68, 0x41, 0xF2, 0x14, 0x30, 0xD2, 0xB2, +0x2A, 0x54, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x0B, 0x78, 0x93, 0x42, 0x06, 0xD1, 0x2D, 0x49, 0x2D, 0x4A, 0x0B, 0x60, +0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x41, 0xF2, 0x13, 0x32, 0x41, 0xF2, 0x14, 0x33, 0xA8, 0x5C, 0xE9, 0x5C, +0x88, 0x42, 0x1D, 0xD2, 0x17, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDA, 0x41, 0xF2, 0x13, 0x32, +0x41, 0xF2, 0x14, 0x33, 0xAA, 0x5C, 0xEB, 0x5C, 0x9A, 0x42, 0x07, 0xD3, 0x18, 0x49, 0x20, 0x48, 0x15, 0x4D, 0x40, 0xF2, +0xD7, 0x12, 0x0D, 0xF0, 0xAF, 0xF9, 0x7E, 0xE7, 0x12, 0x4D, 0x7C, 0xE7, 0x00, 0x22, 0x4F, 0xF4, 0xFA, 0x76, 0x07, 0x92, +0x92, 0x46, 0x28, 0xE7, 0x12, 0x4E, 0x14, 0x48, 0xA9, 0x5C, 0xEA, 0x5C, 0x33, 0x68, 0x06, 0x68, 0x16, 0x48, 0xF6, 0xB2, +0x1B, 0x0C, 0x00, 0x96, 0x0C, 0xF0, 0x20, 0xFF, 0xD4, 0xE7, 0x00, 0xBF, 0x60, 0x81, 0x32, 0x40, 0x6C, 0x81, 0x32, 0x40, +0x38, 0x36, 0x17, 0x00, 0x64, 0x81, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0xA4, 0x80, 0x32, 0x40, +0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xFE, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, 0x04, 0x99, 0x15, 0x00, +0x44, 0x80, 0x32, 0x40, 0x00, 0x40, 0x1E, 0x00, 0x90, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, +0x74, 0x80, 0x32, 0x40, 0x3C, 0x99, 0x15, 0x00, 0x28, 0x99, 0x15, 0x00, 0x40, 0xA9, 0x15, 0x00, 0x0B, 0x02, 0x10, 0xB5, +0x04, 0x46, 0x03, 0xD5, 0x00, 0x23, 0x80, 0xF8, 0x78, 0x30, 0x10, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0x04, 0x49, 0x0C, 0xF0, +0x37, 0xFF, 0x04, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0xBC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB0, 0x99, 0x15, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x70, 0x93, 0xD9, 0xF8, 0x20, 0xB0, 0x83, 0xB0, 0x4F, 0xF4, +0x00, 0x20, 0x0B, 0xF0, 0x79, 0xFC, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xF5, 0x80, 0xBA, 0x4C, 0xDF, 0xF8, 0x58, 0xA3, +0xA1, 0x7F, 0xB9, 0x4F, 0xDF, 0xF8, 0x54, 0x83, 0xB8, 0x4E, 0x00, 0x29, 0x00, 0xF0, 0xEA, 0x80, 0x08, 0x07, 0x0E, 0xD5, +0xB6, 0x4B, 0xDB, 0xF8, 0x70, 0x00, 0x1B, 0x68, 0xDA, 0xF8, 0x10, 0x20, 0x5B, 0x68, 0x03, 0x44, 0x9B, 0x1A, 0x00, 0x2B, +0xC0, 0xF2, 0xCB, 0x80, 0x01, 0xF0, 0xF7, 0x01, 0xA1, 0x77, 0x4A, 0x07, 0x00, 0xF1, 0x99, 0x80, 0x8B, 0x07, 0x15, 0xD5, +0xDB, 0xF8, 0x04, 0x30, 0x23, 0xF0, 0x02, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x99, 0xF8, 0x1D, 0x30, 0x05, 0x2B, 0x08, 0xD1, +0xA8, 0x4D, 0xA9, 0x48, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA1, 0x7F, 0x89, 0xF8, 0x1D, 0x30, 0x01, 0xF0, +0xFD, 0x01, 0xA1, 0x77, 0xCD, 0x07, 0x2E, 0xD5, 0x33, 0x68, 0x58, 0x01, 0x40, 0xF1, 0xA3, 0x80, 0x31, 0x68, 0x09, 0x0C, +0x11, 0xF4, 0x7C, 0x7F, 0x00, 0xF0, 0xAA, 0x80, 0x9E, 0x4A, 0x10, 0x39, 0x01, 0xF0, 0xFF, 0x01, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xA1, 0x80, 0x99, 0x4A, 0x93, 0xF8, 0x22, 0x10, +0x13, 0x68, 0x98, 0x4A, 0xB3, 0xF9, 0x00, 0x30, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x22, 0x00, 0x2B, 0x00, 0x92, +0xC0, 0xF2, 0x9F, 0x80, 0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x00, 0xF0, 0xA8, 0x80, 0xA1, 0x7F, 0x01, 0xF0, 0xFE, 0x01, +0xA1, 0x77, 0x8A, 0x06, 0x9D, 0xD5, 0x8E, 0x4E, 0x8E, 0x49, 0x35, 0x68, 0xC5, 0xF3, 0x41, 0x17, 0x3A, 0x46, 0x02, 0x20, +0x0C, 0xF0, 0xAA, 0xFE, 0x00, 0x23, 0xC5, 0xF3, 0x47, 0x15, 0x8B, 0xF8, 0x78, 0x30, 0x00, 0x2F, 0x40, 0xF0, 0xB2, 0x80, +0x87, 0x4B, 0x80, 0x4E, 0x5A, 0x78, 0x1A, 0x70, 0x86, 0x4A, 0x87, 0x4D, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, +0xDB, 0xF8, 0x04, 0x30, 0xD6, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x01, 0x03, 0xCB, 0xF8, 0x04, 0x30, 0x0B, 0xF1, 0x28, 0x00, +0x90, 0x47, 0x2A, 0x68, 0x13, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x24, 0x81, 0x78, 0x49, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, +0x0B, 0x60, 0x13, 0x78, 0x01, 0x2B, 0x12, 0xD1, 0x01, 0xF5, 0xFF, 0x41, 0x34, 0x31, 0x78, 0x4A, 0xDA, 0xF8, 0x10, 0x30, +0x08, 0x68, 0xB2, 0xF8, 0xB2, 0x10, 0xD6, 0xF8, 0xE0, 0x21, 0x03, 0xEB, 0x40, 0x13, 0x59, 0x1A, 0x0B, 0xF1, 0x18, 0x00, +0x90, 0x47, 0x2B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x00, 0xF0, 0x00, 0x81, 0xA1, 0x7F, 0x01, 0xF0, 0xDF, 0x01, 0xA1, 0x77, +0x4B, 0xE7, 0x6D, 0x49, 0x61, 0x4D, 0x02, 0x20, 0x0C, 0xF0, 0x60, 0xFE, 0x6B, 0x49, 0x63, 0x68, 0x0A, 0x68, 0x22, 0xF0, +0x04, 0x02, 0x0A, 0x60, 0x22, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x1A, 0x43, 0x4A, 0x61, 0xD5, 0xF8, 0x98, 0x14, 0x63, 0x60, +0x9B, 0xF8, 0x63, 0x00, 0xD5, 0xF8, 0x94, 0x34, 0x5A, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xA1, 0x7F, 0x23, 0xF0, 0x7C, 0x73, +0x3B, 0x60, 0xD8, 0xF8, 0x00, 0x30, 0x01, 0xF0, 0xFB, 0x01, 0x43, 0xF4, 0x80, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xA1, 0x77, +0x3E, 0xE7, 0x5B, 0x48, 0x0C, 0xF0, 0xEA, 0xFD, 0x7F, 0xE7, 0x00, 0x22, 0x9B, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF8, 0xF7, +0x01, 0xFB, 0x60, 0xB1, 0xA1, 0x7F, 0x2B, 0xE7, 0x55, 0x48, 0x0C, 0xF0, 0xDD, 0xFD, 0x72, 0xE7, 0x54, 0x48, 0x0C, 0xF0, +0xD9, 0xFD, 0x6E, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x10, 0x30, 0xA1, 0x7F, 0xCB, 0xF8, 0x70, 0x30, +0x1A, 0xE7, 0x93, 0x45, 0x3F, 0xF4, 0x5E, 0xAF, 0x4D, 0x49, 0x4E, 0x48, 0x40, 0xF2, 0x22, 0x32, 0x0D, 0xF0, 0x40, 0xF8, +0x3B, 0x68, 0x13, 0xF4, 0xE0, 0x2F, 0x7F, 0xF4, 0x58, 0xAF, 0x32, 0x68, 0x33, 0x68, 0x49, 0x49, 0xD0, 0x0F, 0xC3, 0xF3, +0x80, 0x73, 0x05, 0x46, 0x02, 0x46, 0x02, 0x20, 0x01, 0x93, 0x0C, 0xF0, 0x05, 0xFE, 0x01, 0x9B, 0x53, 0xEA, 0x05, 0x02, +0x28, 0x46, 0x3F, 0xF4, 0x46, 0xAF, 0x2F, 0x4D, 0x00, 0x9A, 0x19, 0x46, 0xD5, 0xF8, 0x3C, 0x32, 0x98, 0x47, 0x33, 0x68, +0x23, 0xF0, 0x00, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x33, 0x60, 0x36, 0xE7, 0xDA, 0xF8, 0x10, 0x10, +0x01, 0xF5, 0x9C, 0x51, 0x32, 0x46, 0x08, 0x31, 0x05, 0xE0, 0xDA, 0xF8, 0x10, 0x30, 0xCB, 0x1A, 0x00, 0x2B, 0xC0, 0xF2, +0xC2, 0x80, 0x13, 0x68, 0x1B, 0x07, 0xF6, 0xD5, 0xDF, 0xF8, 0x90, 0x80, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x08, 0x03, +0xC8, 0xF8, 0x00, 0x30, 0xD8, 0xF8, 0x00, 0x30, 0xDE, 0x06, 0x19, 0xD5, 0x2C, 0x49, 0x19, 0x4E, 0x02, 0x20, 0x0C, 0xF0, +0xCF, 0xFD, 0x2B, 0x4B, 0xDF, 0xF8, 0x74, 0xC0, 0x1A, 0x68, 0xD6, 0xF8, 0x3C, 0x32, 0x12, 0x0C, 0x8C, 0xF8, 0x00, 0x20, +0x05, 0xF0, 0x01, 0x01, 0x78, 0x08, 0x5A, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x10, 0x03, 0xC8, 0xF8, +0x00, 0x30, 0x1B, 0xE7, 0x21, 0x4B, 0x22, 0x49, 0x0B, 0x4E, 0x01, 0x25, 0x1D, 0x60, 0x02, 0x20, 0x0C, 0xF0, 0xB2, 0xFD, +0x0F, 0x4A, 0x1F, 0x49, 0x53, 0x78, 0x0D, 0x60, 0xAB, 0x42, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x13, 0x70, 0x09, 0xE7, +0x98, 0x9C, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x70, 0x00, 0x32, 0x40, 0xC8, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x28, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x8C, 0x00, 0x32, 0x40, +0x20, 0x9A, 0x15, 0x00, 0x13, 0x53, 0x1E, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, +0xC0, 0x99, 0x15, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xC4, 0x99, 0x15, 0x00, 0xDC, 0x99, 0x15, 0x00, 0xF0, 0x99, 0x15, 0x00, +0x70, 0x79, 0x15, 0x00, 0x04, 0x9A, 0x15, 0x00, 0x14, 0x9A, 0x15, 0x00, 0x40, 0x9A, 0x15, 0x00, 0x44, 0x80, 0x32, 0x40, +0x64, 0x85, 0x32, 0x40, 0x4C, 0x9A, 0x15, 0x00, 0x68, 0x85, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, +0x6C, 0x00, 0x32, 0x40, 0x36, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xF7, 0xF7, 0x35, 0xF9, 0xF9, 0xE6, 0xEF, 0xF3, 0x10, 0x83, +0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x32, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x31, 0x4B, 0x2F, 0x4F, 0x1A, 0x68, 0x01, 0x32, +0x1A, 0x60, 0x00, 0x21, 0x3A, 0x68, 0x39, 0x60, 0x02, 0xF0, 0x0F, 0x08, 0xDA, 0xF8, 0x10, 0x20, 0x31, 0x46, 0x16, 0x46, +0x0A, 0x46, 0x47, 0xF2, 0x30, 0x50, 0x04, 0xE0, 0xDA, 0xF8, 0x10, 0x10, 0x89, 0x1B, 0x81, 0x42, 0x1B, 0xD8, 0x39, 0x68, +0x09, 0x07, 0xF7, 0xD1, 0x25, 0x48, 0x26, 0x49, 0xD0, 0xF8, 0x00, 0xC0, 0x0F, 0x68, 0x16, 0x46, 0xDA, 0xF8, 0x10, 0x20, +0xB8, 0xF1, 0x00, 0x0F, 0x1A, 0xD1, 0x22, 0x4A, 0x04, 0x21, 0x11, 0x60, 0x1A, 0x68, 0x32, 0xB1, 0x1B, 0x49, 0x01, 0x3A, +0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x2A, 0x68, 0xA0, 0xE6, 0x1C, 0x49, 0x00, 0x92, 0x02, 0x20, +0x0C, 0xF0, 0x24, 0xFD, 0x15, 0x4B, 0x00, 0x9A, 0xD3, 0xE7, 0x19, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x1D, 0xFD, 0x3B, 0xE7, +0x07, 0xEA, 0x0C, 0x07, 0x7F, 0x07, 0xE0, 0xD4, 0xCD, 0xE9, 0x00, 0x16, 0x80, 0x46, 0x16, 0x46, 0x01, 0xE0, 0x7A, 0x07, +0x12, 0xD4, 0x00, 0x9A, 0xD8, 0xF8, 0x00, 0x70, 0x12, 0x68, 0xDA, 0xF8, 0x10, 0x10, 0x47, 0xF2, 0x30, 0x50, 0x89, 0x1B, +0x81, 0x42, 0x07, 0xEA, 0x02, 0x07, 0xF0, 0xD9, 0x0B, 0x49, 0x02, 0x20, 0x0C, 0xF0, 0x00, 0xFD, 0x03, 0x4B, 0xEA, 0xE7, +0x01, 0x9E, 0xC4, 0xE7, 0x38, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, +0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x5C, 0x9A, 0x15, 0x00, 0x2C, 0x9A, 0x15, 0x00, 0x68, 0x9A, 0x15, 0x00, +0x10, 0xB5, 0x00, 0x20, 0x0B, 0xF0, 0xD0, 0xF8, 0x01, 0x28, 0x05, 0xD1, 0x05, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, +0x60, 0x31, 0x18, 0x47, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0B, 0xF0, 0x1A, 0xB8, 0x88, 0x1A, 0x17, 0x00, +0x03, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0x01, 0x21, 0x00, 0x20, 0x0B, 0xF0, 0x11, 0xB8, 0x00, 0xBF, 0x38, 0x00, 0x32, 0x40, +0xF8, 0xB5, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x46, 0xD0, 0x90, 0xF8, 0x8A, 0x30, 0x04, 0x46, 0x00, 0x2B, 0x42, 0xD1, +0x3D, 0x4E, 0x3E, 0x49, 0x94, 0xF8, 0x6C, 0x30, 0x3D, 0x4A, 0x67, 0x6A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, +0x9D, 0x68, 0x13, 0x6A, 0xA3, 0x42, 0x3D, 0x44, 0x54, 0xD0, 0xD6, 0xF8, 0xE0, 0x31, 0x29, 0x46, 0x04, 0xF1, 0x18, 0x00, +0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x82, 0xF8, 0xD4, 0xF8, 0x80, 0x10, 0xD6, 0xF8, 0x14, 0x32, 0x39, 0x44, 0x20, 0x46, +0x98, 0x47, 0xD6, 0xF8, 0xA4, 0x30, 0x2A, 0x46, 0x39, 0x46, 0x20, 0x46, 0x98, 0x47, 0xD8, 0xB9, 0x94, 0xF8, 0x78, 0x30, +0x62, 0x68, 0x2C, 0x49, 0x01, 0x33, 0xDB, 0xB2, 0x42, 0xF0, 0x01, 0x02, 0x09, 0x68, 0x84, 0xF8, 0x78, 0x30, 0x62, 0x60, +0x0A, 0x78, 0x93, 0x42, 0x21, 0xD8, 0x39, 0xD0, 0xB3, 0xEB, 0x52, 0x0F, 0x26, 0xD0, 0xB3, 0xEB, 0x92, 0x0F, 0x4F, 0xEA, +0x92, 0x01, 0x21, 0xD0, 0x01, 0xEB, 0x41, 0x01, 0x8B, 0x42, 0x1D, 0xD0, 0xF8, 0xBD, 0x90, 0xF8, 0x8C, 0x20, 0x00, 0x2A, +0xB8, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2B, 0x80, 0xF8, 0x8A, 0x30, 0x29, 0xD9, 0x02, 0x2B, 0x16, 0x4E, 0xB0, 0xD1, +0x90, 0xF8, 0x63, 0x00, 0xD6, 0xF8, 0xC0, 0x31, 0x00, 0x21, 0x98, 0x47, 0xA9, 0xE7, 0xD6, 0xF8, 0x64, 0x11, 0x94, 0xF8, +0x6C, 0x00, 0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF8, 0xF7, 0x30, 0xB9, 0xBD, 0xE8, 0xF8, 0x40, 0xEA, 0xF7, 0x5A, 0xBE, +0x0F, 0x4B, 0x65, 0x62, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xAA, 0xD1, 0x0D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, +0x9F, 0xD1, 0xA4, 0xE7, 0xEA, 0xF7, 0x4C, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0x06, 0xF0, 0x47, 0xBD, 0xBD, 0xE8, +0xF8, 0x40, 0xFF, 0xF7, 0x9B, 0xB8, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0xC8, 0x35, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x4B, 0x2D, 0xE9, 0xF0, 0x47, 0x9C, 0x68, +0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x35, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x34, 0x4D, 0x2B, 0x68, +0x04, 0x20, 0x01, 0x33, 0x2B, 0x60, 0xF6, 0xF7, 0xF1, 0xFC, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF6, 0xF7, 0x8C, 0xFD, +0x2B, 0x68, 0x2B, 0xB1, 0x2C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x4C, 0xD0, 0xDF, 0xF8, 0xB4, 0x80, +0x00, 0x2C, 0x43, 0xD0, 0x29, 0x4F, 0x2A, 0x4E, 0x40, 0xF6, 0xE7, 0x35, 0x02, 0xE0, 0x24, 0x68, 0x00, 0x2C, 0x3B, 0xD0, +0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xF8, 0xD1, 0x94, 0xF8, 0xD5, 0x30, 0x01, 0x3B, 0xDB, 0xB2, 0x84, 0xF8, 0xD5, 0x30, +0x00, 0x2B, 0xF0, 0xD1, 0x94, 0xF8, 0xD4, 0x30, 0x84, 0xF8, 0xD5, 0x30, 0x20, 0x46, 0xFE, 0xF7, 0xD3, 0xFF, 0x61, 0x6A, +0xD8, 0xF8, 0x14, 0x32, 0x01, 0xF6, 0xE8, 0x31, 0x20, 0x46, 0x98, 0x47, 0x3B, 0x68, 0xB4, 0xF8, 0xD2, 0x20, 0x59, 0x01, +0xB5, 0xEB, 0x43, 0x1F, 0x28, 0xBF, 0x01, 0xEB, 0x82, 0x21, 0x32, 0x69, 0x23, 0x6C, 0xA2, 0xF6, 0xE8, 0x39, 0x89, 0x44, +0x20, 0x46, 0x4A, 0x46, 0x1B, 0xB1, 0xD8, 0xF8, 0xA4, 0x30, 0x61, 0x6A, 0x98, 0x47, 0x94, 0xF8, 0xC0, 0x34, 0x04, 0xF1, +0x18, 0x00, 0x49, 0x46, 0x00, 0x2B, 0xC6, 0xD0, 0xD8, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x24, 0x68, 0x00, 0x2C, 0xC3, 0xD1, +0xD8, 0xF8, 0x84, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x00, 0x2A, 0xB0, 0xD0, 0x62, 0xB6, 0xAE, 0xE7, 0x00, 0xBF, +0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, +0x88, 0x1A, 0x17, 0x00, 0x08, 0xF0, 0x4A, 0xBE, 0x14, 0x4B, 0x15, 0x4A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x10, 0xB5, +0x14, 0x68, 0x00, 0x2B, 0x04, 0xF0, 0x40, 0x74, 0x14, 0xDB, 0x20, 0x46, 0x0B, 0xF0, 0x04, 0xF9, 0x0F, 0x4B, 0x9B, 0x7C, +0x3B, 0xB9, 0x0F, 0x4A, 0x0F, 0x4B, 0x10, 0x6A, 0xD3, 0xF8, 0xCC, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x0C, 0x4B, +0x20, 0x46, 0xD3, 0xF8, 0x68, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0xB4, 0xF1, 0x40, 0x7F, 0xE7, 0xD1, 0x08, 0x49, +0x08, 0x48, 0x4F, 0xF4, 0x9D, 0x62, 0x0C, 0xF0, 0xBB, 0xFD, 0xE0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, +0x00, 0x88, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x78, 0x9A, 0x15, 0x00, +0xF0, 0xB5, 0x2D, 0x4E, 0x2D, 0x4B, 0xDF, 0xF8, 0xC8, 0xE0, 0xDF, 0xF8, 0xC8, 0xC0, 0x2C, 0x4F, 0x4F, 0xF4, 0x1E, 0x72, +0x02, 0xFB, 0x00, 0x62, 0x15, 0x8D, 0xD4, 0x8C, 0x44, 0xEA, 0x05, 0x44, 0x1C, 0x60, 0x52, 0x8D, 0x27, 0x4D, 0x5A, 0x60, +0x00, 0x24, 0x27, 0x4A, 0xCE, 0xF8, 0x00, 0x40, 0x4F, 0xF0, 0x00, 0x53, 0xCC, 0xF8, 0x00, 0x40, 0x2C, 0x60, 0x00, 0xF1, +0x10, 0x05, 0x3C, 0x60, 0xEC, 0xB2, 0x13, 0x60, 0x13, 0x68, 0x9F, 0x00, 0xFC, 0xD4, 0xDD, 0x00, 0x26, 0xD4, 0x15, 0x68, +0xC5, 0xF3, 0x07, 0x43, 0xA3, 0x42, 0x4F, 0xEA, 0x15, 0x45, 0x1F, 0xD0, 0xED, 0xB2, 0xDF, 0xF8, 0x5C, 0xE0, 0xDF, 0xF8, +0x68, 0xC0, 0x18, 0x4F, 0x2D, 0x04, 0x4F, 0xF0, 0xFF, 0x33, 0x45, 0xF0, 0x80, 0x45, 0xCE, 0xF8, 0x00, 0x30, 0xCC, 0xF8, +0x00, 0x30, 0x15, 0x60, 0x3B, 0x68, 0x5A, 0x00, 0xFC, 0xD4, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x63, 0x0C, 0x48, +0x1D, 0x8D, 0xDA, 0x8C, 0x42, 0xEA, 0x05, 0x42, 0x02, 0x60, 0x0D, 0x4A, 0x5B, 0x8D, 0x13, 0x60, 0x0B, 0x01, 0x43, 0xEA, +0x04, 0x43, 0x09, 0x4A, 0x43, 0xF0, 0x80, 0x43, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, +0x20, 0x46, 0xF0, 0xBD, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, +0xC4, 0x00, 0x32, 0x40, 0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x41, +0x82, 0xB0, 0x47, 0x78, 0x90, 0xF8, 0x29, 0x60, 0x01, 0x23, 0x8D, 0xF8, 0x06, 0x30, 0xFF, 0x2F, 0x4F, 0xF0, 0x00, 0x03, +0x04, 0x46, 0x00, 0xF1, 0x04, 0x08, 0x8D, 0xF8, 0x07, 0x30, 0x00, 0xF0, 0x83, 0x80, 0x74, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x73, 0xDB, 0x3A, 0x46, 0x94, 0xF8, 0x28, 0x30, 0x70, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, +0xF5, 0xFA, 0x07, 0xF1, 0x10, 0x05, 0x6E, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x18, 0x33, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, +0x6B, 0x4A, 0x6C, 0x48, 0x6C, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0x22, 0x17, 0x8D, 0xD3, 0x8C, 0x43, 0xEA, +0x07, 0x43, 0x03, 0x60, 0x53, 0x8D, 0x0B, 0x60, 0x0D, 0xF1, 0x06, 0x03, 0x0D, 0xF1, 0x07, 0x02, 0x94, 0xF8, 0x28, 0x00, +0x41, 0x46, 0xFF, 0xF7, 0x7B, 0xF8, 0x63, 0x4B, 0xA2, 0x68, 0x1A, 0x60, 0xE2, 0x68, 0x5A, 0x60, 0x22, 0x69, 0x9A, 0x60, +0x62, 0x69, 0xDA, 0x60, 0x9D, 0xF8, 0x07, 0x30, 0x04, 0x2B, 0x65, 0xD0, 0x5D, 0x4A, 0x12, 0x68, 0x02, 0x2B, 0x12, 0x78, +0x1F, 0xD1, 0xD1, 0x07, 0x00, 0xF1, 0x85, 0x80, 0x5A, 0x48, 0x01, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x01, 0x60, 0x92, 0x07, +0x17, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x56, 0x4A, 0x2B, 0x04, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, +0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x5C, 0x00, 0xFC, 0xD4, 0x28, 0x46, +0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x97, 0x07, 0x6F, 0xD4, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x4A, 0x4A, +0x1B, 0x02, 0x43, 0xEA, 0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, +0x80, 0x43, 0x13, 0x60, 0x13, 0x68, 0x59, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0x2F, +0x89, 0xD9, 0x40, 0x49, 0x40, 0x48, 0x40, 0xF2, 0x5C, 0x52, 0x0C, 0xF0, 0xAB, 0xFC, 0x82, 0xE7, 0x90, 0xF8, 0x28, 0x30, +0x05, 0x2B, 0x4E, 0xD0, 0x34, 0x48, 0x35, 0x4A, 0x25, 0x78, 0x3B, 0x49, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x60, 0x13, 0x60, +0x94, 0xF8, 0x28, 0x30, 0x94, 0xF8, 0x29, 0x20, 0x4F, 0xF4, 0x80, 0x70, 0x0C, 0xF0, 0x6C, 0xFA, 0x05, 0xEB, 0x86, 0x05, +0x29, 0x4B, 0xED, 0xB2, 0xD3, 0xF8, 0x48, 0x34, 0x29, 0x46, 0x20, 0x46, 0x98, 0x47, 0x83, 0xE7, 0x30, 0x4A, 0xA1, 0x69, +0x11, 0x60, 0xE1, 0x69, 0x51, 0x60, 0x21, 0x6A, 0x91, 0x60, 0x27, 0x4A, 0x2D, 0x49, 0x60, 0x6A, 0x12, 0x68, 0x08, 0x60, +0x12, 0x78, 0x90, 0x07, 0xB1, 0xD5, 0x9D, 0xF8, 0x06, 0x00, 0x94, 0xF8, 0x2A, 0x10, 0x23, 0x4A, 0x1B, 0x02, 0x43, 0xEA, +0x00, 0x33, 0x43, 0xEA, 0x05, 0x43, 0x43, 0xEA, 0x06, 0x13, 0x43, 0xEA, 0x81, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, +0x13, 0x68, 0x58, 0x00, 0xFC, 0xD4, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x49, 0xA0, 0x69, 0x08, 0x60, +0xE0, 0x69, 0x48, 0x60, 0x20, 0x6A, 0x88, 0x60, 0x60, 0x6A, 0xC8, 0x60, 0x75, 0xE7, 0x5A, 0x1E, 0x01, 0x2A, 0xDA, 0xD8, +0x73, 0xE7, 0x18, 0x4B, 0x05, 0x78, 0x1B, 0x68, 0x09, 0x4A, 0x1B, 0x0E, 0x03, 0x3B, 0x2B, 0x44, 0x03, 0xEB, 0x46, 0x03, +0xDD, 0xB2, 0x29, 0x46, 0xD2, 0xF8, 0x48, 0x34, 0x98, 0x47, 0x28, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0xB4, 0x9A, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xBC, 0x00, 0x32, 0x40, +0xC0, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, 0x34, 0x36, 0x17, 0x00, 0x64, 0x05, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, +0x70, 0x79, 0x15, 0x00, 0xA0, 0x9A, 0x15, 0x00, 0x90, 0x9A, 0x15, 0x00, 0xC8, 0x00, 0x32, 0x40, 0xD4, 0x00, 0x32, 0x40, +0xD8, 0x00, 0x32, 0x40, 0x33, 0x4A, 0x13, 0x68, 0xB0, 0xEB, 0x13, 0x6F, 0x70, 0xB5, 0x04, 0x46, 0x46, 0xD8, 0x0F, 0x28, +0x24, 0xD8, 0x30, 0x4B, 0x30, 0x4D, 0x31, 0x49, 0x31, 0x48, 0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0xA3, 0x10, 0x2A, 0x60, +0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x00, 0xD1, 0xF8, 0x54, 0x34, 0x04, 0xF0, 0x03, 0x01, 0x98, 0x47, 0x2B, 0x4A, +0x2B, 0x49, 0x2C, 0x4E, 0x2C, 0x4D, 0x2D, 0x48, 0x24, 0x04, 0x00, 0x23, 0x44, 0xF0, 0x80, 0x44, 0x33, 0x60, 0x2B, 0x60, +0x13, 0x60, 0x03, 0x60, 0x0A, 0x46, 0x0C, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0x70, 0xBD, 0xA0, 0xF1, 0x10, 0x05, +0x25, 0x48, 0x4F, 0xF4, 0x1E, 0x73, 0xED, 0xB2, 0x03, 0xFB, 0x05, 0x05, 0x28, 0x46, 0x95, 0xF8, 0x22, 0x60, 0xFD, 0xF7, +0xD3, 0xFF, 0x1A, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, 0x96, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0xE8, 0xD0, +0x28, 0x8D, 0xEB, 0x8C, 0x11, 0x49, 0x12, 0x4A, 0x43, 0xEA, 0x00, 0x43, 0x0B, 0x60, 0x6B, 0x8D, 0x13, 0x60, 0xCC, 0xE7, +0x13, 0x68, 0x15, 0x68, 0x0F, 0x48, 0x0E, 0x4A, 0x1B, 0x0E, 0x01, 0x33, 0xE3, 0x1A, 0x61, 0x1E, 0xA1, 0xEB, 0x15, 0x61, +0x03, 0xEB, 0xD3, 0x73, 0x5B, 0x10, 0x4F, 0xF4, 0xA4, 0x64, 0x01, 0xF0, 0x01, 0x01, 0x04, 0xFB, 0x03, 0x00, 0x04, 0x31, +0xBD, 0xE8, 0x70, 0x40, 0xD2, 0xF8, 0x54, 0x34, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x00, 0x32, 0x40, 0xBC, 0x00, 0x32, 0x40, +0xC0, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB4, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, +0xAC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB4, 0x0E, 0x49, +0x0E, 0x4F, 0x0F, 0x4E, 0x0F, 0x4D, 0x10, 0x4C, 0x4F, 0xF0, 0xFF, 0x32, 0x00, 0xF1, 0x10, 0x03, 0x0E, 0x48, 0x3A, 0x60, +0xDB, 0xB2, 0x0A, 0x60, 0x00, 0x21, 0x01, 0x60, 0x1B, 0x04, 0x18, 0x30, 0x43, 0xF0, 0x80, 0x43, 0x31, 0x60, 0x02, 0x46, +0x29, 0x60, 0x21, 0x60, 0x03, 0x60, 0x13, 0x68, 0x5B, 0x00, 0xFC, 0xD4, 0xF0, 0xBC, 0x70, 0x47, 0xC0, 0x00, 0x32, 0x40, +0xBC, 0x00, 0x32, 0x40, 0xB0, 0x00, 0x32, 0x40, 0xB4, 0x00, 0x32, 0x40, 0xB8, 0x00, 0x32, 0x40, 0xAC, 0x00, 0x32, 0x40, +0x08, 0xB5, 0x4F, 0xF0, 0x80, 0x60, 0x0A, 0xF0, 0xA5, 0xFE, 0x00, 0x21, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x46, 0x0A, 0xF0, +0x89, 0xBC, 0x00, 0xBF, 0x14, 0x4B, 0x15, 0x49, 0x1A, 0x68, 0x22, 0xF0, 0x02, 0x02, 0xF0, 0xB4, 0x1A, 0x60, 0x1A, 0x68, +0x12, 0x4F, 0x13, 0x4E, 0x13, 0x4D, 0x14, 0x4C, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x4F, 0xF4, 0x40, 0x72, 0x3A, 0x60, +0x07, 0x68, 0x82, 0x88, 0x00, 0x20, 0x30, 0x60, 0x28, 0x60, 0x27, 0x60, 0x0E, 0x4C, 0x0A, 0x60, 0x19, 0x68, 0x62, 0x68, +0x0D, 0x4D, 0xA6, 0xF5, 0x00, 0x46, 0x44, 0x3E, 0x2A, 0x43, 0x21, 0xF4, 0xE0, 0x61, 0x19, 0x60, 0x25, 0x60, 0x32, 0x60, +0xF0, 0xBC, 0xFC, 0xF7, 0x57, 0xBE, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x14, 0x00, 0x32, 0x40, 0x1C, 0x00, 0x32, 0x40, +0xA4, 0x80, 0x32, 0x40, 0xA8, 0x80, 0x32, 0x40, 0x10, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x8C, 0x84, 0x03, 0x35, +0x0B, 0x49, 0x0C, 0x48, 0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0B, 0x4C, 0x0B, 0x4D, 0x42, 0xF0, 0x02, 0x02, 0x23, 0x43, +0x02, 0x60, 0x0C, 0x60, 0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x36, 0xFE, 0x07, 0x4B, 0x08, 0x49, 0x08, 0x4A, 0x19, 0x60, +0x13, 0x68, 0x0B, 0x43, 0x13, 0x60, 0x38, 0xBD, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x8C, 0xA4, 0x07, 0x35, +0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0x0D, 0x49, 0x0E, 0x48, +0x38, 0xB5, 0x02, 0x68, 0x4B, 0x68, 0x0D, 0x4C, 0x0D, 0x4D, 0x22, 0xF0, 0x02, 0x02, 0x23, 0x43, 0x02, 0x60, 0x0C, 0x60, +0x00, 0x20, 0x2B, 0x60, 0xFC, 0xF7, 0x10, 0xFE, 0x09, 0x4B, 0x0A, 0x4A, 0x0A, 0x49, 0x19, 0x60, 0x13, 0x68, 0x23, 0xF4, +0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, +0x8C, 0x84, 0x03, 0x35, 0x60, 0x00, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, +0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, 0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA5, 0x01, +0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0x00, 0xEB, 0x80, 0x03, 0xC0, 0xEB, 0x03, 0x10, +0x04, 0x4B, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0x90, 0xF8, 0xA4, 0x01, 0x21, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, +0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x37, 0x4A, 0x37, 0x4B, 0x92, 0xF8, 0x30, 0x10, 0x1B, 0x68, 0x00, 0x29, 0x45, 0xD1, +0x00, 0x28, 0x40, 0xD0, 0x9B, 0xB2, 0x01, 0x21, 0x80, 0xEA, 0xE0, 0x76, 0x00, 0x28, 0x4F, 0xEA, 0x83, 0x23, 0x82, 0xF8, +0x30, 0x10, 0xA6, 0xEB, 0xE0, 0x76, 0x4E, 0xDD, 0xB6, 0xEB, 0x53, 0x0F, 0x23, 0xFA, 0x01, 0xF4, 0x98, 0xBF, 0x04, 0x46, +0xEF, 0xF3, 0x10, 0x81, 0xC9, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x29, 0x49, 0x01, 0x20, 0x08, 0x60, 0x28, 0x4D, 0x29, 0x4F, +0x29, 0x68, 0x29, 0x48, 0x01, 0x31, 0x00, 0x68, 0x29, 0x60, 0x39, 0x69, 0x00, 0x2C, 0x4F, 0xEA, 0x40, 0x17, 0x01, 0xEB, +0x40, 0x11, 0x4F, 0xEA, 0x93, 0x00, 0x25, 0xDD, 0xB8, 0x42, 0x1A, 0xD8, 0x64, 0x36, 0xDB, 0x1B, 0x9E, 0x42, 0x31, 0xD9, +0x20, 0x4B, 0x94, 0x62, 0x09, 0x1A, 0xD3, 0xF8, 0xE0, 0x31, 0x1F, 0x48, 0x98, 0x47, 0x2B, 0x68, 0x43, 0xB1, 0x18, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x1B, 0xB9, 0x12, 0xB1, 0x62, 0xB6, 0x00, 0xE0, 0x04, 0x46, 0x20, 0x46, 0xF8, 0xBD, +0x00, 0x24, 0x20, 0x46, 0xF8, 0xBD, 0x15, 0x4E, 0x94, 0x62, 0x19, 0x44, 0x09, 0x1A, 0xD6, 0xF8, 0xE0, 0x31, 0x13, 0x48, +0x98, 0x47, 0xE6, 0xE7, 0x30, 0x44, 0xB8, 0x42, 0x0E, 0xD3, 0x0F, 0x4B, 0x0F, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0x94, 0x62, +0x64, 0x31, 0x98, 0x47, 0xDB, 0xE7, 0x5C, 0x08, 0xB6, 0xEB, 0x53, 0x0F, 0x8C, 0xBF, 0x64, 0x42, 0x04, 0x46, 0xAF, 0xE7, +0x20, 0x46, 0xFE, 0xF7, 0x57, 0xFD, 0xD0, 0xE7, 0x98, 0x9C, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xB8, 0x9C, 0x17, 0x00, +0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x0E, 0xDB, 0x11, 0x4B, 0xDB, 0x7F, 0x2B, 0xB1, +0x10, 0x4A, 0x93, 0x7C, 0x52, 0x7C, 0x13, 0x44, 0x01, 0x2B, 0x11, 0xDD, 0x0E, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, +0x60, 0x31, 0x18, 0x47, 0x00, 0x20, 0x0A, 0xF0, 0xED, 0xFB, 0x03, 0x28, 0xEB, 0xD0, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, +0x06, 0x72, 0x0C, 0xF0, 0x25, 0xFA, 0xE4, 0xE7, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x0A, 0xF0, 0x36, 0xBB, +0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xC4, 0x9A, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x39, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x61, 0xDB, +0x37, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0xDC, 0xFF, 0xEF, 0xF3, 0x10, 0x83, 0xD8, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x34, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0x80, 0x32, 0x4C, 0xD8, 0xF8, 0x00, 0x30, 0x32, 0x4D, 0x01, 0x33, 0x00, 0x22, +0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x22, 0x60, 0x2F, 0x69, 0x03, 0xF0, 0x0F, 0x09, 0x47, 0xF2, 0x30, 0x56, 0x05, 0xE0, +0xF6, 0xF7, 0x22, 0xFB, 0x2B, 0x69, 0xDB, 0x1B, 0xB3, 0x42, 0x2C, 0xD8, 0x23, 0x68, 0x19, 0x07, 0xF6, 0xD1, 0x28, 0x4A, +0x28, 0x48, 0x53, 0x68, 0x28, 0x49, 0x04, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x53, 0x60, 0x0B, 0x68, 0xB9, 0xF1, 0x00, 0x0F, +0x22, 0xD1, 0x25, 0x4B, 0x25, 0x49, 0x04, 0x20, 0x18, 0x60, 0x0B, 0xF0, 0xA7, 0xFF, 0x24, 0x4B, 0x93, 0xF8, 0x5A, 0x30, +0x0B, 0xBB, 0x03, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0xE1, 0xFA, 0x21, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x00, 0x21, 0x51, 0x82, +0x3B, 0xB1, 0x15, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, +0xF8, 0x83, 0x1A, 0x49, 0x04, 0x20, 0x0B, 0xF0, 0x8B, 0xFF, 0xC4, 0xE7, 0x23, 0x40, 0x5A, 0x07, 0xD9, 0xD4, 0x02, 0x68, +0x0B, 0x68, 0x13, 0x40, 0x5B, 0x07, 0xFA, 0xD5, 0xD3, 0xE7, 0xF6, 0xF7, 0x07, 0xFB, 0xDA, 0xE7, 0x00, 0x20, 0x0A, 0xF0, +0x65, 0xFB, 0x04, 0x28, 0x98, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x40, 0xF2, 0x14, 0x72, 0x0C, 0xF0, 0x9D, 0xF9, 0x91, 0xE7, +0x38, 0x36, 0x17, 0x00, 0x14, 0x9B, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, +0x1C, 0x9E, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x28, 0x9B, 0x15, 0x00, +0x30, 0x9D, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x5C, 0x9A, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF0, 0x9A, 0x15, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x24, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x31, 0xDB, 0x00, 0x20, +0x0A, 0xF0, 0x32, 0xFB, 0x02, 0x28, 0x05, 0xD0, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x82, 0xBA, +0x1C, 0x4B, 0x30, 0x22, 0x1A, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x19, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x19, 0x4C, 0x23, 0x68, 0x4F, 0xF0, 0x80, 0x60, 0x01, 0x33, 0x23, 0x60, 0x0A, 0xF0, 0x85, 0xFC, 0x16, 0x4B, +0x1B, 0x68, 0x5B, 0x07, 0x02, 0xD5, 0x15, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0x23, 0x68, 0x00, 0x2B, 0xDC, 0xD0, 0x0F, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x00, 0x2B, 0xD6, 0xD1, 0x00, 0x2A, 0xD4, 0xD0, 0x62, 0xB6, 0xD2, 0xE7, 0x00, 0x20, +0x0A, 0xF0, 0x00, 0xFB, 0x03, 0x28, 0x04, 0xD0, 0x00, 0x20, 0x0A, 0xF0, 0xFB, 0xFA, 0x00, 0x28, 0xC3, 0xD1, 0x09, 0x49, +0x09, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x0C, 0xF0, 0x33, 0xF9, 0xBC, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x6C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, +0x3C, 0x9B, 0x15, 0x00, 0x08, 0xB5, 0x00, 0x20, 0x0A, 0xF0, 0xDE, 0xFA, 0x04, 0x28, 0x00, 0xD0, 0x08, 0xBD, 0xBD, 0xE8, +0x08, 0x40, 0x01, 0x21, 0x00, 0x20, 0x0A, 0xF0, 0x2D, 0xBA, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0x78, 0xA0, +0xDA, 0xF8, 0x1C, 0x33, 0x17, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x98, 0x47, 0x04, 0x46, 0x60, 0xBB, 0x96, 0xF8, 0x00, 0x90, +0x16, 0x4A, 0x95, 0xF8, 0x19, 0x80, 0xDA, 0xF8, 0xB0, 0x31, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x09, 0x29, 0x41, 0x46, +0x89, 0xF8, 0x5D, 0x02, 0xA9, 0xF8, 0x5E, 0x02, 0x30, 0x78, 0x98, 0x47, 0x38, 0x70, 0xD9, 0xF8, 0x2C, 0x30, 0x2B, 0xB1, +0xDA, 0xF8, 0xB0, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x69, 0x7E, 0x90, 0x47, 0x0A, 0x49, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, +0x08, 0x11, 0x91, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x33, 0x78, 0x81, 0xF8, 0x6C, 0x30, 0x6B, 0x7F, 0x81, 0xF8, 0x6D, 0x30, +0xAB, 0x7F, 0x81, 0xF8, 0x6E, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x7C, 0x4E, 0x7D, 0x4C, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x00, 0x67, +0x4F, 0xF0, 0x4F, 0x08, 0x46, 0x23, 0x18, 0xFB, 0x00, 0x38, 0x97, 0xF8, 0x22, 0xB0, 0x85, 0xB0, 0x05, 0x46, 0x06, 0xEB, +0xC8, 0x08, 0x4F, 0xF0, 0x00, 0x09, 0xD7, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x89, 0xFA, 0xA8, 0xF1, 0x28, 0x01, 0x4F, 0xF0, +0x80, 0x42, 0x09, 0xF1, 0x01, 0x09, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, 0x98, 0x47, 0xD7, 0xF8, 0x30, 0x32, +0x41, 0x46, 0x08, 0x37, 0x08, 0xF1, 0x08, 0x08, 0x4F, 0xF0, 0x80, 0x42, 0x50, 0x46, 0x13, 0xB1, 0xD4, 0xF8, 0x84, 0x33, +0x98, 0x47, 0xB9, 0xF1, 0x05, 0x0F, 0xE0, 0xD1, 0x65, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x33, 0x93, 0xF8, +0x62, 0x10, 0xC1, 0xB9, 0xFF, 0x22, 0x83, 0xF8, 0x6C, 0x20, 0xD4, 0xF8, 0xAC, 0x31, 0x28, 0x46, 0x98, 0x47, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x05, 0x66, 0xF3, 0x6A, 0x23, 0xB1, 0x93, 0xF8, 0x23, 0x00, 0xD4, 0xF8, 0xAC, 0x31, 0x98, 0x47, +0xD4, 0xF8, 0x24, 0x33, 0x28, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF4, 0x1E, 0x78, 0x08, 0xFB, +0x05, 0x62, 0x92, 0xF8, 0x24, 0x90, 0xB9, 0xF1, 0x01, 0x0F, 0x02, 0xD0, 0x02, 0x29, 0xED, 0xD0, 0xDD, 0xE7, 0x93, 0xF8, +0xDE, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x83, 0xF8, 0xDE, 0x20, 0x00, 0x2A, 0xF4, 0xD1, 0x93, 0xF8, 0x63, 0xA0, 0x0A, 0xF1, +0x0A, 0x0A, 0x5F, 0xFA, 0x8A, 0xFA, 0x08, 0xFB, 0x0A, 0xF3, 0x06, 0xEB, 0x03, 0x08, 0x00, 0x93, 0x98, 0xF8, 0x24, 0x30, +0x73, 0xB9, 0x44, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x0B, 0x37, 0x38, 0x46, 0x97, 0xF8, 0x63, 0x10, 0xE3, 0x68, +0x0A, 0x31, 0xC9, 0xB2, 0x98, 0x47, 0x97, 0xF8, 0x62, 0x10, 0xD7, 0xE7, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0x01, 0x92, +0x09, 0xF0, 0x64, 0xFF, 0x01, 0x9A, 0x88, 0xF8, 0x24, 0x20, 0x80, 0xF8, 0x00, 0xA0, 0x42, 0x70, 0x09, 0xF0, 0x8C, 0xFF, +0x98, 0xF8, 0x24, 0x30, 0x00, 0x2B, 0xDE, 0xD1, 0x98, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0xDA, 0xD8, 0x98, 0xF8, 0x22, 0x00, +0x31, 0x4B, 0xCD, 0xF8, 0x04, 0x90, 0x9E, 0x22, 0xA4, 0x21, 0x11, 0xFB, 0x00, 0x21, 0x2D, 0x4A, 0x03, 0x95, 0x07, 0xFB, +0x00, 0x27, 0x2B, 0x48, 0x02, 0x97, 0x4F, 0xF0, 0x4F, 0x0C, 0x46, 0x27, 0x1C, 0xFB, 0x0A, 0x77, 0x00, 0xEB, 0xC1, 0x0A, +0x00, 0x99, 0x28, 0x4A, 0x02, 0x9D, 0xC1, 0x46, 0x88, 0x46, 0x06, 0xEB, 0xC7, 0x07, 0x98, 0x44, 0xD9, 0xF8, 0x08, 0x12, +0x31, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x21, 0x4B, 0x01, 0x99, 0x19, 0x60, 0x11, 0x68, +0xA7, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xAA, 0xF1, 0x28, 0x01, 0x13, 0x60, 0x00, 0x90, 0x0A, 0xF0, 0xA1, 0xFC, 0xD9, 0xF8, +0x08, 0x12, 0xD9, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC5, 0xF8, 0xC8, 0x14, 0xC5, 0xF8, 0xCC, 0x34, 0x0A, 0xF0, 0xA0, 0xFB, +0x14, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x29, 0xB1, 0x13, 0x4B, 0x10, 0x60, 0x19, 0x68, 0x08, 0xB9, 0x01, 0xB1, 0x62, 0xB6, +0xD9, 0xF8, 0x30, 0x32, 0x50, 0x46, 0x39, 0x46, 0x09, 0xF1, 0x08, 0x09, 0x0A, 0xF1, 0x08, 0x0A, 0x08, 0x35, 0x2B, 0xB1, +0x0A, 0xF0, 0x80, 0xFC, 0x38, 0x46, 0x0A, 0xF0, 0x87, 0xFB, 0x08, 0x4A, 0x08, 0x37, 0x47, 0x45, 0xC2, 0xD1, 0x40, 0x20, +0x03, 0x9D, 0x0A, 0xF0, 0xE1, 0xFA, 0x7A, 0xE7, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x10, 0xB5, 0x01, 0x23, 0x04, 0x46, 0x00, 0x22, +0x06, 0x21, 0x43, 0x20, 0x09, 0xF0, 0xE0, 0xFE, 0x94, 0xF8, 0x63, 0x30, 0x03, 0x70, 0xBD, 0xE8, 0x10, 0x40, 0x09, 0xF0, +0x09, 0xBF, 0x00, 0xBF, 0x70, 0xB5, 0x90, 0xF9, 0x87, 0x30, 0x04, 0x46, 0x90, 0xF9, 0x86, 0x00, 0x94, 0xF8, 0x88, 0x20, +0x94, 0xF8, 0x89, 0x60, 0x84, 0xF8, 0x86, 0x10, 0xBB, 0xB1, 0x0D, 0x46, 0x52, 0xB2, 0xAE, 0xB9, 0x88, 0x42, 0x10, 0xDD, +0x9B, 0x1A, 0x99, 0x42, 0x0D, 0xDA, 0x01, 0x26, 0x00, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x57, 0x20, 0x09, 0xF0, 0xBC, 0xFE, +0x94, 0xF8, 0x63, 0x20, 0x02, 0x70, 0x46, 0x70, 0x85, 0x70, 0x09, 0xF0, 0xE5, 0xFE, 0x84, 0xF8, 0x89, 0x60, 0x70, 0xBD, +0x01, 0x2E, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x13, 0x44, 0x99, 0x42, 0xF5, 0xDD, 0x00, 0x26, 0xE6, 0xE7, 0x00, 0xBF, +0x14, 0x4B, 0x93, 0xF9, 0x00, 0x20, 0x22, 0xB3, 0x30, 0xB4, 0x9C, 0x78, 0x90, 0xF9, 0x86, 0x00, 0x93, 0xF9, 0x01, 0x50, +0x6C, 0xB9, 0x88, 0x42, 0x08, 0xDD, 0x52, 0x1B, 0x91, 0x42, 0x05, 0xDA, 0x0D, 0x49, 0x0A, 0x68, 0x42, 0xF4, 0x00, 0x72, +0x0A, 0x60, 0x01, 0x24, 0x9C, 0x70, 0x30, 0xBC, 0x70, 0x47, 0x01, 0x2C, 0xFA, 0xD1, 0x88, 0x42, 0xF8, 0xDA, 0x2A, 0x44, +0x91, 0x42, 0xF5, 0xDD, 0x05, 0x49, 0x0A, 0x68, 0x00, 0x24, 0x22, 0xF4, 0x00, 0x72, 0x0A, 0x60, 0x9C, 0x70, 0x30, 0xBC, +0x70, 0x47, 0x70, 0x47, 0xA4, 0x1F, 0x17, 0x00, 0xB0, 0xB3, 0x33, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0C, 0x46, 0x06, 0x46, +0x80, 0x68, 0x91, 0xF8, 0x8B, 0x10, 0xD0, 0xF8, 0x08, 0x80, 0x60, 0x6F, 0xB6, 0xF8, 0x1C, 0xB0, 0xDF, 0xF8, 0x1C, 0xA1, +0x87, 0xB0, 0x00, 0x25, 0x05, 0x90, 0x03, 0x92, 0x1F, 0x46, 0x84, 0xF8, 0x78, 0x50, 0x49, 0xB1, 0x94, 0xF8, 0x63, 0x00, +0xDA, 0xF8, 0xC0, 0x31, 0x01, 0x21, 0x98, 0x47, 0xA4, 0xF8, 0x8A, 0x50, 0x84, 0xF8, 0x8C, 0x50, 0x3A, 0x4B, 0x3B, 0x4D, +0x1B, 0x68, 0x22, 0x6F, 0x5B, 0x68, 0x01, 0x21, 0x84, 0xF8, 0x85, 0x10, 0x29, 0x69, 0x5B, 0x1A, 0xD3, 0x42, 0x58, 0xD4, +0x96, 0xF9, 0x2D, 0x10, 0x04, 0x91, 0xE8, 0xF7, 0x35, 0xFB, 0x34, 0x4B, 0x04, 0x99, 0x5B, 0x7C, 0x01, 0x2B, 0x59, 0xD0, +0xDA, 0xF8, 0x9C, 0x31, 0x20, 0x46, 0xAB, 0xF1, 0x24, 0x05, 0x98, 0x47, 0xAD, 0xB2, 0x00, 0x22, 0x04, 0x21, 0x08, 0xF1, +0x20, 0x00, 0x0A, 0xF0, 0x19, 0xFC, 0x00, 0x23, 0x01, 0x2D, 0x3B, 0x60, 0x08, 0xF1, 0x24, 0x02, 0x22, 0xD9, 0x04, 0x96, +0x3E, 0x46, 0x27, 0x46, 0x2C, 0x46, 0x09, 0xE0, 0x32, 0x60, 0xC9, 0xF5, 0x7F, 0x42, 0xFE, 0x32, 0x14, 0x44, 0xA4, 0xB2, +0x01, 0x2C, 0x05, 0xEB, 0x09, 0x02, 0x10, 0xD9, 0x92, 0xF8, 0x01, 0x90, 0x15, 0x46, 0x09, 0xF1, 0x01, 0x0C, 0xA4, 0x45, +0x15, 0xF8, 0x02, 0x1B, 0x07, 0xDA, 0x05, 0x29, 0xEA, 0xD0, 0x02, 0x46, 0x49, 0x46, 0x28, 0x46, 0x0A, 0xF0, 0xF4, 0xFB, +0xE5, 0xE7, 0x3C, 0x46, 0x37, 0x46, 0x04, 0x9E, 0x60, 0x67, 0x3B, 0x68, 0x01, 0x93, 0x03, 0x9B, 0x00, 0x93, 0x32, 0x46, +0x59, 0x46, 0x40, 0x46, 0x23, 0x46, 0xDA, 0xF8, 0xD0, 0x51, 0xA8, 0x47, 0x04, 0x20, 0x0A, 0xF0, 0xA1, 0xF8, 0x01, 0x28, +0x04, 0xD0, 0x60, 0x6F, 0x05, 0x9B, 0xC0, 0x1A, 0x18, 0xBF, 0x01, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x22, +0x94, 0xF8, 0x6C, 0x00, 0x11, 0x46, 0xF7, 0xF7, 0x75, 0xF9, 0x00, 0x28, 0x9E, 0xD1, 0x2B, 0x69, 0x23, 0x67, 0x9B, 0xE7, +0x20, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x04, 0x99, 0xA0, 0xE7, 0x00, 0xBF, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, +0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x05, 0x46, 0x0C, 0x46, 0x02, 0x23, 0x0C, 0x21, +0x59, 0x20, 0x09, 0xF0, 0xD3, 0xFD, 0x05, 0x70, 0x44, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0xF0, 0xFD, 0xBD, 0x00, 0xBF, +0x08, 0xB5, 0x03, 0x4B, 0x08, 0x46, 0xD3, 0xF8, 0x74, 0x31, 0x98, 0x47, 0x01, 0x20, 0x08, 0xBD, 0x88, 0x1A, 0x17, 0x00, +0x08, 0xB5, 0x04, 0x4A, 0x08, 0x78, 0xD2, 0xF8, 0x5C, 0x22, 0x19, 0x46, 0x90, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, +0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x46, 0x2F, 0x20, 0x19, 0x46, 0x02, 0x23, 0x34, 0x78, 0x09, 0xF0, 0xAE, 0xFD, +0x0D, 0x49, 0x76, 0x78, 0x0D, 0x4B, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x46, 0x07, 0xFB, 0x04, 0x10, 0x29, 0x46, 0x90, 0xF8, +0x65, 0x20, 0x80, 0xF8, 0x66, 0x60, 0x01, 0xF8, 0x01, 0x2F, 0x7F, 0x22, 0xD3, 0xF8, 0x40, 0x33, 0x80, 0xF8, 0x65, 0x20, +0x2A, 0x46, 0x98, 0x47, 0x28, 0x46, 0x09, 0xF0, 0xC5, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x03, 0x23, 0x01, 0x46, 0x0B, 0x20, 0x09, 0xF0, 0x86, 0xFD, +0x06, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xC4, 0x31, 0xA2, 0x1C, 0x61, 0x1C, 0x28, 0x46, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, +0x09, 0xF0, 0xAA, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x0E, 0x4E, 0x0D, 0x46, 0x1C, 0x46, +0x19, 0x46, 0x28, 0x46, 0xD6, 0xF8, 0x80, 0x30, 0x17, 0x46, 0x98, 0x47, 0x0C, 0xB9, 0x00, 0x20, 0xF8, 0xBD, 0x06, 0x46, +0x3A, 0x46, 0x21, 0x46, 0x03, 0x23, 0x47, 0x20, 0x09, 0xF0, 0x62, 0xFD, 0x2A, 0x78, 0x02, 0x70, 0x04, 0x22, 0x46, 0x70, +0x82, 0x70, 0x09, 0xF0, 0x8B, 0xFD, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0C, 0x46, +0x76, 0x20, 0x19, 0x46, 0x0C, 0x23, 0x09, 0xF0, 0x4F, 0xFD, 0x23, 0x78, 0x0C, 0x4A, 0x0D, 0x4C, 0x4F, 0xF4, 0x1E, 0x71, +0x01, 0xFB, 0x03, 0x23, 0x4F, 0xF4, 0xA4, 0x65, 0x93, 0xF8, 0x22, 0x20, 0xD3, 0xF8, 0x48, 0x11, 0x05, 0xFB, 0x02, 0x42, +0x49, 0x69, 0x92, 0xF8, 0x86, 0x20, 0x02, 0x72, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x14, 0x09, 0xF0, 0x67, 0xFD, 0x20, 0x46, +0x38, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x85, 0xB0, +0x01, 0x23, 0x0C, 0x21, 0x53, 0x20, 0x09, 0xF0, 0x27, 0xFD, 0x01, 0x22, 0x02, 0x70, 0x04, 0x46, 0x28, 0x78, 0x04, 0x28, +0x28, 0xD8, 0x1D, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x03, 0xB3, 0xAB, 0x78, +0x23, 0xB3, 0x19, 0x4A, 0x19, 0x49, 0x16, 0x68, 0x09, 0x69, 0x17, 0x68, 0xB0, 0xF8, 0xD2, 0x20, 0xC9, 0x1B, 0x92, 0x02, +0xEF, 0x68, 0xB6, 0xFB, 0xF2, 0xF6, 0x06, 0xFB, 0x02, 0x22, 0x14, 0x4E, 0x39, 0x44, 0x6F, 0x68, 0xD6, 0xF8, 0x04, 0x62, +0x01, 0x97, 0x0A, 0x44, 0xA9, 0x68, 0x00, 0x91, 0x02, 0x92, 0xEA, 0x78, 0x00, 0x21, 0xB0, 0x47, 0xFF, 0x28, 0x01, 0xD0, +0x00, 0x23, 0x23, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x25, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x08, 0x4B, 0x69, 0x78, +0xD3, 0xF8, 0x08, 0x32, 0x98, 0x47, 0x20, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x19, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, +0x18, 0x88, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, +0x05, 0x20, 0x1C, 0x23, 0x09, 0xF0, 0xD8, 0xFC, 0x2C, 0x4D, 0x2D, 0x4B, 0x03, 0x60, 0x2A, 0x68, 0x2C, 0x4B, 0x42, 0x60, +0x1B, 0x68, 0x83, 0x60, 0x0A, 0x22, 0x04, 0x23, 0x83, 0x76, 0x02, 0x83, 0x04, 0x46, 0x00, 0xF1, 0x10, 0x01, 0x0C, 0x30, +0xE8, 0xF7, 0x9E, 0xF8, 0x26, 0x4B, 0x63, 0x61, 0x2B, 0x68, 0x98, 0x03, 0x24, 0xD4, 0x21, 0x4B, 0x1B, 0x68, 0x99, 0x03, +0x2C, 0xD4, 0x1F, 0x4B, 0x1B, 0x68, 0x9A, 0x04, 0x03, 0xD5, 0x63, 0x69, 0x43, 0xF4, 0x00, 0x23, 0x63, 0x61, 0xE8, 0xF7, +0x2F, 0xF9, 0x18, 0xB1, 0x63, 0x69, 0x43, 0xF4, 0x80, 0x33, 0x63, 0x61, 0x17, 0x4B, 0x1B, 0x68, 0x1B, 0x04, 0x22, 0xD4, +0xE8, 0xF7, 0x2E, 0xF9, 0x63, 0x69, 0x08, 0xB1, 0x43, 0xF0, 0x80, 0x63, 0x43, 0xF0, 0x40, 0x53, 0x20, 0x46, 0x63, 0x61, +0x09, 0xF0, 0xCE, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0xE8, 0xF7, 0x3E, 0xF9, 0x00, 0x28, 0xD6, 0xD0, 0x63, 0x69, 0x43, 0xF4, +0x00, 0x33, 0x63, 0x61, 0x0A, 0x4B, 0x1B, 0x68, 0x99, 0x03, 0xD2, 0xD5, 0xE8, 0xF7, 0x3A, 0xF9, 0x00, 0x28, 0xCE, 0xD0, +0x63, 0x69, 0x43, 0xF4, 0x00, 0x13, 0x63, 0x61, 0xC9, 0xE7, 0xE8, 0xF7, 0x03, 0xF9, 0x00, 0x28, 0xD8, 0xD0, 0x63, 0x69, +0x43, 0xF0, 0x80, 0x43, 0x63, 0x61, 0xD3, 0xE7, 0x04, 0x00, 0x32, 0x40, 0x01, 0x03, 0x04, 0x06, 0x08, 0x00, 0x32, 0x40, +0x5F, 0xFA, 0x10, 0x00, 0xF0, 0xB5, 0x23, 0x48, 0x4D, 0x79, 0x00, 0x68, 0x8C, 0x79, 0x50, 0xF8, 0x25, 0xC0, 0x21, 0x4F, +0x0E, 0x68, 0x4F, 0xF4, 0xA4, 0x70, 0x00, 0xFB, 0x04, 0x50, 0x02, 0x30, 0x83, 0xB0, 0x47, 0xF8, 0x20, 0x60, 0x19, 0x46, +0xBC, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, 0xCC, 0xF3, 0x0B, 0x03, 0x1B, 0xBB, 0x2C, 0xF4, 0x7F, 0x6C, 0x2C, 0xF0, 0x0F, 0x0C, +0xC6, 0xF3, 0x0B, 0x06, 0x4C, 0xEA, 0x06, 0x06, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x74, 0x94, 0xF8, 0x64, 0x30, +0x73, 0xB1, 0x01, 0x2D, 0x1A, 0xD0, 0x02, 0x2D, 0x12, 0xD0, 0xA5, 0xB1, 0x0F, 0x4B, 0x1E, 0x60, 0x0F, 0x4B, 0xD3, 0xF8, +0xA0, 0x31, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x1B, 0x20, 0x09, 0xF0, 0xA5, 0xFC, 0x00, 0x20, +0x03, 0xB0, 0xF0, 0xBD, 0x66, 0x46, 0xE1, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xEC, 0xE7, 0x08, 0x4B, 0x1E, 0x60, 0xE9, 0xE7, +0x07, 0x4B, 0x1E, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0xAC, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, +0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x48, +0x8C, 0x78, 0x0D, 0x88, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x04, 0x19, 0x46, 0x70, 0x20, 0xA4, 0xF8, 0xBE, 0x54, +0x09, 0xF0, 0x7A, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x10, 0xB5, 0x08, 0x4C, 0x08, 0x78, 0xD4, 0xF8, +0xC8, 0x41, 0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x0D, 0x20, 0x09, 0xF0, 0x68, 0xFC, +0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x08, 0x78, 0x64, 0x6D, +0x82, 0xB0, 0x01, 0x92, 0x00, 0x93, 0xA0, 0x47, 0xDD, 0xE9, 0x00, 0x12, 0x3A, 0x20, 0x09, 0xF0, 0x55, 0xFC, 0x00, 0x20, +0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x78, 0x08, 0x46, 0x19, 0x46, 0x24, 0xB1, 0x25, 0x4B, +0x93, 0xF8, 0xA9, 0x30, 0x00, 0x2B, 0x36, 0xD1, 0x23, 0x4B, 0x24, 0x4E, 0x24, 0x4D, 0x00, 0x24, 0x1C, 0x70, 0x34, 0x68, +0x24, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x24, 0xF0, 0x10, 0x04, 0x6C, 0x67, 0x1E, 0x4D, 0x2C, 0x68, 0x24, 0xF4, +0x00, 0x64, 0x2C, 0x60, 0xC4, 0x78, 0x9C, 0x70, 0x84, 0x78, 0x00, 0x25, 0x5D, 0x70, 0xC4, 0xB1, 0x1A, 0x4C, 0x23, 0x68, +0x43, 0xF0, 0x00, 0x43, 0x23, 0x60, 0x03, 0x79, 0x63, 0xB1, 0x18, 0x4C, 0x85, 0x68, 0x18, 0x4B, 0x25, 0x60, 0x1C, 0x68, +0xC4, 0xF3, 0x13, 0x04, 0x1C, 0x60, 0xC4, 0x68, 0x18, 0x68, 0x40, 0xEA, 0x04, 0x50, 0x18, 0x60, 0x66, 0x20, 0x09, 0xF0, +0x17, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x0E, 0x4C, 0x23, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x23, 0x60, 0xE5, 0xE7, 0x08, 0x4B, +0x08, 0x4E, 0x09, 0x4D, 0x01, 0x24, 0x1C, 0x70, 0x34, 0x68, 0x44, 0xF0, 0x00, 0x74, 0x34, 0x60, 0x6C, 0x6F, 0x44, 0xF0, +0x10, 0x04, 0x6C, 0x67, 0xC7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0xE0, 0x50, 0x34, 0x40, +0x00, 0x00, 0x50, 0x40, 0x48, 0x30, 0x34, 0x40, 0xF4, 0x00, 0x60, 0x40, 0xF8, 0x00, 0x60, 0x40, 0x70, 0xB5, 0x08, 0x46, +0x07, 0x4C, 0x09, 0x68, 0x46, 0x68, 0x05, 0x89, 0xC4, 0xF8, 0xBD, 0x10, 0x78, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC1, 0x60, +0xA4, 0xF8, 0xC5, 0x50, 0x09, 0xF0, 0xE2, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x2C, 0x19, 0x17, 0x00, 0x38, 0xB5, 0x08, 0x46, +0x0E, 0x49, 0x44, 0x78, 0x0C, 0x70, 0x84, 0x78, 0x4C, 0x70, 0xC4, 0x78, 0x8C, 0x70, 0x0C, 0x4C, 0x05, 0x79, 0x41, 0x79, +0x61, 0x70, 0x25, 0x70, 0xC1, 0x79, 0x85, 0x79, 0xA5, 0x70, 0xE1, 0x70, 0x08, 0x4C, 0x41, 0x68, 0x05, 0x68, 0xC4, 0xF8, +0xCB, 0x10, 0x7A, 0x20, 0x19, 0x46, 0xC4, 0xF8, 0xC7, 0x50, 0x09, 0xF0, 0xC1, 0xFB, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, +0x68, 0x25, 0x17, 0x00, 0x6C, 0x25, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x48, 0x09, 0x68, 0x01, 0x60, +0x19, 0x46, 0x72, 0x20, 0x09, 0xF0, 0xB0, 0xFB, 0x00, 0x20, 0x08, 0xBD, 0x34, 0x00, 0x32, 0x40, 0x30, 0xB5, 0x19, 0x46, +0x83, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x16, 0x4C, +0x16, 0x4D, 0x23, 0x68, 0x01, 0x33, 0xCD, 0xE9, 0x00, 0x21, 0x23, 0x60, 0x08, 0xF0, 0x12, 0xFA, 0xE7, 0xF7, 0x96, 0xFF, +0x09, 0xF0, 0x02, 0xFB, 0x0E, 0xF0, 0x22, 0xF8, 0xD5, 0xF8, 0x10, 0x34, 0x98, 0x47, 0xD5, 0xF8, 0xA8, 0x31, 0x98, 0x47, +0x23, 0x68, 0xDD, 0xE9, 0x00, 0x21, 0x33, 0xB1, 0x08, 0x48, 0x01, 0x3B, 0x00, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x00, 0xB1, +0x62, 0xB6, 0x01, 0x20, 0x09, 0xF0, 0x7E, 0xFB, 0x00, 0x21, 0x08, 0x46, 0x09, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x03, 0xB0, +0x30, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x18, 0x46, +0x21, 0x4E, 0x02, 0x23, 0x0D, 0x46, 0x01, 0x46, 0x25, 0x20, 0x09, 0xF0, 0xFF, 0xFA, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x1C, 0x4B, 0x28, 0x46, 0xD3, 0xF8, 0xB8, 0x31, 0x98, 0x47, 0x00, 0x25, 0x60, 0x70, +0x25, 0x70, 0x20, 0x46, 0x09, 0xF0, 0x1E, 0xFB, 0x28, 0x46, 0x70, 0xBD, 0x2B, 0x78, 0x05, 0x2B, 0x19, 0xD8, 0x2B, 0x79, +0x20, 0x2B, 0x0A, 0xD8, 0x95, 0xF8, 0x28, 0x30, 0x05, 0x2B, 0xE8, 0xD9, 0x11, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xFB, 0x62, +0x0B, 0xF0, 0xBE, 0xFB, 0xE1, 0xE7, 0x0E, 0x49, 0x0F, 0x48, 0x4F, 0xF4, 0xDF, 0x62, 0x0B, 0xF0, 0xB7, 0xFB, 0x33, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE9, 0xDB, 0xD5, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0xF2, 0x62, 0x0B, 0xF0, +0xAB, 0xFB, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDB, 0xC9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xE4, 0x9B, 0x15, 0x00, 0xBC, 0x9B, 0x15, 0x00, 0x90, 0x9B, 0x15, 0x00, +0x11, 0x48, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x70, 0xB5, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x0B, 0xDB, +0x20, 0x78, 0x0D, 0x4B, 0xD3, 0xF8, 0xB4, 0x31, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x27, 0x20, 0x09, 0xF0, 0x0A, 0xFB, +0x00, 0x20, 0x70, 0xBD, 0x08, 0x4B, 0x08, 0x78, 0x1B, 0x68, 0x1B, 0x0E, 0x09, 0x33, 0x98, 0x42, 0xED, 0xDD, 0x06, 0x49, +0x06, 0x48, 0x40, 0xF2, 0x22, 0x72, 0x0B, 0xF0, 0x75, 0xFB, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xD8, 0x00, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x14, 0x9C, 0x15, 0x00, 0x16, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x68, +0x15, 0x4F, 0x0C, 0x46, 0xB0, 0xF9, 0x00, 0x10, 0x25, 0x78, 0x00, 0x29, 0x16, 0x46, 0x98, 0x46, 0x11, 0xDB, 0x4F, 0xF4, +0xA4, 0x60, 0x00, 0xFB, 0x05, 0x70, 0x62, 0x88, 0xA0, 0xF8, 0x68, 0x20, 0x23, 0x79, 0x80, 0xF8, 0x6A, 0x30, 0x32, 0x46, +0x41, 0x46, 0x4C, 0x20, 0x09, 0xF0, 0xD4, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, +0x05, 0x72, 0x92, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xE5, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF6, 0x5B, 0x22, 0x0B, 0xF0, +0x3D, 0xFB, 0xDE, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, +0x13, 0x4B, 0x70, 0xB5, 0x1B, 0x68, 0x0C, 0x78, 0xB3, 0xF9, 0x00, 0x30, 0x11, 0x4E, 0x00, 0x2B, 0x0D, 0x46, 0x0D, 0xDB, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x6A, 0x78, 0x83, 0xF8, 0x87, 0x20, 0xAA, 0x78, 0x83, 0xF8, 0x88, 0x20, +0x00, 0x20, 0x83, 0xF8, 0x89, 0x00, 0x70, 0xBD, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x63, 0x93, 0xF8, 0x62, 0x30, +0x00, 0x2B, 0xE9, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x78, 0x52, 0x0B, 0xF0, 0x0E, 0xFB, 0xE2, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x20, 0x48, 0x2D, 0xE9, +0xF0, 0x41, 0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x84, 0xB0, 0x0E, 0x46, 0x15, 0x46, 0x98, 0x46, 0x29, 0xDB, +0x30, 0x46, 0xE7, 0xF7, 0xAB, 0xFD, 0x00, 0x24, 0x19, 0x4F, 0x00, 0x94, 0x40, 0xF6, 0xB4, 0x13, 0x21, 0x46, 0x1A, 0x46, +0x20, 0x46, 0xCD, 0xE9, 0x01, 0x44, 0xE7, 0xF7, 0xEB, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, 0x0F, 0x20, 0x98, 0x47, 0x13, 0x4B, +0xB6, 0xF8, 0x44, 0x20, 0x9A, 0x83, 0x41, 0x46, 0x2A, 0x46, 0x03, 0x20, 0x09, 0xF0, 0x62, 0xFA, 0xD7, 0xF8, 0x60, 0x31, +0x98, 0x47, 0xD7, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x09, 0xF0, 0xEA, 0xFB, 0x20, 0x46, 0x04, 0xB0, +0xBD, 0xE8, 0xF0, 0x81, 0x10, 0x46, 0x09, 0xF0, 0x8B, 0xFC, 0x00, 0x28, 0xD0, 0xD0, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, +0xA7, 0x72, 0x0B, 0xF0, 0xC3, 0xFA, 0xC9, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x58, 0x9C, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x49, 0x78, 0x16, 0x46, 0x1D, 0x46, 0xE1, 0xB1, +0x01, 0x29, 0x63, 0x88, 0x3C, 0xD0, 0x02, 0x29, 0x32, 0xD0, 0x03, 0x29, 0x0C, 0xBF, 0x20, 0x48, 0x20, 0x48, 0xA2, 0x88, +0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, 0x49, 0xFD, 0xE3, 0x88, 0x23, 0xB1, 0x1D, 0x4B, 0x20, 0x78, 0xD3, 0xF8, +0x80, 0x34, 0x98, 0x47, 0x32, 0x46, 0x29, 0x46, 0x68, 0x20, 0x09, 0xF0, 0x1D, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x04, 0xF1, +0x08, 0x01, 0x4F, 0xF4, 0x40, 0x72, 0x16, 0x48, 0x1D, 0xF0, 0x34, 0xFD, 0x04, 0xF5, 0x42, 0x71, 0x4F, 0xF4, 0x00, 0x72, +0x13, 0x48, 0x1D, 0xF0, 0x2D, 0xFD, 0x04, 0xF5, 0xA1, 0x61, 0x80, 0x22, 0x0C, 0x48, 0x1D, 0xF0, 0x27, 0xFD, 0x40, 0x22, +0x04, 0xF5, 0xB1, 0x61, 0x0A, 0x48, 0x1D, 0xF0, 0x21, 0xFD, 0xD6, 0xE7, 0x0B, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, +0x08, 0x01, 0x1D, 0xF0, 0x19, 0xFD, 0xCE, 0xE7, 0x06, 0x48, 0xA2, 0x88, 0x18, 0x44, 0x04, 0xF1, 0x08, 0x01, 0x1D, 0xF0, +0x11, 0xFD, 0xC6, 0xE7, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, +0x1C, 0x16, 0x17, 0x00, 0x38, 0xB5, 0x19, 0x46, 0x81, 0x20, 0x40, 0x23, 0x09, 0xF0, 0x78, 0xF9, 0x00, 0x25, 0x04, 0x46, +0x08, 0x49, 0x00, 0xF8, 0x01, 0x5B, 0x24, 0x22, 0x1D, 0xF0, 0xF8, 0xFC, 0x23, 0x78, 0x24, 0x33, 0xDB, 0xB2, 0xE2, 0x18, +0x23, 0x70, 0x20, 0x46, 0x55, 0x70, 0x09, 0xF0, 0x97, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0x00, 0xBF, 0xDC, 0xD1, 0x15, 0x00, +0x10, 0xB5, 0x82, 0xB0, 0x08, 0x46, 0x1C, 0x46, 0x01, 0x92, 0xFA, 0xF7, 0x83, 0xFA, 0x06, 0x49, 0x4F, 0xF4, 0x80, 0x70, +0x0B, 0xF0, 0x0E, 0xF8, 0x01, 0x9A, 0x21, 0x46, 0x6C, 0x20, 0x09, 0xF0, 0xB9, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, +0x7C, 0x9C, 0x15, 0x00, 0x25, 0x48, 0x2D, 0xE9, 0xF8, 0x43, 0x00, 0x68, 0xDF, 0xF8, 0xA0, 0x90, 0x0C, 0x46, 0xB0, 0xF9, +0x00, 0x10, 0x65, 0x79, 0x00, 0x29, 0x17, 0x46, 0x1E, 0x46, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0xF0, +0x09, 0xEB, 0x00, 0x08, 0x21, 0x79, 0x98, 0xF8, 0xAC, 0x20, 0x23, 0x68, 0xC8, 0xF8, 0xC4, 0x34, 0x01, 0x2A, 0x88, 0xF8, +0xC3, 0x14, 0x0A, 0xD1, 0x17, 0x4B, 0xB0, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x48, 0x44, 0x98, 0x47, 0x00, 0x22, 0xD8, 0xF8, +0xC4, 0x34, 0x88, 0xF8, 0xAC, 0x20, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0x95, 0x11, 0x49, 0x95, 0xF8, 0xC3, 0x24, +0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0xD0, 0xFF, 0x3A, 0x46, 0x31, 0x46, 0x62, 0x20, 0x09, 0xF0, 0x7B, 0xF9, 0x00, 0x20, +0xBD, 0xE8, 0xF8, 0x83, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x93, 0x93, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xC9, 0xD0, +0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0x27, 0x62, 0x0B, 0xF0, 0xE4, 0xF9, 0xC2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x8C, 0x9C, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, +0x00, 0xB5, 0x83, 0xB0, 0x08, 0x46, 0x01, 0x92, 0x00, 0x93, 0xFA, 0xF7, 0x45, 0xFA, 0xDD, 0xE9, 0x00, 0x12, 0x6E, 0x20, +0x09, 0xF0, 0x50, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0xF0, 0xB5, 0x0C, 0x46, 0x0E, 0x78, 0x60, 0x78, +0x89, 0x78, 0x83, 0xB0, 0x1D, 0x46, 0x01, 0x92, 0x9E, 0xB9, 0xFE, 0xF7, 0xD5, 0xFE, 0x01, 0x9A, 0x00, 0xBB, 0x03, 0x26, +0x29, 0x46, 0x03, 0x23, 0x2B, 0x20, 0x09, 0xF0, 0xD1, 0xF8, 0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x86, 0x70, +0x09, 0xF0, 0xFA, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0xFE, 0xF7, 0xD1, 0xFE, 0x01, 0x9A, 0x00, 0x28, 0xEA, 0xD0, +0x60, 0x78, 0x14, 0x4B, 0xA1, 0x78, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x00, 0x30, 0x15, 0xF0, 0x9D, 0xFC, 0x02, 0x26, +0x01, 0x9A, 0xDF, 0xE7, 0x61, 0x78, 0x94, 0xF8, 0x02, 0xC0, 0x0D, 0x48, 0x0D, 0x4F, 0x01, 0xEB, 0x81, 0x03, 0xC1, 0xEB, +0x03, 0x13, 0x63, 0x44, 0x00, 0xEB, 0xC3, 0x03, 0x4F, 0xF0, 0x9E, 0x0E, 0x93, 0xF8, 0xA5, 0x31, 0x0E, 0xFB, 0x01, 0xC1, +0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x81, 0x01, 0x07, 0xEB, 0xC3, 0x03, 0x81, 0xF8, 0x5A, 0x61, 0x1E, 0x81, 0x02, 0x26, +0xC2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x46, 0x02, 0xF0, 0x0C, 0xFA, +0x01, 0x20, 0x08, 0xBD, 0x70, 0xB5, 0x48, 0x78, 0xFF, 0x28, 0x0C, 0x46, 0x16, 0x46, 0x1D, 0x46, 0x01, 0xD0, 0x17, 0xF0, +0xB3, 0xF9, 0x21, 0x78, 0xA0, 0x78, 0x0A, 0x4B, 0x0A, 0x4A, 0x00, 0x39, 0x18, 0xBF, 0x01, 0x21, 0x00, 0x38, 0x18, 0xBF, +0x01, 0x20, 0x18, 0x70, 0x11, 0x70, 0x02, 0x46, 0x06, 0x48, 0x0A, 0xF0, 0xDD, 0xFE, 0x32, 0x46, 0x29, 0x46, 0x64, 0x20, +0x09, 0xF0, 0xD8, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0xB9, 0x34, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, 0x9C, 0x9C, 0x15, 0x00, +0xF8, 0xB5, 0x19, 0x46, 0x74, 0x20, 0x06, 0x23, 0x09, 0xF0, 0x62, 0xF8, 0x4F, 0xF4, 0xD2, 0x77, 0x04, 0x46, 0x3B, 0x68, +0x08, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x06, 0x46, 0x09, 0x20, 0x98, 0x47, 0x36, 0x0C, 0x36, 0x04, 0x56, 0xEA, 0x00, 0x03, +0x1A, 0xD1, 0x3B, 0x68, 0x07, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x05, 0x46, 0x08, 0x20, 0x98, 0x47, 0x83, 0xB2, 0x19, 0x0A, +0x28, 0x0A, 0x2A, 0x0C, 0x63, 0x70, 0x2B, 0x0E, 0x21, 0x70, 0x20, 0x71, 0xE2, 0x70, 0xA3, 0x70, 0xEA, 0xB2, 0x07, 0x48, +0x65, 0x71, 0x0A, 0xF0, 0xA5, 0xFE, 0x20, 0x46, 0x09, 0xF0, 0x6A, 0xF8, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x04, 0x45, 0xEA, +0x16, 0x45, 0x03, 0x0C, 0xE7, 0xE7, 0x00, 0xBF, 0xC0, 0x9C, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x46, 0x48, 0x7A, +0x09, 0x7A, 0x16, 0x46, 0xE2, 0x88, 0x84, 0xB0, 0xCD, 0xE9, 0x00, 0x21, 0x02, 0x90, 0x62, 0x88, 0x5E, 0x48, 0x21, 0x88, +0x1D, 0x46, 0xA3, 0x88, 0x0A, 0xF0, 0x86, 0xFE, 0xB4, 0xF8, 0x00, 0xC0, 0x67, 0x88, 0xA0, 0x88, 0xE2, 0x88, 0x5A, 0x4B, +0xBC, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x9E, 0x80, 0x19, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0x0B, 0x68, 0xDF, 0xF8, 0x6C, 0xE1, +0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, 0x0C, 0x33, 0x0B, 0x60, 0xDE, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x08, 0x03, 0x43, 0xEA, +0x0C, 0x33, 0xCE, 0xF8, 0x00, 0x30, 0x00, 0x2F, 0x79, 0xD0, 0x4B, 0x68, 0xDF, 0xF8, 0x44, 0xE1, 0xDF, 0xF8, 0x48, 0xC1, +0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, 0x07, 0x33, 0x4B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, +0x07, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x28, 0x3F, 0xD0, 0x8F, 0x68, 0xDF, 0xF8, 0x1C, 0xE1, 0xDF, 0xF8, 0x14, 0xC1, +0x07, 0xEA, 0x0E, 0x07, 0x47, 0xEA, 0x00, 0x37, 0x8F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0x43, 0xEA, +0x00, 0x33, 0xCC, 0xF8, 0x00, 0x30, 0x00, 0x2A, 0x38, 0xD0, 0xC8, 0x68, 0xDF, 0xF8, 0xF4, 0xC0, 0x38, 0x4F, 0x00, 0xEA, +0x0C, 0x00, 0x40, 0xEA, 0x02, 0x30, 0xC8, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x43, 0xEA, 0x02, 0x33, 0x3B, 0x60, +0x23, 0x7A, 0x33, 0x4A, 0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x2F, 0x4A, +0x00, 0x2B, 0x31, 0xD0, 0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0x2C, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, +0x32, 0x46, 0x29, 0x46, 0x7F, 0x20, 0x09, 0xF0, 0x17, 0xF8, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x88, 0x68, +0xDF, 0xF8, 0x9C, 0xC0, 0x25, 0x4F, 0x00, 0xEA, 0x0C, 0x00, 0x88, 0x60, 0x3B, 0x68, 0x03, 0xEA, 0x0C, 0x03, 0x3B, 0x60, +0x00, 0x2A, 0xC6, 0xD1, 0xCA, 0x68, 0x21, 0x4F, 0x1C, 0x48, 0x3A, 0x40, 0xCA, 0x60, 0x03, 0x68, 0x1B, 0x4A, 0x3B, 0x40, +0x03, 0x60, 0x23, 0x7A, 0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x63, 0x7A, 0x16, 0x4A, +0x00, 0x2B, 0xCD, 0xD1, 0x13, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xCC, 0xE7, 0x4F, 0x68, 0xDF, 0xF8, 0x50, 0xE0, +0xDF, 0xF8, 0x54, 0xC0, 0x07, 0xEA, 0x0E, 0x07, 0x4F, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, +0x00, 0x30, 0x88, 0xE7, 0x19, 0x68, 0xDF, 0xF8, 0x34, 0xE0, 0x0B, 0x68, 0xDF, 0xF8, 0x30, 0xC0, 0x03, 0xEA, 0x0E, 0x03, +0x0B, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x03, 0xEA, 0x0E, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x64, 0xE7, 0xD8, 0x9C, 0x15, 0x00, +0xAC, 0x35, 0x17, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x24, 0x02, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x08, 0x02, 0x32, 0x40, +0xFF, 0x0F, 0x00, 0xF0, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8A, 0x46, 0x83, 0xB0, +0x49, 0x7C, 0x28, 0x48, 0xDF, 0xF8, 0xBC, 0x90, 0x27, 0x4F, 0x16, 0x46, 0xDA, 0xF8, 0x0C, 0x20, 0x00, 0x92, 0x01, 0x91, +0x9A, 0xF8, 0x10, 0xB0, 0xDA, 0xF8, 0x00, 0x10, 0x1D, 0x46, 0xDA, 0xE9, 0x01, 0x23, 0x0A, 0xF0, 0xA5, 0xFD, 0x21, 0x4A, +0x21, 0x49, 0x9A, 0xF8, 0x11, 0x00, 0x82, 0xF8, 0x05, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0B, 0xF3, 0x03, 0xF1, +0x08, 0x02, 0x01, 0xEB, 0x02, 0x08, 0x01, 0xEB, 0x03, 0x0B, 0xAA, 0xF1, 0x04, 0x0A, 0x00, 0x24, 0x5A, 0xF8, 0x04, 0x0F, +0xE3, 0xB2, 0x90, 0xB1, 0x48, 0xF8, 0x24, 0x00, 0x16, 0x4A, 0x9B, 0xF8, 0x64, 0x10, 0x12, 0x68, 0x42, 0xF8, 0x24, 0x00, +0x49, 0xB1, 0x01, 0x2C, 0x13, 0xD0, 0x02, 0x2B, 0x17, 0xD0, 0x9B, 0xB1, 0x38, 0x60, 0x11, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, +0x98, 0x47, 0x01, 0x34, 0x04, 0x2C, 0xE5, 0xD1, 0x32, 0x46, 0x29, 0x46, 0x83, 0x20, 0x08, 0xF0, 0x73, 0xFF, 0x00, 0x20, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC9, 0xF8, 0x00, 0x00, 0xEC, 0xE7, 0x08, 0x4B, 0x18, 0x60, 0xE9, 0xE7, 0x08, 0x4B, +0x18, 0x60, 0xE6, 0xE7, 0x18, 0x9D, 0x15, 0x00, 0x0C, 0x02, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0xAC, 0x35, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, +0xF8, 0xB5, 0x7C, 0x20, 0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0xE5, 0xFE, 0x23, 0x78, 0x05, 0x46, 0x00, 0x2B, +0x5F, 0xD0, 0x35, 0x48, 0x0A, 0xF0, 0x46, 0xFD, 0x34, 0x4B, 0x1B, 0x68, 0x00, 0x22, 0x1A, 0x70, 0x4F, 0xF4, 0xD2, 0x73, +0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0x68, 0x70, 0x62, 0x78, 0x06, 0x46, 0x00, 0x2A, 0x45, 0xD0, 0x2E, 0x4F, 0xC0, 0xF3, +0x40, 0x11, 0x42, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0x4F, 0xD4, 0x2C, 0x48, 0x0F, 0x22, 0x01, 0x21, 0xE8, 0xF7, 0x1C, 0xFC, +0x02, 0x22, 0x11, 0x46, 0x29, 0x48, 0xE8, 0xF7, 0x17, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x28, 0x48, 0xE8, 0xF7, 0x12, 0xFC, +0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x24, 0x48, 0xE8, 0xF7, 0x0C, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x11, 0x46, 0x22, 0x48, +0xE8, 0xF7, 0x06, 0xFC, 0x02, 0x22, 0x11, 0x46, 0x20, 0x48, 0xE8, 0xF7, 0x01, 0xFC, 0x4F, 0xF4, 0x00, 0x52, 0x00, 0x21, +0x1D, 0x48, 0xE8, 0xF7, 0xFB, 0xFB, 0x97, 0xF8, 0xB4, 0x10, 0x01, 0x22, 0x23, 0x78, 0x6B, 0xB1, 0xE3, 0x78, 0x2B, 0xB1, +0xB7, 0xF8, 0xAA, 0x30, 0x43, 0xF4, 0x80, 0x43, 0xA7, 0xF8, 0xAA, 0x30, 0x16, 0x48, 0xF3, 0xB2, 0x0A, 0xF0, 0xFA, 0xFC, +0x97, 0xF8, 0xB4, 0x10, 0x29, 0x70, 0x28, 0x46, 0x08, 0xF0, 0xBC, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xA3, 0x78, 0x0B, 0x4F, +0xC3, 0xF3, 0x40, 0x11, 0x5B, 0x06, 0x87, 0xF8, 0xB4, 0x10, 0xB8, 0xD5, 0xE0, 0xE7, 0x0D, 0x48, 0x0A, 0xF0, 0xE6, 0xFC, +0x04, 0x4B, 0x1B, 0x68, 0x03, 0x22, 0x1A, 0x70, 0x9E, 0xE7, 0x00, 0x22, 0xD6, 0xE7, 0x00, 0xBF, 0x48, 0x9D, 0x15, 0x00, +0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x04, 0x20, 0x01, 0x50, 0x04, 0x10, 0x01, 0x50, 0x08, 0x10, 0x01, 0x50, +0x00, 0x10, 0x01, 0x50, 0x68, 0x9D, 0x15, 0x00, 0x58, 0x9D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x18, 0x46, 0xB1, 0xB0, +0x0C, 0x46, 0x10, 0x23, 0x01, 0x46, 0x6A, 0x20, 0x04, 0x94, 0x08, 0xF0, 0x59, 0xFE, 0x4F, 0xF4, 0xD2, 0x73, 0x02, 0x46, +0x1B, 0x68, 0x05, 0x92, 0x06, 0x20, 0x98, 0x47, 0x04, 0x46, 0x01, 0x46, 0x91, 0x48, 0x0A, 0xF0, 0xB5, 0xFC, 0x14, 0xF4, +0x7F, 0x4F, 0xC4, 0xF3, 0x07, 0x25, 0x6F, 0xD1, 0x26, 0x0E, 0xE5, 0xB2, 0x6E, 0xD0, 0xF4, 0xB2, 0x00, 0x2D, 0x6F, 0xD1, +0x04, 0x9B, 0x19, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x83, 0x80, 0x00, 0x2E, 0x40, 0xF0, 0x89, 0x80, 0x59, 0x7D, 0x31, 0xB1, +0x86, 0x48, 0x0A, 0xF0, 0x9D, 0xFC, 0x04, 0x9B, 0x5C, 0x7D, 0x00, 0x2C, 0x7F, 0xD1, 0x04, 0x9B, 0xDB, 0x68, 0x00, 0x2B, +0x40, 0xF0, 0x8D, 0x80, 0x04, 0x9B, 0xDF, 0xF8, 0x40, 0xB2, 0x99, 0x68, 0x1A, 0x68, 0x7F, 0x4B, 0xDF, 0xF8, 0x38, 0xA2, +0xD3, 0xF8, 0x70, 0x32, 0x7D, 0x4C, 0xCD, 0xE9, 0x08, 0x21, 0x08, 0xA8, 0x0A, 0xA9, 0x98, 0x47, 0x1A, 0xAE, 0x6F, 0xF0, +0x3F, 0x08, 0x09, 0xAF, 0x0A, 0xAB, 0x07, 0x97, 0xA8, 0xEB, 0x03, 0x08, 0x35, 0x46, 0x0D, 0xF1, 0x78, 0x09, 0x06, 0x96, +0xE3, 0x79, 0x00, 0x93, 0x08, 0xEB, 0x05, 0x02, 0x23, 0x68, 0x03, 0x92, 0x59, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, +0xBD, 0xFC, 0x15, 0xF8, 0x01, 0x6B, 0x57, 0xF8, 0x04, 0x3F, 0x03, 0x9A, 0x00, 0x96, 0x51, 0x46, 0x23, 0x60, 0xE6, 0x71, +0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0xB0, 0xFC, 0x4D, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE3, 0xD1, 0xDF, 0xF8, 0xD8, 0xB1, +0x06, 0x9E, 0x9B, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x52, 0xD1, 0xDF, 0xF8, 0xD0, 0xA1, 0x61, 0x4B, 0x00, 0x20, 0xD3, 0xF8, +0xB0, 0x34, 0x98, 0x47, 0x05, 0x98, 0x5F, 0x4C, 0x5F, 0x4A, 0x60, 0x4B, 0x82, 0x60, 0xC0, 0xE9, 0x00, 0x4A, 0xC3, 0x60, +0x08, 0xF0, 0x0C, 0xFE, 0x00, 0x20, 0x31, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x23, 0x0E, 0x0B, 0xD1, 0x26, 0x0C, 0xF4, 0xB2, +0x00, 0x2D, 0x8F, 0xD0, 0x3C, 0xB9, 0x04, 0x9B, 0x59, 0x7D, 0x00, 0x29, 0x40, 0xF0, 0x99, 0x80, 0x00, 0x24, 0x00, 0xE0, +0xDC, 0xB2, 0x1F, 0x2D, 0x28, 0xBF, 0x1F, 0x25, 0xE9, 0x06, 0x41, 0xEA, 0x85, 0x51, 0x51, 0x4A, 0x51, 0x48, 0xE8, 0xF7, +0x17, 0xFB, 0x51, 0x48, 0x29, 0x46, 0x0A, 0xF0, 0x23, 0xFC, 0x86, 0xE7, 0x4F, 0x48, 0x0A, 0xF0, 0x1F, 0xFC, 0x04, 0x9B, +0x1D, 0x7D, 0x00, 0x2E, 0x70, 0xD0, 0x00, 0x2D, 0xE7, 0xD1, 0x3F, 0x2C, 0x21, 0x46, 0x4B, 0x48, 0x28, 0xBF, 0x3F, 0x21, +0x3F, 0x22, 0x03, 0x91, 0xE8, 0xF7, 0x00, 0xFB, 0x03, 0x99, 0x48, 0x48, 0x0A, 0xF0, 0x0C, 0xFC, 0x04, 0x9B, 0xDB, 0x68, +0x00, 0x2B, 0x3F, 0xF4, 0x73, 0xAF, 0x04, 0x9B, 0x18, 0x69, 0xEB, 0xF7, 0x6F, 0xF8, 0x6D, 0xE7, 0x42, 0x4A, 0x38, 0x4D, +0x93, 0x69, 0xD5, 0xF8, 0x28, 0x42, 0xDF, 0xF8, 0x20, 0xA1, 0x40, 0x4F, 0x43, 0xF0, 0x01, 0x03, 0x93, 0x61, 0x04, 0x9B, +0x5B, 0x68, 0x08, 0x93, 0x41, 0xF2, 0x7C, 0x52, 0x00, 0x23, 0x11, 0x46, 0xCD, 0xE9, 0x00, 0x33, 0x01, 0x20, 0xA0, 0x47, +0x39, 0x4A, 0x01, 0x23, 0x82, 0xF8, 0x2A, 0x30, 0x0A, 0xA9, 0xD5, 0xF8, 0x70, 0x32, 0x37, 0x4D, 0x08, 0xA8, 0x98, 0x47, +0x54, 0x46, 0xCD, 0xF8, 0x10, 0xA0, 0xDD, 0xF8, 0x1C, 0xA0, 0xE3, 0x79, 0x00, 0x93, 0x06, 0xEB, 0x08, 0x02, 0x23, 0x68, +0x03, 0x92, 0x39, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, 0x22, 0xFC, 0x16, 0xF8, 0x01, 0xCB, 0x5A, 0xF8, 0x04, 0x3F, +0x03, 0x9A, 0xCD, 0xF8, 0x00, 0xC0, 0x29, 0x46, 0x23, 0x60, 0x84, 0xF8, 0x07, 0xC0, 0x4F, 0xF4, 0x00, 0x50, 0x0A, 0xF0, +0x13, 0xFC, 0x4E, 0x45, 0x04, 0xF1, 0x10, 0x04, 0xE1, 0xD1, 0x9B, 0xF8, 0xB4, 0x30, 0xDD, 0xF8, 0x10, 0xA0, 0x00, 0x2B, +0x3F, 0xF4, 0x65, 0xAF, 0x13, 0x4B, 0x00, 0x20, 0xD3, 0xF8, 0x80, 0x34, 0x98, 0x47, 0x1D, 0x4B, 0x1E, 0x49, 0x93, 0xF8, +0x2A, 0x20, 0x08, 0x20, 0x00, 0x23, 0x0A, 0xF0, 0xFB, 0xFB, 0x5B, 0xE7, 0x59, 0x7D, 0x1C, 0x46, 0x39, 0xB1, 0x0A, 0x48, +0x0A, 0xF0, 0xA4, 0xFB, 0x64, 0x7D, 0x00, 0x2D, 0x3F, 0xF4, 0x05, 0xAF, 0x6D, 0xE7, 0x00, 0x2D, 0x3F, 0xF4, 0x03, 0xAF, +0x66, 0xE7, 0x04, 0x48, 0x0A, 0xF0, 0x98, 0xFB, 0x04, 0x9B, 0x5C, 0x7D, 0x63, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x15, 0x00, +0xBC, 0x9D, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1C, 0x13, 0x17, 0x00, 0x1C, 0x18, 0x17, 0x00, 0x9C, 0x18, 0x17, 0x00, +0x00, 0x00, 0xC0, 0xFF, 0x04, 0x88, 0x01, 0x50, 0xD0, 0x9D, 0x15, 0x00, 0xAC, 0x9D, 0x15, 0x00, 0x28, 0x91, 0x01, 0x50, +0xE4, 0x9D, 0x15, 0x00, 0x00, 0x80, 0x50, 0x40, 0x44, 0x9E, 0x15, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x64, 0x9E, 0x15, 0x00, +0x9C, 0x77, 0x15, 0x00, 0xFC, 0x9D, 0x15, 0x00, 0x20, 0x9E, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x1C, 0x16, 0x17, 0x00, +0x38, 0xB5, 0x00, 0x22, 0x0D, 0x46, 0x01, 0x23, 0x0C, 0x21, 0x54, 0x20, 0x08, 0xF0, 0xFA, 0xFC, 0x01, 0x23, 0x03, 0x70, +0x04, 0x46, 0x28, 0x78, 0x04, 0x28, 0x0D, 0xD8, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, +0xC0, 0x34, 0x2B, 0xB1, 0x00, 0x23, 0x23, 0x70, 0x69, 0x78, 0x31, 0xB1, 0x06, 0xF0, 0xA2, 0xFB, 0x20, 0x46, 0x08, 0xF0, +0x13, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x06, 0xF0, 0xBD, 0xFB, 0x20, 0x46, 0x08, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x38, 0xBD, +0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x10, 0x46, 0x14, 0x46, 0x0D, 0x46, 0x1E, 0x46, 0x08, 0xF0, 0x73, 0xFF, 0x03, 0x28, +0x25, 0xD0, 0x20, 0x46, 0x08, 0xF0, 0x6E, 0xFF, 0x04, 0x28, 0x20, 0xD0, 0x2A, 0x78, 0x1B, 0x4D, 0x20, 0x46, 0xEA, 0x77, +0x72, 0xB9, 0x08, 0xF0, 0x65, 0xFF, 0x02, 0x28, 0x17, 0xD0, 0x18, 0x4B, 0xD3, 0xF8, 0x60, 0x31, 0x98, 0x47, 0x23, 0x20, +0x22, 0x46, 0x31, 0x46, 0x08, 0xF0, 0x20, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x08, 0xF0, 0x56, 0xFF, 0x58, 0xB1, 0x02, 0x28, +0xF9, 0xD0, 0x10, 0x4B, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0xA3, 0xFE, 0x02, 0x20, +0x70, 0xBD, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0x00, 0x23, 0x6B, 0x82, 0xE0, 0xE7, +0x08, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xF8, 0xD0, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x31, 0x62, 0x0A, 0xF0, 0x76, 0xFD, +0xF1, 0xE7, 0x00, 0xBF, 0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, +0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x1E, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x0E, 0x46, 0x14, 0x46, 0x1C, 0xDB, 0x20, 0x46, 0x08, 0xF0, 0x1C, 0xFF, 0x58, 0xB1, 0x02, 0x28, 0x08, 0xD0, 0x18, 0x4B, +0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x20, 0x46, 0x02, 0x21, 0x08, 0xF0, 0x69, 0xFE, 0x02, 0x20, 0x70, 0xBD, 0x2B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x20, 0x46, 0x03, 0x21, 0x08, 0xF0, 0x5E, 0xFE, 0x33, 0x68, 0x98, 0x47, +0x00, 0x20, 0x70, 0xBD, 0x10, 0x46, 0x08, 0xF0, 0xFF, 0xFE, 0x04, 0x28, 0xDD, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, +0x71, 0x62, 0x0A, 0xF0, 0x37, 0xFD, 0xD6, 0xE7, 0x09, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0xE7, 0xD0, 0x05, 0x49, 0x08, 0x48, +0x4F, 0xF4, 0xCF, 0x62, 0x0A, 0xF0, 0x2C, 0xFD, 0xE0, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xAC, 0x9E, 0x15, 0x00, 0x38, 0x00, 0x32, 0x40, 0x84, 0x9E, 0x15, 0x00, 0x70, 0xB5, 0x12, 0x4C, +0x88, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x40, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x40, 0x1E, 0x46, 0x84, 0xB9, +0x90, 0xF8, 0x6C, 0x00, 0x0C, 0x4D, 0x0C, 0x88, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x51, 0xA4, 0x02, 0x8C, 0x60, +0x31, 0x46, 0x15, 0x20, 0x08, 0xF0, 0x8A, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x06, 0x4C, 0x09, 0x88, 0xD4, 0xF8, +0x60, 0x44, 0x01, 0x92, 0xA0, 0x47, 0x01, 0x9A, 0xF0, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x88, 0x79, 0x19, 0x4D, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x00, 0xF6, +0x06, 0xF1, 0x38, 0x00, 0x28, 0x44, 0x35, 0x44, 0x82, 0xB0, 0x90, 0x46, 0x06, 0x22, 0x1F, 0x46, 0x0C, 0x46, 0x1C, 0xF0, +0x85, 0xFF, 0x95, 0xF8, 0xC0, 0x34, 0x73, 0xB9, 0x10, 0x49, 0x11, 0x4B, 0x20, 0x68, 0xA2, 0x88, 0x08, 0x60, 0x1A, 0x60, +0x42, 0x46, 0x39, 0x46, 0x19, 0x20, 0x08, 0xF0, 0x57, 0xFC, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x0D, 0xF1, +0x07, 0x00, 0xFC, 0xF7, 0x9F, 0xFF, 0x00, 0x28, 0xF0, 0xD1, 0x08, 0x49, 0x08, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, +0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0x02, 0x60, 0xE6, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, +0x24, 0x00, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x0D, 0x46, 0x9E, 0x4F, +0x95, 0xF8, 0x03, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x89, 0xB0, 0x01, 0xFB, 0x0A, 0xFB, 0x07, 0xEB, 0x0B, 0x06, 0x00, 0x24, +0x0D, 0xF1, 0x1F, 0x00, 0x90, 0x46, 0x99, 0x46, 0x8D, 0xF8, 0x1F, 0x40, 0xFC, 0xF7, 0x72, 0xFF, 0x96, 0xF8, 0x62, 0x30, +0xAA, 0x78, 0x86, 0xF8, 0x64, 0x20, 0x04, 0x46, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x96, 0xF8, 0x6C, 0x10, 0x02, 0x91, +0x00, 0x2A, 0x00, 0xF0, 0x45, 0x81, 0x8E, 0x4A, 0x8E, 0x4B, 0x03, 0x92, 0x8C, 0x46, 0x8E, 0x49, 0x18, 0x69, 0xD2, 0xF8, +0xE0, 0x31, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x0C, 0x12, 0x0B, 0xF1, 0x18, 0x01, 0x79, 0x18, 0x04, 0x91, 0x91, 0x68, +0x05, 0x92, 0x41, 0x18, 0x04, 0x98, 0x98, 0x47, 0x05, 0x9A, 0x2B, 0x88, 0x13, 0x84, 0xFC, 0xF7, 0x39, 0xFF, 0x05, 0x9A, +0x96, 0xF8, 0xC0, 0x14, 0x01, 0x94, 0x13, 0x8C, 0x92, 0xF8, 0x23, 0x20, 0x00, 0x91, 0x4F, 0xF4, 0x80, 0x70, 0x7F, 0x49, +0x0A, 0xF0, 0x3C, 0xFA, 0x96, 0xF8, 0xC0, 0x34, 0x33, 0xB9, 0x7D, 0x4A, 0x29, 0x88, 0x13, 0x68, 0x9B, 0xB2, 0x43, 0xEA, +0x01, 0x43, 0x13, 0x60, 0x7A, 0x4B, 0x1B, 0x68, 0x18, 0x04, 0x00, 0xF1, 0xD2, 0x81, 0x79, 0x49, 0x79, 0x4B, 0xB1, 0xF8, +0x1C, 0xC0, 0x02, 0x99, 0x08, 0x46, 0x72, 0x49, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x12, 0x4F, 0xF4, 0xA4, 0x6B, +0x90, 0x68, 0x02, 0x92, 0x0B, 0xFB, 0x0A, 0x7B, 0x0C, 0xF1, 0x14, 0x0C, 0x00, 0xFB, 0x0C, 0xFC, 0xA3, 0xFB, 0x0C, 0x3C, +0xDB, 0xF8, 0x04, 0x00, 0x4F, 0xEA, 0x9C, 0x4C, 0x00, 0x23, 0xA2, 0xF8, 0x1E, 0xC0, 0x40, 0xF0, 0x01, 0x00, 0xDF, 0xF8, +0x90, 0xC1, 0xAB, 0xF8, 0x68, 0x30, 0x8B, 0xF8, 0x6A, 0x30, 0x8B, 0xF8, 0x8C, 0x30, 0x8B, 0xF8, 0x78, 0x30, 0xCB, 0xF8, +0x74, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0xDC, 0xF8, 0x10, 0x00, 0xCB, 0xF8, 0x70, 0x00, 0x30, 0x46, 0x04, 0xF0, 0xF4, 0xFA, +0x9B, 0xF8, 0xC0, 0x04, 0x5D, 0x49, 0x00, 0x23, 0x00, 0x28, 0x40, 0xF0, 0x76, 0x81, 0x5D, 0x4B, 0x02, 0x9A, 0x9B, 0x7C, +0x00, 0x2B, 0x40, 0xF0, 0x8B, 0x81, 0x00, 0x2C, 0x40, 0xF0, 0xD5, 0x81, 0xDF, 0xF8, 0x7C, 0xB1, 0xDB, 0xF8, 0x20, 0x30, +0x00, 0x2B, 0x40, 0xF0, 0x81, 0x81, 0x9D, 0xF8, 0x1F, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x87, 0x82, 0x53, 0x49, 0x93, 0x68, +0x0A, 0x68, 0xCB, 0xF8, 0x20, 0x60, 0x12, 0x0C, 0x12, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x13, 0x43, 0x0B, 0x60, 0xDD, 0xE9, +0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x8B, 0xF8, 0x24, 0x40, 0xD3, 0xF8, 0x60, 0x32, 0x98, 0x47, +0xAA, 0x78, 0x11, 0x46, 0x30, 0x46, 0x05, 0xF0, 0x5B, 0xFF, 0xAB, 0x78, 0x00, 0x2B, 0x38, 0xD0, 0x45, 0x4B, 0x1B, 0x68, +0x1A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE0, 0x80, 0x43, 0x49, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x00, 0xF0, 0xE5, 0x80, +0xC2, 0xF3, 0x0B, 0x01, 0x00, 0x29, 0x40, 0xF0, 0x4F, 0x81, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0A, 0x71, 0x22, 0xF4, +0x7F, 0x62, 0xC9, 0x68, 0x3B, 0x48, 0x22, 0xF0, 0x0F, 0x02, 0xC1, 0xF3, 0x0B, 0x01, 0x0A, 0x43, 0x02, 0x60, 0x9A, 0x68, +0x00, 0x2A, 0x40, 0xF0, 0xD9, 0x80, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x35, 0x49, 0x12, 0x69, 0x0A, 0x60, +0xDB, 0x68, 0x00, 0x2B, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x77, 0x30, 0x4B, 0x7A, 0x69, +0x1A, 0x60, 0x21, 0x4B, 0xD3, 0xF8, 0xA0, 0x31, 0x98, 0x47, 0x42, 0x46, 0x49, 0x46, 0x1F, 0x20, 0x08, 0xF0, 0x30, 0xFB, +0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0xB1, 0x22, 0x4B, 0x9C, 0x68, 0x6C, 0xB1, 0x94, 0xF8, 0x62, 0x30, +0x3B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x23, 0xB1, 0xA6, 0x42, 0x02, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x13, 0xB1, 0x24, 0x68, +0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x2A, 0x00, 0xF0, 0xB2, 0x80, 0x1F, 0x4B, 0x19, 0x6A, 0xA1, 0x42, 0x9D, 0xD1, 0x0E, 0x49, +0x1D, 0x4C, 0xD1, 0xF8, 0x64, 0x12, 0x00, 0x22, 0x1A, 0x62, 0x83, 0xF8, 0x24, 0x20, 0x88, 0x47, 0x0F, 0x4A, 0x1A, 0x48, +0xD2, 0xE9, 0x00, 0x13, 0x43, 0xF0, 0x10, 0x03, 0x19, 0x43, 0x01, 0x60, 0x17, 0x48, 0x18, 0x49, 0x20, 0x60, 0x53, 0x60, +0x0B, 0x68, 0x03, 0x43, 0x0B, 0x60, 0xAA, 0x78, 0x83, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xD0, 0x9E, 0x15, 0x00, 0x68, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, +0x98, 0x9C, 0x17, 0x00, 0x83, 0xDE, 0x1B, 0x43, 0x00, 0x88, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, 0xAC, 0x35, 0x17, 0x00, +0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, 0x0C, 0x02, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, +0x70, 0x80, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x74, 0x80, 0x32, 0x40, 0xAC, 0x4B, 0x03, 0x93, +0x0B, 0xF1, 0x18, 0x00, 0x38, 0x44, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0xD3, 0xF8, 0xDC, 0x33, 0x98, 0x47, +0xA7, 0x49, 0x96, 0xF8, 0xC0, 0x24, 0x23, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x0A, 0xF9, 0xA4, 0x4B, 0x1B, 0x68, +0x19, 0x04, 0x00, 0xF1, 0xD8, 0x80, 0xA3, 0x4B, 0x9B, 0x7F, 0x3B, 0xB9, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, +0x82, 0xF8, 0xC3, 0x34, 0xC2, 0xF8, 0xC4, 0x34, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0xC0, 0x34, +0x00, 0x2B, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x8E, 0x80, 0x98, 0x4B, 0x9C, 0x68, 0x00, 0x2C, 0x00, 0xF0, +0x89, 0x80, 0x94, 0xF8, 0x62, 0x30, 0x4B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xB1, 0xA6, 0x42, 0x04, 0xD0, 0x94, 0xF8, +0xC0, 0x34, 0x00, 0x2B, 0x00, 0xF0, 0x4A, 0x81, 0x24, 0x68, 0x00, 0x2C, 0xEF, 0xD1, 0x77, 0xE0, 0x4F, 0xF4, 0xA4, 0x62, +0x02, 0xFB, 0x0A, 0x72, 0x8C, 0x49, 0x92, 0x68, 0x0A, 0x60, 0x5A, 0x68, 0x00, 0x2A, 0x7F, 0xF4, 0x1B, 0xAF, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x0A, 0x72, 0x88, 0x49, 0xD2, 0x68, 0x0A, 0x60, 0x9A, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x27, 0xAF, +0x85, 0x49, 0x0A, 0x60, 0xDB, 0x68, 0x00, 0x2B, 0x3F, 0xF4, 0x2C, 0xAF, 0x83, 0x4A, 0x13, 0x60, 0x7A, 0x4B, 0xD3, 0xF8, +0xA0, 0x31, 0x98, 0x47, 0x2F, 0xE7, 0x81, 0x48, 0x81, 0x49, 0x03, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x03, 0x60, 0x0B, 0x6A, +0x00, 0x2B, 0x7F, 0xF4, 0xE6, 0xAE, 0x00, 0x2C, 0x3F, 0xF4, 0xE3, 0xAE, 0xDF, 0xF8, 0xC4, 0xB1, 0x0C, 0x62, 0x81, 0xF8, +0x24, 0x20, 0x04, 0xF1, 0x18, 0x00, 0xDB, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xDB, 0xF8, 0x60, 0x32, 0x98, 0x47, 0x76, 0x49, +0xDF, 0xF8, 0xE4, 0xC1, 0x75, 0x48, 0xD4, 0xF8, 0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF0, 0x10, 0x02, +0x13, 0x43, 0xCC, 0xF8, 0x00, 0x30, 0xC0, 0xF8, 0x00, 0xE0, 0x70, 0x4B, 0x4C, 0xF8, 0x3C, 0x4C, 0x00, 0xF5, 0x00, 0x40, +0x54, 0x30, 0x6E, 0x4C, 0x1C, 0x60, 0x03, 0x68, 0x4A, 0x60, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, 0x03, 0x60, +0x1A, 0xE0, 0xCC, 0xB1, 0x64, 0x4A, 0x10, 0x6A, 0xB0, 0xB1, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, +0x64, 0x32, 0x98, 0x47, 0x60, 0x49, 0x64, 0x48, 0xD1, 0xE9, 0x00, 0x23, 0x43, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, +0x02, 0x60, 0xAA, 0x78, 0x9F, 0xE6, 0x02, 0x2C, 0x65, 0xD0, 0x01, 0x2C, 0x00, 0xF0, 0xC0, 0x80, 0xAA, 0x78, 0x98, 0xE6, +0x52, 0x49, 0x0A, 0x60, 0x94, 0xE7, 0xE6, 0xF7, 0x1F, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x29, 0xAE, 0x02, 0x9A, 0x11, 0x46, +0x57, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x23, 0x5B, 0x68, 0x9A, 0x06, 0x7F, 0xF5, 0x1E, 0xAE, 0x28, 0x88, +0xE6, 0xF7, 0x54, 0xFE, 0xF9, 0xF7, 0x9C, 0xF9, 0x51, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x0A, 0xF0, 0x41, 0xF8, 0x03, 0x9B, +0xD3, 0xF8, 0xE0, 0x33, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x0A, 0x73, 0x93, 0xF8, 0x62, 0x20, 0x04, 0x2A, +0x3F, 0xF4, 0x07, 0xAE, 0x93, 0xF8, 0x63, 0x00, 0x03, 0x9B, 0xD3, 0xF8, 0x30, 0x33, 0x98, 0x47, 0xFF, 0xE5, 0xE6, 0xF7, +0xF1, 0xFD, 0x00, 0x28, 0x3F, 0xF4, 0x23, 0xAF, 0x41, 0x4B, 0x02, 0x99, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x3B, +0xDB, 0xF8, 0x04, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x18, 0xAF, 0x96, 0xF8, 0x62, 0x30, 0x04, 0x2B, 0x3F, 0xF4, 0x13, 0xAF, +0x96, 0xF8, 0x63, 0x00, 0x06, 0xF0, 0x2A, 0xFB, 0x0D, 0xE7, 0x01, 0x2C, 0xB0, 0xD1, 0x30, 0x4C, 0x22, 0x6A, 0xB2, 0x42, +0xAC, 0xD0, 0x23, 0x62, 0x02, 0x93, 0xDD, 0xE9, 0x03, 0x30, 0xD3, 0xF8, 0xD8, 0x21, 0x90, 0x47, 0x02, 0x9B, 0x84, 0xF8, +0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, 0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0x37, 0xE6, 0x26, 0x4C, 0x23, 0x6A, 0x00, 0x2B, +0x98, 0xD1, 0x1E, 0x4B, 0x98, 0x68, 0x20, 0xB9, 0xA3, 0xE0, 0x00, 0x68, 0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x90, 0xF8, +0x62, 0x30, 0x00, 0x2B, 0xF7, 0xD1, 0x90, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF3, 0xD0, 0x86, 0x42, 0xF1, 0xD0, 0x90, 0xF8, +0xC0, 0x34, 0x00, 0x2B, 0xED, 0xD1, 0x1F, 0x49, 0x17, 0x4A, 0x20, 0x62, 0x9B, 0x46, 0x90, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, +0x1E, 0x7C, 0x0C, 0xFB, 0x03, 0x13, 0x11, 0x68, 0x9B, 0x68, 0x09, 0x0C, 0x09, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x0B, 0x43, +0x13, 0x60, 0x03, 0x9B, 0x18, 0x30, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x84, 0xF8, 0x24, 0xB0, 0xD3, 0xF8, +0x60, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xFE, 0xE5, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9F, 0x15, 0x00, 0x04, 0x00, 0x32, 0x40, +0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0x02, 0x32, 0x40, 0x04, 0x02, 0x32, 0x40, 0x08, 0x02, 0x32, 0x40, +0x0C, 0x02, 0x32, 0x40, 0x64, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x20, 0x00, 0x32, 0x40, +0x70, 0x80, 0x32, 0x40, 0x01, 0x00, 0x04, 0x00, 0x60, 0x00, 0x32, 0x40, 0x68, 0x65, 0x17, 0x00, 0xF0, 0x9E, 0x15, 0x00, +0x29, 0x4A, 0x11, 0x6A, 0xB1, 0x42, 0x7F, 0xF4, 0x3B, 0xAF, 0x13, 0x62, 0x82, 0xF8, 0x24, 0x30, 0x03, 0x9B, 0xD3, 0xF8, +0x64, 0x32, 0x98, 0x47, 0xAA, 0x78, 0xCC, 0xE5, 0xDF, 0xF8, 0x88, 0xB0, 0xDB, 0xF8, 0x20, 0x20, 0x00, 0x2A, 0x7F, 0xF4, +0x2B, 0xAF, 0x94, 0xF8, 0x6C, 0x30, 0x1F, 0x48, 0x1F, 0x49, 0xCB, 0xF8, 0x20, 0x40, 0x4F, 0xF4, 0x1E, 0x7C, 0x0C, 0xFB, +0x03, 0x03, 0x08, 0x68, 0x9B, 0x68, 0x02, 0x92, 0x00, 0x0C, 0x00, 0x04, 0xC3, 0xF3, 0x8F, 0x23, 0x03, 0x43, 0x0B, 0x60, +0x03, 0x9B, 0x04, 0xF1, 0x18, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x03, 0x9B, 0x02, 0x9A, 0x8B, 0xF8, 0x24, 0x20, +0xD3, 0xF8, 0x60, 0x32, 0xDF, 0xF8, 0x50, 0xB0, 0x98, 0x47, 0x11, 0x49, 0xDF, 0xF8, 0x4C, 0xC0, 0x10, 0x48, 0xD4, 0xF8, +0x38, 0xE0, 0xA4, 0x8F, 0xD1, 0xE9, 0x00, 0x23, 0x23, 0xF0, 0x10, 0x03, 0x1A, 0x43, 0x4B, 0x60, 0xCB, 0xF8, 0x00, 0x20, +0xCC, 0xF8, 0x00, 0xE0, 0x04, 0x60, 0xAA, 0x78, 0x8F, 0xE5, 0x01, 0x2B, 0x7F, 0xF4, 0xF2, 0xAE, 0xE1, 0xE6, 0x00, 0x23, +0x93, 0xF8, 0x6C, 0x30, 0xFF, 0xDE, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x64, 0x00, 0x32, 0x40, +0x98, 0x9C, 0x17, 0x00, 0x24, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x07, 0x20, +0x0C, 0x46, 0x19, 0x46, 0x02, 0x23, 0x08, 0xF0, 0x7F, 0xF8, 0x23, 0x46, 0x07, 0x4D, 0x13, 0xF8, 0x02, 0x1B, 0x22, 0x7A, +0xD5, 0xF8, 0x58, 0x54, 0x04, 0x46, 0x18, 0x46, 0x63, 0x1C, 0xA8, 0x47, 0x20, 0x70, 0x20, 0x46, 0x08, 0xF0, 0xA0, 0xF8, +0x00, 0x20, 0x38, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x00, 0xB5, 0x08, 0x78, 0x03, 0x28, 0x83, 0xB0, 0x19, 0x46, 0x07, 0xD8, +0xCD, 0xE9, 0x00, 0x23, 0x0C, 0x4B, 0xD3, 0xF8, 0x64, 0x34, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0x0A, 0x4B, 0x9B, 0x68, +0x33, 0xB1, 0x09, 0x20, 0x08, 0xF0, 0xC0, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x04, 0x4B, 0xD3, 0xF8, +0xE8, 0x30, 0xCD, 0xE9, 0x00, 0x21, 0x98, 0x47, 0xDD, 0xE9, 0x00, 0x21, 0xEF, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, +0x00, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0D, 0x78, 0x0C, 0x46, 0x16, 0x46, 0x98, 0x46, 0x00, 0x2D, 0x3B, 0xD1, +0x91, 0xF8, 0x02, 0xC0, 0x26, 0x49, 0x27, 0x4A, 0x11, 0xF8, 0x0C, 0x00, 0xE1, 0x78, 0x52, 0xF8, 0x20, 0x20, 0x60, 0x78, +0x24, 0x4F, 0x25, 0x4B, 0x91, 0x42, 0xB8, 0xBF, 0x4A, 0x08, 0x00, 0xEB, 0x80, 0x01, 0xC0, 0xEB, 0x01, 0x11, 0x61, 0x44, +0x07, 0xEB, 0xC1, 0x01, 0x4F, 0xF0, 0x9E, 0x0E, 0x91, 0xF8, 0xA5, 0x11, 0x0E, 0xFB, 0x00, 0xC0, 0xA8, 0xBF, 0x02, 0xEB, +0xD2, 0x72, 0x07, 0xEB, 0x80, 0x00, 0xA8, 0xBF, 0xC2, 0xF3, 0x47, 0x02, 0x01, 0xEB, 0x41, 0x01, 0x80, 0xF8, 0x5A, 0x21, +0x03, 0xEB, 0xC1, 0x01, 0xA2, 0x88, 0x0A, 0x81, 0x32, 0x46, 0x41, 0x46, 0x03, 0x23, 0x29, 0x20, 0x08, 0xF0, 0x0C, 0xF8, +0x62, 0x78, 0x02, 0x70, 0xA2, 0x78, 0x42, 0x70, 0x85, 0x70, 0x08, 0xF0, 0x35, 0xF8, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, +0x48, 0x78, 0x0B, 0x49, 0xA2, 0x88, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x10, 0xA1, 0x78, 0x14, 0xF0, 0xA0, 0xFB, +0x08, 0xB9, 0x04, 0x25, 0xE2, 0xE7, 0x07, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x00, 0x25, 0xDB, 0xE7, +0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, +0x2D, 0xE9, 0xF0, 0x43, 0x04, 0x46, 0x87, 0xB0, 0x10, 0x46, 0x15, 0x46, 0x0E, 0x46, 0x1F, 0x46, 0x08, 0xF0, 0x7C, 0xFA, +0x40, 0xB1, 0x02, 0x38, 0x80, 0xB2, 0x02, 0x28, 0x4D, 0xD8, 0x02, 0x24, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, +0xDF, 0xF8, 0x88, 0x83, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x65, 0xDB, 0x3B, 0x2C, 0x00, 0xF2, +0xA7, 0x80, 0x05, 0x2C, 0x40, 0xF2, 0xE3, 0x80, 0x06, 0x3C, 0x35, 0x2C, 0x4A, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0xBF, 0x01, +0x49, 0x00, 0xB5, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x88, 0x01, 0x49, 0x00, 0x6E, 0x01, +0x49, 0x00, 0x5A, 0x01, 0x49, 0x00, 0x50, 0x01, 0x49, 0x00, 0x3A, 0x01, 0x49, 0x00, 0x30, 0x01, 0x49, 0x00, 0x49, 0x00, +0x49, 0x00, 0x1D, 0x01, 0x49, 0x00, 0x13, 0x01, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, +0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0xF6, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, +0x49, 0x00, 0xEF, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, 0x49, 0x00, +0x49, 0x00, 0x49, 0x00, 0xE2, 0x00, 0xB1, 0x4B, 0xB1, 0x4C, 0x1B, 0x68, 0x28, 0x46, 0x03, 0xF0, 0x0F, 0x03, 0xE3, 0x74, +0x08, 0xF0, 0x20, 0xFA, 0xAE, 0x4B, 0xA0, 0x74, 0xD3, 0xF8, 0xE0, 0x30, 0x98, 0x47, 0x28, 0x46, 0x02, 0x21, 0x08, 0xF0, +0x6F, 0xF9, 0x9E, 0xE7, 0xDF, 0xF8, 0xA0, 0x82, 0x02, 0x24, 0x98, 0xF8, 0x13, 0x30, 0xA5, 0x4A, 0x1B, 0x01, 0xDB, 0xB2, +0x13, 0x60, 0x28, 0x46, 0x98, 0xF8, 0x12, 0x10, 0x08, 0xF0, 0x60, 0xF9, 0x20, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, +0x9E, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x40, 0xF0, 0x6F, 0x81, 0x3B, 0x2C, 0x67, 0xD8, 0x05, 0x2C, 0x67, 0xD9, 0x06, 0x3C, +0x35, 0x2C, 0x64, 0xD8, 0xDF, 0xE8, 0x14, 0xF0, 0x56, 0x01, 0x63, 0x00, 0x4C, 0x01, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, +0x63, 0x00, 0x63, 0x00, 0x1F, 0x01, 0x63, 0x00, 0x05, 0x01, 0x63, 0x00, 0xF1, 0x00, 0x63, 0x00, 0xE7, 0x00, 0x63, 0x00, +0xD1, 0x00, 0x63, 0x00, 0xC7, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0xB4, 0x00, 0x63, 0x00, 0xAA, 0x00, 0x63, 0x00, +0x97, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x8D, 0x00, 0x63, 0x00, +0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x86, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, +0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x79, 0x00, 0x87, 0x2C, 0x3C, 0xD1, +0xDF, 0xF8, 0xF0, 0x81, 0xDF, 0xF8, 0xF0, 0x91, 0x00, 0x27, 0x88, 0xF8, 0x30, 0x70, 0x30, 0x68, 0xD9, 0xF8, 0xF8, 0x30, +0x98, 0x47, 0x04, 0x46, 0x00, 0x28, 0x40, 0xF0, 0x19, 0x81, 0x98, 0xF8, 0x31, 0x30, 0x00, 0x2B, 0x97, 0xD0, 0x05, 0xA8, +0x88, 0xF8, 0x31, 0x40, 0x01, 0xF0, 0x74, 0xFD, 0x00, 0x28, 0x90, 0xD0, 0x05, 0x9A, 0x71, 0x49, 0x92, 0xF8, 0x63, 0x30, +0x92, 0xF8, 0xC1, 0x04, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x05, 0xF0, 0x9C, 0xFF, +0x81, 0xE7, 0x87, 0x2C, 0xD4, 0xD0, 0x6A, 0x49, 0x6A, 0x48, 0xDF, 0xF8, 0x98, 0x81, 0x40, 0xF6, 0x06, 0x22, 0x09, 0xF0, +0xCB, 0xFF, 0x02, 0x24, 0x75, 0xE7, 0x87, 0x2C, 0xC8, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xED, 0xDB, 0xDF, 0xF8, 0x78, 0x81, 0x02, 0x24, 0x69, 0xE7, 0x5D, 0x4B, 0xDF, 0xF8, 0x6C, 0x81, 0x9B, 0x6D, 0x30, 0x46, +0x98, 0x47, 0x2A, 0x46, 0x39, 0x46, 0x3C, 0x20, 0x07, 0xF0, 0x38, 0xFF, 0x00, 0x24, 0x5C, 0xE7, 0x30, 0x46, 0x09, 0xF0, +0xD3, 0xFF, 0xDF, 0xF8, 0x50, 0x81, 0x00, 0x24, 0x55, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x28, 0x20, 0xFF, 0xF7, +0x7B, 0xFE, 0xDF, 0xF8, 0x3C, 0x81, 0x04, 0x46, 0x4B, 0xE7, 0x52, 0x4B, 0x32, 0x78, 0x1B, 0x68, 0x51, 0x48, 0xDF, 0xF8, +0x2C, 0x81, 0xDB, 0xB2, 0x03, 0xFB, 0x02, 0xF3, 0x42, 0xEA, 0x03, 0x23, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x21, 0x20, +0x07, 0xF0, 0x14, 0xFF, 0x00, 0x24, 0x38, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x1E, 0x20, 0xFF, 0xF7, 0xD4, 0xFA, +0xDF, 0xF8, 0x00, 0x81, 0x04, 0x46, 0x2E, 0xE7, 0x45, 0x48, 0x33, 0x78, 0x02, 0x68, 0xDF, 0xF8, 0xF4, 0x80, 0x9B, 0x03, +0x22, 0xF4, 0xE0, 0x32, 0x03, 0xF4, 0xE0, 0x33, 0x13, 0x43, 0x03, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x1D, 0x20, 0x07, 0xF0, +0xF7, 0xFE, 0x00, 0x24, 0x1B, 0xE7, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x18, 0x20, 0xFF, 0xF7, 0x77, 0xFA, 0xDF, 0xF8, +0xC8, 0x80, 0x04, 0x46, 0x11, 0xE7, 0x73, 0x79, 0xDF, 0xF8, 0xBC, 0x80, 0x36, 0x4A, 0x31, 0x68, 0x92, 0x6A, 0x08, 0xEB, +0x83, 0x00, 0x41, 0x61, 0x22, 0xB1, 0x12, 0x79, 0x9A, 0x42, 0x04, 0xBF, 0x32, 0x4B, 0x19, 0x60, 0x39, 0x46, 0x2A, 0x46, +0x17, 0x20, 0x07, 0xF0, 0xD7, 0xFE, 0x00, 0x24, 0xFB, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x14, 0x20, 0xFF, 0xF7, +0x2B, 0xFA, 0xDF, 0xF8, 0x88, 0x80, 0x04, 0x46, 0xF1, 0xE6, 0x2A, 0x4A, 0x31, 0x78, 0x13, 0x68, 0xDF, 0xF8, 0x78, 0x80, +0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, +0x13, 0x20, 0x07, 0xF0, 0xB9, 0xFE, 0x00, 0x24, 0xDD, 0xE6, 0x39, 0x46, 0x02, 0x23, 0x2A, 0x46, 0x11, 0x20, 0x07, 0xF0, +0x49, 0xFE, 0x72, 0x7A, 0xF3, 0x88, 0xB1, 0x7A, 0x02, 0x91, 0xCD, 0xE9, 0x00, 0x32, 0x04, 0x46, 0xB3, 0x88, 0x72, 0x88, +0x71, 0x78, 0x30, 0x78, 0xDF, 0xF8, 0x34, 0x80, 0xE6, 0xF7, 0x1E, 0xFA, 0x20, 0x46, 0x07, 0xF0, 0x67, 0xFE, 0x00, 0x24, +0xC3, 0xE6, 0xDF, 0xF8, 0x24, 0x80, 0x33, 0x68, 0xD8, 0xF8, 0x04, 0x10, 0x11, 0x4A, 0xC8, 0xF8, 0x00, 0x30, 0x0B, 0x43, +0x13, 0x60, 0x39, 0x46, 0x2A, 0x46, 0x0F, 0x20, 0x07, 0xF0, 0x8E, 0xFE, 0x00, 0x24, 0xB2, 0xE6, 0x38, 0x00, 0x32, 0x40, +0x98, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, +0xE4, 0x00, 0x32, 0x40, 0xE8, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x30, 0x9D, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, +0x90, 0x00, 0x32, 0x40, 0x60, 0x00, 0x32, 0x40, 0x38, 0x36, 0x17, 0x00, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x08, 0x20, +0xFF, 0xF7, 0x96, 0xFD, 0xDF, 0xF8, 0x2C, 0x81, 0x04, 0x46, 0x8C, 0xE6, 0x3B, 0x46, 0x31, 0x46, 0x2A, 0x46, 0x06, 0x20, +0xFF, 0xF7, 0x72, 0xFD, 0xDF, 0xF8, 0x18, 0x81, 0x04, 0x46, 0x82, 0xE6, 0xD9, 0xF8, 0x6C, 0x31, 0x30, 0x68, 0x98, 0x47, +0x3C, 0x46, 0x7C, 0xE6, 0x3F, 0x49, 0x40, 0x48, 0x40, 0xF6, 0xC9, 0x12, 0x09, 0xF0, 0xCA, 0xFE, 0x3B, 0x2C, 0x3F, 0xF6, +0xFE, 0xAE, 0x05, 0x2C, 0x7F, 0xF6, 0xFD, 0xAE, 0x06, 0x3C, 0x35, 0x2C, 0x3F, 0xF6, 0xF9, 0xAE, 0x01, 0xA3, 0x53, 0xF8, +0x24, 0xF0, 0x00, 0xBF, 0xBD, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xA9, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x4F, 0xAD, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0x1B, 0xAD, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xF3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0xDF, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xB3, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x9F, 0xAC, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x79, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0x65, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x3F, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0x2B, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x1D, 0xAC, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, +0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0xEF, 0xAB, 0x13, 0x00, 0x03, 0xAC, 0x13, 0x00, +0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xC0, 0x68, 0xCB, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, +0x70, 0x47, 0x00, 0xBF, 0x01, 0x48, 0x08, 0xF0, 0xE9, 0xB9, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, 0x06, 0x4B, 0x38, 0xB1, +0xC1, 0x68, 0x04, 0x22, 0x4F, 0xF4, 0x80, 0x20, 0x98, 0x60, 0x19, 0x63, 0x9A, 0x60, 0x70, 0x47, 0x4F, 0xF4, 0x80, 0x62, +0x9A, 0x60, 0x70, 0x47, 0x00, 0x10, 0x50, 0x40, 0x33, 0x4A, 0xF8, 0xB5, 0x13, 0x69, 0xCB, 0x1A, 0x00, 0x2B, 0x0C, 0x46, +0x05, 0x46, 0x57, 0xDB, 0x30, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x46, 0xDB, 0xEF, 0xF3, 0x10, 0x83, +0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2B, 0x4F, 0x2C, 0x4E, 0x3B, 0x68, 0x32, 0x68, +0x01, 0x33, 0x95, 0x42, 0x3B, 0x60, 0x19, 0xD0, 0x29, 0x46, 0x30, 0x46, 0x08, 0xF0, 0x08, 0xFA, 0x30, 0x46, 0x27, 0x4A, +0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x40, 0xFA, 0x30, 0x68, 0x85, 0x42, 0x16, 0xD0, 0x3B, 0x68, 0x23, 0xB1, 0x1F, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, 0xA3, 0xB1, 0x1A, 0x4B, 0x19, 0x69, 0x64, 0x1A, 0x00, 0x2C, 0x17, 0xDB, 0xF8, 0xBD, +0x30, 0x46, 0x08, 0xF0, 0xE3, 0xF9, 0x30, 0x46, 0x1A, 0x4A, 0xEC, 0x60, 0x29, 0x46, 0x08, 0xF0, 0x27, 0xFA, 0x30, 0x68, +0x18, 0x4B, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xE3, 0xE7, 0x00, 0x2A, 0xE8, 0xD0, 0x62, 0xB6, 0x0E, 0x4B, 0x19, 0x69, +0x64, 0x1A, 0x00, 0x2C, 0xE7, 0xDA, 0xBD, 0xE8, 0xF8, 0x40, 0x4F, 0xF0, 0x80, 0x40, 0x08, 0xF0, 0xE3, 0xB8, 0x09, 0x4B, +0x1B, 0x69, 0xE3, 0x1A, 0x00, 0x2B, 0xB3, 0xDA, 0x0D, 0x49, 0x0E, 0x48, 0x7D, 0x22, 0x09, 0xF0, 0xCF, 0xFD, 0xAD, 0xE7, +0x13, 0x69, 0x41, 0x68, 0x0B, 0x48, 0x22, 0x46, 0x09, 0xF0, 0x4E, 0xFB, 0xA0, 0xE7, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, +0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0xE9, 0xAE, 0x13, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0x9F, 0x15, 0x00, 0x4C, 0x9F, 0x15, 0x00, 0x38, 0xB5, 0x01, 0x46, +0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4C, 0x10, 0x4D, +0x23, 0x68, 0x2A, 0x68, 0x01, 0x33, 0x8A, 0x42, 0x23, 0x60, 0x28, 0x46, 0x0B, 0xD0, 0x08, 0xF0, 0x99, 0xF9, 0x23, 0x68, +0x33, 0xB1, 0x08, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, 0x08, 0xF0, +0x81, 0xF9, 0x06, 0x4B, 0x28, 0x68, 0xD3, 0xF8, 0xDC, 0x31, 0x98, 0x47, 0xED, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0xD0, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x2C, 0x4F, 0x2D, 0x4D, +0xDF, 0xF8, 0xC8, 0xA0, 0xDF, 0xF8, 0xC0, 0x80, 0x2B, 0x4E, 0xB9, 0x46, 0x01, 0xE0, 0xA0, 0x68, 0x98, 0x47, 0x4F, 0xF0, +0x80, 0x40, 0x08, 0xF0, 0x9F, 0xF8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0xC8, 0xF8, +0x00, 0x30, 0x2B, 0x68, 0x3C, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x4C, 0xB3, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x32, 0x2B, +0x08, 0xD4, 0xDA, 0xF8, 0xDC, 0x31, 0x20, 0x46, 0x98, 0x47, 0x32, 0x69, 0xE3, 0x68, 0x9B, 0x1A, 0x00, 0x2B, 0x2A, 0xDA, +0x48, 0x46, 0x08, 0xF0, 0x43, 0xF9, 0x2B, 0x68, 0x33, 0xB1, 0x01, 0x3B, 0xD8, 0xF8, 0x00, 0x20, 0x2B, 0x60, 0x0B, 0xB9, +0x02, 0xB1, 0x62, 0xB6, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x63, 0x68, 0xCB, 0xDA, 0x00, 0x2B, +0xC9, 0xD1, 0x11, 0x49, 0x11, 0x48, 0xEB, 0x22, 0x09, 0xF0, 0x3C, 0xFD, 0x63, 0x68, 0xC2, 0xE7, 0xDA, 0xF8, 0xDC, 0x31, +0x20, 0x46, 0x98, 0x47, 0x2B, 0x68, 0x33, 0xB1, 0x0C, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0xBD, 0xE8, 0xF0, 0x87, 0x2B, 0x68, 0x00, 0x2B, 0xFA, 0xD0, 0xF2, 0xE7, 0x00, 0xBF, 0xD0, 0x9C, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x90, 0x9F, 0x15, 0x00, +0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x11, 0xF4, 0x00, 0x05, 0x04, 0x46, 0x0E, 0xD1, 0x90, 0xF8, +0x5C, 0x22, 0x1E, 0x49, 0x1E, 0x48, 0x01, 0x32, 0xD2, 0xB2, 0x84, 0xF8, 0x5C, 0x22, 0x09, 0xF0, 0x8D, 0xFA, 0x94, 0xF8, +0x5C, 0x32, 0x09, 0x2B, 0x15, 0xD8, 0x70, 0xBD, 0x17, 0x49, 0x19, 0x48, 0x09, 0xF0, 0x84, 0xFA, 0x94, 0xF8, 0x23, 0x30, +0x00, 0x22, 0x0D, 0x2B, 0x84, 0xF8, 0x5C, 0x22, 0xF3, 0xD8, 0x15, 0x49, 0x15, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, +0x03, 0x13, 0x12, 0x69, 0xC3, 0xF8, 0x58, 0x22, 0x70, 0xBD, 0x2A, 0x46, 0x08, 0x23, 0x0C, 0x21, 0x7D, 0x20, 0x07, 0xF0, +0x05, 0xFC, 0x94, 0xF8, 0x23, 0x30, 0x03, 0x70, 0x94, 0xF8, 0x22, 0x30, 0x43, 0x70, 0x06, 0x46, 0x04, 0xF1, 0x26, 0x01, +0x84, 0xF8, 0x5C, 0x52, 0x02, 0x30, 0x06, 0x22, 0x1B, 0xF0, 0x7E, 0xFF, 0x30, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x07, 0xF0, +0x21, 0xBC, 0x00, 0xBF, 0x34, 0xA0, 0x15, 0x00, 0x9C, 0x9F, 0x15, 0x00, 0xB4, 0x9F, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x63, 0x30, 0x63, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x0A, 0x33, +0x04, 0xFB, 0x03, 0xF3, 0x11, 0x46, 0x02, 0xF1, 0x28, 0x04, 0x1C, 0x44, 0x1A, 0x44, 0x83, 0xB0, 0x0B, 0x46, 0xD2, 0xF8, +0x08, 0x12, 0x00, 0x29, 0x40, 0xF0, 0xA2, 0x80, 0xD2, 0xF8, 0x30, 0x12, 0x08, 0x32, 0x00, 0x29, 0x40, 0xF0, 0x9C, 0x80, +0xA2, 0x42, 0xF2, 0xD1, 0x57, 0x4A, 0x58, 0x4C, 0xDF, 0xF8, 0x70, 0xB1, 0x4F, 0xF4, 0xA4, 0x61, 0x93, 0xF8, 0x25, 0x60, +0x2E, 0xB1, 0x93, 0xF8, 0x22, 0x60, 0x01, 0xFB, 0x06, 0x46, 0xB0, 0x42, 0x06, 0xD0, 0x03, 0xF5, 0x1E, 0x73, 0x9A, 0x42, +0xF2, 0xD1, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x23, 0x60, 0x0D, 0x2E, 0x77, 0xD9, 0x4F, 0xF0, 0x00, 0x08, +0xDB, 0xF8, 0x10, 0xE0, 0x1E, 0x46, 0x03, 0xF1, 0x28, 0x0C, 0xD6, 0xF8, 0x08, 0x72, 0x77, 0xB9, 0xD6, 0xF8, 0x30, 0x72, +0x08, 0x36, 0x57, 0xB9, 0xB4, 0x45, 0xF6, 0xD1, 0xCE, 0xF5, 0x64, 0x0E, 0x0E, 0xF5, 0x61, 0x4E, 0x0E, 0xF1, 0xC0, 0x0E, +0x1E, 0xEB, 0x08, 0x0F, 0xDB, 0xD5, 0x90, 0xF8, 0x63, 0x60, 0x93, 0xF8, 0x20, 0xE0, 0x00, 0x96, 0x35, 0x46, 0xC6, 0xEB, +0x86, 0x17, 0x3C, 0x4E, 0x4F, 0xEA, 0xDE, 0x08, 0x06, 0xEB, 0x87, 0x07, 0x0E, 0xF0, 0x07, 0x0C, 0x01, 0x26, 0x18, 0xF8, +0x07, 0x90, 0x06, 0xFA, 0x0C, 0xFC, 0x1C, 0xEA, 0x09, 0x0F, 0x07, 0xEB, 0xDE, 0x06, 0x01, 0x96, 0x5F, 0xFA, 0x8C, 0xFA, +0x0F, 0xFA, 0x85, 0xFE, 0xBD, 0xD1, 0x4A, 0xEA, 0x09, 0x09, 0x08, 0xF8, 0x07, 0x90, 0xB0, 0xF8, 0xD0, 0x90, 0x90, 0xF8, +0xD8, 0xC0, 0x09, 0xF1, 0x01, 0x09, 0xC4, 0x45, 0xA0, 0xF8, 0xD0, 0x90, 0x3E, 0xD8, 0xAF, 0x00, 0x90, 0xF8, 0xD9, 0x90, +0xC1, 0x45, 0x0B, 0xD2, 0x00, 0x9D, 0x28, 0x4E, 0x80, 0xF8, 0xD9, 0x80, 0x07, 0xEB, 0x05, 0x0A, 0x06, 0xEB, 0xCA, 0x0A, +0x01, 0x9E, 0xCA, 0xF8, 0x20, 0x60, 0xC1, 0x46, 0x23, 0x4E, 0x00, 0x9D, 0xCC, 0xF1, 0x06, 0x0C, 0xCC, 0x44, 0x06, 0xEB, +0xCE, 0x0E, 0x1F, 0xFA, 0x8C, 0xFC, 0x1E, 0x4E, 0xA0, 0xF8, 0xCE, 0xC0, 0xAC, 0xF1, 0x02, 0x08, 0x8E, 0xF8, 0x01, 0x80, +0x4F, 0xF0, 0x28, 0x0C, 0x2F, 0x44, 0x06, 0xEB, 0xC7, 0x07, 0x0C, 0xFB, 0x05, 0x66, 0x90, 0xF8, 0xD8, 0xC0, 0x8E, 0xF8, +0x04, 0xC0, 0x14, 0x36, 0x0E, 0xF1, 0x04, 0x0E, 0xC7, 0xF8, 0x0C, 0xE0, 0x7E, 0x60, 0x7C, 0xE7, 0x0D, 0x4D, 0x4F, 0xF4, +0x1E, 0x77, 0x07, 0xFB, 0x06, 0x56, 0xD6, 0xF8, 0x58, 0x82, 0x81, 0xE7, 0x0F, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x61, 0xE7, +0x00, 0x9D, 0x0B, 0x4E, 0x05, 0xEB, 0x85, 0x09, 0x08, 0xF0, 0x1E, 0x0C, 0x06, 0xEB, 0xC9, 0x09, 0x67, 0x44, 0x80, 0xF8, +0xD8, 0xC0, 0xC9, 0xF8, 0x1C, 0x70, 0xAF, 0x00, 0xB2, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x7E, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x16, 0x2C, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, 0x02, 0x88, 0xC3, 0x78, 0x04, 0x46, 0xB2, 0xB9, 0x82, 0x78, 0x00, 0x2A, +0x40, 0xF0, 0xAD, 0x80, 0x88, 0x48, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x03, 0x83, 0xF8, 0xDA, 0x20, 0x34, 0xF8, +0x04, 0x1C, 0x42, 0x20, 0x00, 0x22, 0x07, 0xF0, 0x5B, 0xFB, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0xF8, 0x43, 0x07, 0xF0, +0x69, 0xBB, 0x80, 0x48, 0x80, 0x4D, 0x94, 0xF8, 0x02, 0xE0, 0xC3, 0xEB, 0x83, 0x11, 0x00, 0xEB, 0x81, 0x00, 0x01, 0x26, +0xC2, 0xF3, 0xC7, 0x01, 0x02, 0xF0, 0x07, 0x02, 0x06, 0xFA, 0x02, 0xF2, 0x0F, 0x5C, 0x0E, 0x18, 0x5F, 0xFA, 0x82, 0xFC, +0x05, 0xEB, 0xC3, 0x05, 0xBE, 0xF1, 0x00, 0x0F, 0x4D, 0xD0, 0x1C, 0xEA, 0x07, 0x0F, 0xD8, 0xD1, 0xDF, 0xF8, 0xC4, 0xE1, +0x4F, 0xF4, 0xA4, 0x62, 0x4C, 0xEA, 0x07, 0x07, 0x02, 0xFB, 0x03, 0xE2, 0x37, 0x70, 0xB2, 0xF8, 0xD0, 0x70, 0x92, 0xF8, +0xD8, 0xC0, 0x01, 0x37, 0x8C, 0x45, 0xA2, 0xF8, 0xD0, 0x70, 0x6C, 0x4F, 0x0A, 0xD9, 0x03, 0xEB, 0x83, 0x0C, 0x01, 0xF0, +0xFE, 0x08, 0x07, 0xEB, 0xCC, 0x0C, 0x40, 0x44, 0xCC, 0xF8, 0x1C, 0x00, 0x82, 0xF8, 0xD8, 0x80, 0x4F, 0xF4, 0xA4, 0x60, +0x00, 0xFB, 0x03, 0xE0, 0x4F, 0xEA, 0x83, 0x0C, 0x90, 0xF8, 0xD9, 0x80, 0x88, 0x45, 0x07, 0xD2, 0x0C, 0xEB, 0x03, 0x02, +0x07, 0xEB, 0xC2, 0x02, 0x80, 0xF8, 0xD9, 0x10, 0x88, 0x46, 0x16, 0x62, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xEE, +0x0C, 0xEB, 0x03, 0x01, 0x9E, 0xF8, 0xD8, 0x20, 0x2A, 0x71, 0xC2, 0xF1, 0x06, 0x02, 0x28, 0x20, 0x42, 0x44, 0x07, 0xEB, +0xC1, 0x01, 0x00, 0xFB, 0x03, 0x73, 0x92, 0xB2, 0x2E, 0x1D, 0x14, 0x33, 0x90, 0x1E, 0xCE, 0x60, 0x4B, 0x60, 0xAE, 0xF8, +0xCE, 0x20, 0x68, 0x70, 0x8D, 0xE7, 0x1C, 0xEA, 0x07, 0x0F, 0x8A, 0xD0, 0xDF, 0xF8, 0x28, 0xE1, 0x4F, 0xF4, 0xA4, 0x68, +0x08, 0xFB, 0x03, 0xF8, 0x27, 0xEA, 0x02, 0x02, 0x0E, 0xEB, 0x08, 0x0C, 0x32, 0x70, 0xBC, 0xF8, 0xD0, 0x70, 0x01, 0x3F, +0xBF, 0xB2, 0xAC, 0xF8, 0xD0, 0x70, 0x00, 0x2F, 0x4D, 0xD0, 0x9C, 0xF8, 0xD8, 0x70, 0x01, 0xF0, 0xFE, 0x02, 0x97, 0x42, +0x29, 0xD0, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x92, 0xF8, 0xD9, 0x70, 0x8F, 0x42, 0x35, 0xD0, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE3, 0x93, 0xF8, 0xD8, 0x10, 0x29, 0x71, 0xC1, 0xF1, 0x06, 0x01, 0x39, 0x44, 0x89, 0xB2, +0x8A, 0x1E, 0xA3, 0xF8, 0xCE, 0x10, 0x6A, 0x70, 0x59, 0xE7, 0x32, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, +0x01, 0x22, 0x83, 0xF8, 0xDA, 0x20, 0x50, 0xE7, 0x3A, 0x5C, 0x07, 0xF1, 0x01, 0x08, 0x00, 0x2A, 0x51, 0xD1, 0x5F, 0xFA, +0x88, 0xF7, 0x8C, 0xF8, 0xD8, 0x70, 0xFB, 0x2F, 0xF4, 0xD1, 0xFA, 0x22, 0x17, 0x46, 0xDF, 0xF8, 0xA8, 0x90, 0x03, 0xEB, +0x83, 0x08, 0x4F, 0xF4, 0xA4, 0x6C, 0x09, 0xEB, 0xC8, 0x08, 0x0C, 0xFB, 0x03, 0xEC, 0x02, 0x44, 0xC8, 0xF8, 0x1C, 0x20, +0x8C, 0xF8, 0xD8, 0x70, 0xC1, 0xE7, 0x41, 0xB3, 0x37, 0x78, 0x01, 0x39, 0xB4, 0x46, 0xC9, 0xB2, 0x01, 0x3E, 0x57, 0xBB, +0x82, 0xF8, 0xD9, 0x10, 0xF5, 0xE7, 0x0E, 0xF1, 0xD8, 0x02, 0x06, 0x21, 0xAC, 0xF8, 0xCE, 0x10, 0xFF, 0x21, 0x28, 0xF8, +0x02, 0x10, 0x19, 0x4A, 0x9C, 0xF8, 0xCE, 0x10, 0x2F, 0x71, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x6E, 0x1D, +0x8A, 0x1E, 0xDE, 0x60, 0x6A, 0x70, 0xE2, 0x78, 0x9C, 0xF8, 0xD9, 0x50, 0x12, 0x49, 0x02, 0xEB, 0x82, 0x02, 0x28, 0x44, +0x01, 0xEB, 0x82, 0x02, 0x18, 0x62, 0x5A, 0x60, 0x09, 0xE7, 0x0F, 0x46, 0x0C, 0x4A, 0x03, 0xEB, 0x83, 0x01, 0x02, 0xEB, +0xC1, 0x02, 0x10, 0x62, 0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xE2, 0x60, 0x46, 0x92, 0xF8, 0xD9, 0x70, +0xF0, 0xE7, 0x07, 0xF0, 0xFE, 0x07, 0x3A, 0x46, 0xB1, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x3C, 0x4C, 0x18, 0x00, +0x2C, 0x50, 0x18, 0x00, 0x9C, 0x4B, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x89, 0x46, 0xD0, 0xF8, +0xB8, 0x50, 0x89, 0x88, 0x99, 0xF8, 0x08, 0xA0, 0x90, 0xF8, 0x63, 0xB0, 0xD5, 0xF8, 0x24, 0x80, 0x2A, 0x4B, 0xB9, 0xF8, +0x06, 0x70, 0xD3, 0xF8, 0x54, 0x31, 0x29, 0x4E, 0xA1, 0xEB, 0x0A, 0x0A, 0x04, 0x46, 0x42, 0x46, 0xA0, 0xF8, 0xCC, 0xA0, +0x58, 0x46, 0x98, 0x47, 0xB9, 0xF8, 0x06, 0x30, 0x6A, 0x6A, 0x21, 0x6C, 0x23, 0x48, 0x03, 0xF1, 0xFF, 0x3C, 0x62, 0x44, +0xAA, 0x62, 0x99, 0xF8, 0x08, 0xC0, 0x06, 0xEB, 0xCB, 0x06, 0xDB, 0x43, 0x0B, 0xEB, 0x8B, 0x0B, 0x0C, 0xF1, 0x01, 0x0C, +0x00, 0xEB, 0x8B, 0x0B, 0x62, 0x44, 0x53, 0x44, 0x13, 0x44, 0x00, 0x20, 0xCB, 0xE9, 0x02, 0x23, 0x03, 0x37, 0xCB, 0xF8, +0x10, 0x00, 0x31, 0xB3, 0x94, 0xF8, 0xC0, 0x34, 0x0A, 0x79, 0x16, 0x49, 0xE3, 0xB1, 0x16, 0x4A, 0x16, 0x48, 0x13, 0x68, +0x12, 0x68, 0x1B, 0x02, 0xD2, 0xB2, 0x9B, 0xB2, 0x13, 0x43, 0x00, 0x22, 0x4B, 0x62, 0xC5, 0xE9, 0x0D, 0x21, 0xE8, 0x64, +0x94, 0xF8, 0x63, 0x30, 0x10, 0x4A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x01, 0x22, 0x2B, 0x62, 0x84, 0xF8, +0xD6, 0x20, 0x18, 0xF8, 0x07, 0x30, 0xF3, 0x70, 0xBD, 0xE8, 0xF8, 0x8F, 0x0A, 0x4B, 0x82, 0x42, 0x08, 0xBF, 0x19, 0x46, +0xDD, 0xE7, 0x04, 0x49, 0xDB, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x50, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, +0x84, 0x3C, 0x18, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x41, 0x00, 0x00, 0x01, 0x9C, 0x4B, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, +0x2D, 0xE9, 0xF8, 0x43, 0x4D, 0x4D, 0x90, 0xF8, 0x63, 0x30, 0xD0, 0xF8, 0xB8, 0x80, 0x05, 0xEB, 0xC3, 0x05, 0x04, 0x46, +0x2F, 0x79, 0x00, 0xF1, 0x6C, 0x06, 0xFF, 0xF7, 0x7D, 0xFD, 0xB0, 0xF8, 0xCC, 0x30, 0xB0, 0xF8, 0xCE, 0x20, 0x13, 0x44, +0x04, 0x33, 0xC8, 0xF8, 0x2C, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x54, 0xD1, 0x42, 0x4A, 0xD8, 0xF8, 0x24, 0x10, +0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x18, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xC8, 0x82, 0x94, 0xF8, 0xD7, 0x30, +0xAB, 0x70, 0x94, 0xF8, 0xDA, 0x90, 0xCB, 0xBB, 0xB9, 0xF1, 0x00, 0x0F, 0x31, 0xD1, 0x07, 0xF0, 0xFE, 0x07, 0x38, 0x4B, +0x1B, 0x78, 0x0B, 0xB1, 0x47, 0xF0, 0x01, 0x07, 0xEB, 0x78, 0x84, 0xF8, 0xD7, 0x30, 0x2F, 0x71, 0x94, 0xF8, 0xD7, 0x30, +0x94, 0xF8, 0xDB, 0x50, 0x01, 0x3B, 0x84, 0xF8, 0xD7, 0x30, 0xBD, 0xB1, 0x01, 0x3D, 0x94, 0xF8, 0xDC, 0x30, 0xED, 0xB2, +0x84, 0xF8, 0xDB, 0x50, 0x63, 0xB1, 0xD8, 0xF8, 0x24, 0x20, 0xD5, 0x54, 0x94, 0xF8, 0xDD, 0x30, 0x23, 0xB1, 0xD8, 0xF8, +0x24, 0x20, 0x94, 0xF8, 0xDB, 0x10, 0xD1, 0x54, 0x94, 0xF8, 0xDB, 0x50, 0x7D, 0xBB, 0x01, 0x23, 0x84, 0xF8, 0xDB, 0x30, +0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xE0, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, +0x01, 0x09, 0xCA, 0xE7, 0x19, 0xF0, 0x02, 0x09, 0x1A, 0xBF, 0x47, 0xF0, 0x01, 0x07, 0x4F, 0xF0, 0x01, 0x09, 0x07, 0xF0, +0xFE, 0x07, 0xC8, 0xE7, 0x90, 0xF8, 0xC1, 0x04, 0x05, 0xF0, 0x7E, 0xF9, 0x00, 0x28, 0xA4, 0xD0, 0x94, 0xF8, 0x63, 0x10, +0x15, 0x4A, 0xD8, 0xF8, 0x2C, 0x30, 0x01, 0xEB, 0x81, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x19, 0x18, 0x93, 0x68, 0xC8, 0xF8, +0x2C, 0x10, 0x01, 0x3B, 0x18, 0x44, 0xD0, 0x60, 0x93, 0xE7, 0x02, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x4E, 0x20, 0x94, 0xF8, +0x63, 0x70, 0x07, 0xF0, 0xE3, 0xF8, 0x07, 0x70, 0x45, 0x70, 0x07, 0xF0, 0x0F, 0xF9, 0x94, 0xF8, 0xDB, 0x30, 0x00, 0x2B, +0xBF, 0xD0, 0x20, 0x46, 0x31, 0x46, 0x06, 0xF0, 0xA3, 0xFC, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x50, 0x18, 0x00, +0x20, 0x62, 0x17, 0x00, 0x16, 0x2C, 0x17, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0xF8, 0xB5, 0x18, 0x4D, 0x18, 0x4F, 0x2E, 0x68, +0x04, 0x46, 0x36, 0xF8, 0x04, 0x1C, 0x00, 0x22, 0x40, 0x20, 0x07, 0xF0, 0x29, 0xF9, 0xD7, 0xF8, 0x78, 0x31, 0x29, 0x68, +0x20, 0x46, 0x98, 0x47, 0x2A, 0x68, 0x00, 0x23, 0x84, 0xF8, 0xDB, 0x30, 0x93, 0x7A, 0x84, 0xF8, 0xDC, 0x30, 0xD2, 0x7A, +0x84, 0xF8, 0xDD, 0x20, 0x0C, 0x3E, 0xD4, 0xF8, 0xB8, 0x20, 0x23, 0xB1, 0x52, 0x6A, 0xD3, 0x5C, 0x01, 0x33, 0x84, 0xF8, +0xDB, 0x30, 0x2B, 0x7A, 0x00, 0x22, 0x6A, 0x72, 0x13, 0xB1, 0xD7, 0xF8, 0x84, 0x31, 0x98, 0x47, 0x00, 0x23, 0x30, 0x46, +0x2B, 0x60, 0xBD, 0xE8, 0xF8, 0x40, 0x07, 0xF0, 0x17, 0xB9, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x70, 0xB5, 0x0E, 0x4D, 0x44, 0x7A, 0x0E, 0x4A, 0x0E, 0x49, 0x03, 0x46, 0x4F, 0xF4, 0x1A, 0x70, 0x00, 0xFB, 0x04, 0x50, +0x01, 0x25, 0x55, 0x72, 0x00, 0x25, 0x95, 0x72, 0x9A, 0x88, 0x68, 0x30, 0x1B, 0xF0, 0x0C, 0xFC, 0x08, 0x4A, 0x09, 0x4B, +0x4F, 0xF4, 0xA4, 0x60, 0x29, 0x46, 0x00, 0xFB, 0x04, 0x20, 0xD3, 0xF8, 0x94, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, +0xFC, 0x41, 0x18, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x14, 0x2A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x7E, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0x7D, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x6E, 0x68, 0x00, 0x2B, 0x83, 0xB0, +0x04, 0x46, 0x44, 0xDB, 0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0x4D, 0xD0, 0xDF, 0xF8, 0xE0, 0x91, 0x77, 0x4D, 0x78, 0x4E, +0x78, 0x4F, 0xDF, 0xF8, 0x00, 0xA2, 0xDF, 0xF8, 0x00, 0x82, 0x03, 0xE0, 0x05, 0xF5, 0x1E, 0x75, 0xB5, 0x42, 0x2F, 0xD0, +0x95, 0xF8, 0x25, 0x20, 0x4F, 0xF4, 0xA4, 0x61, 0x00, 0x2A, 0xF5, 0xD0, 0x95, 0xF8, 0x22, 0x30, 0x01, 0xFB, 0x03, 0x73, +0x9C, 0x42, 0xEF, 0xD1, 0x95, 0xF8, 0x23, 0x30, 0x0D, 0x2B, 0x9B, 0xBF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0x93, +0x00, 0x22, 0xD3, 0xF8, 0x58, 0x22, 0xDA, 0xF8, 0x10, 0x30, 0xA8, 0xEB, 0x03, 0x03, 0xD3, 0x42, 0xDE, 0xD5, 0x20, 0x46, +0xF2, 0xF7, 0x96, 0xFF, 0x00, 0x28, 0xD9, 0xD0, 0x63, 0x49, 0x95, 0xF8, 0x23, 0x00, 0x2A, 0x46, 0xF4, 0xF7, 0xAE, 0xFB, +0x00, 0x28, 0xD1, 0xD1, 0x95, 0xF8, 0x23, 0x10, 0x5F, 0x48, 0x08, 0xF0, 0x89, 0xFE, 0xCB, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x00, 0x2E, 0xB8, 0xD1, 0x5C, 0x49, 0x5C, 0x48, 0x4F, 0xF4, 0x3F, 0x72, 0x09, 0xF0, 0xF7, 0xF8, 0x6E, 0x68, +0x01, 0x3E, 0x6E, 0x60, 0x00, 0x2E, 0xB1, 0xD1, 0xDF, 0xF8, 0x74, 0xB1, 0xFC, 0xF7, 0xCC, 0xFF, 0x94, 0xF8, 0x63, 0x30, +0x9B, 0xF8, 0x00, 0x20, 0x03, 0xF1, 0x0A, 0x08, 0x00, 0x2A, 0x58, 0xD1, 0xDF, 0xF8, 0x2C, 0x91, 0x51, 0x4B, 0x1B, 0x78, +0x53, 0xB3, 0x08, 0xEB, 0x88, 0x02, 0x4F, 0xF4, 0x1E, 0x73, 0xC8, 0xEB, 0x02, 0x12, 0x4E, 0x4F, 0x01, 0x92, 0x03, 0xFB, +0x08, 0x9B, 0x4F, 0xF0, 0x00, 0x0A, 0xDB, 0xF8, 0x08, 0x32, 0x5F, 0xFA, 0x8A, 0xF6, 0x0B, 0xF5, 0x02, 0x78, 0x53, 0xB1, +0x40, 0x46, 0x07, 0xF0, 0xBB, 0xFC, 0xD7, 0xF8, 0x24, 0x34, 0x31, 0x46, 0x98, 0x47, 0xDB, 0xF8, 0x08, 0x32, 0x00, 0x2B, +0xF4, 0xD1, 0xDB, 0xF8, 0x30, 0x22, 0x00, 0x2A, 0x5B, 0xD1, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0x0B, 0xF1, +0x08, 0x0B, 0xE2, 0xD1, 0x3B, 0x4B, 0x1A, 0x70, 0xAB, 0x7A, 0x03, 0xBB, 0xEB, 0x68, 0x63, 0xB1, 0x39, 0x4F, 0xDF, 0xF8, +0xF8, 0x80, 0xD7, 0xF8, 0xD4, 0x61, 0x40, 0x46, 0x07, 0xF0, 0x9A, 0xFC, 0x0C, 0x30, 0xB0, 0x47, 0xEB, 0x68, 0x00, 0x2B, +0xF5, 0xD1, 0x94, 0xF8, 0x63, 0x00, 0x05, 0x44, 0x29, 0x7D, 0x19, 0xB1, 0x30, 0x4B, 0xD3, 0xF8, 0x90, 0x31, 0x98, 0x47, +0x94, 0xF8, 0xDB, 0x30, 0x01, 0x2B, 0x7F, 0xF4, 0x59, 0xAF, 0x20, 0x46, 0xFB, 0xF7, 0xBE, 0xFA, 0x54, 0xE7, 0x2A, 0x4F, +0x28, 0x68, 0xD7, 0xF8, 0x8C, 0x31, 0x98, 0x47, 0xD8, 0xE7, 0x04, 0x23, 0x32, 0x46, 0x0C, 0x21, 0x4A, 0x20, 0x06, 0xF0, +0xA5, 0xFF, 0x80, 0xF8, 0x00, 0x80, 0x46, 0x70, 0x86, 0x70, 0x06, 0xF0, 0xCF, 0xFF, 0x9B, 0xF8, 0x00, 0x30, 0xDF, 0xF8, +0x60, 0x90, 0x00, 0x2B, 0x96, 0xD0, 0x4F, 0xF4, 0x1E, 0x7A, 0x0A, 0xFB, 0x08, 0x9A, 0x9A, 0xF8, 0x31, 0x30, 0x9B, 0x07, +0x0B, 0xD5, 0x1A, 0x4F, 0x09, 0x22, 0x8A, 0xF8, 0x32, 0x20, 0xD7, 0xF8, 0x20, 0x33, 0x32, 0x46, 0x51, 0x46, 0x20, 0x46, +0x98, 0x47, 0x8A, 0xF8, 0x32, 0x60, 0x00, 0x23, 0x8B, 0xF8, 0x00, 0x30, 0x7E, 0xE7, 0x01, 0x98, 0x46, 0x30, 0x50, 0x44, +0x09, 0xEB, 0xC0, 0x00, 0x07, 0xF0, 0x4C, 0xFC, 0x0E, 0x4B, 0x31, 0x46, 0xD3, 0xF8, 0x24, 0x34, 0x98, 0x47, 0x0D, 0x48, +0x08, 0xF0, 0xDA, 0xFD, 0xFE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x18, 0x7E, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x51, 0xB1, 0x13, 0x00, 0xF8, 0x9F, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, +0xC8, 0x9F, 0x15, 0x00, 0x16, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xDC, 0x9F, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, +0xC0, 0xE1, 0xE4, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xE4, 0x9C, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4D, 0x0E, 0x4C, 0x18, 0x22, +0x00, 0x21, 0x28, 0x46, 0xE4, 0xF7, 0x42, 0xFB, 0x05, 0xF1, 0x0C, 0x00, 0x07, 0xF0, 0xCE, 0xFB, 0x20, 0x46, 0x04, 0xF0, +0xD9, 0xFF, 0x04, 0xF1, 0x26, 0x00, 0x04, 0xF0, 0xD5, 0xFF, 0x04, 0xF1, 0x4C, 0x00, 0x04, 0xF0, 0xD1, 0xFF, 0x04, 0xF1, +0x72, 0x00, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0xF0, 0xCB, 0xBF, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x64, 0x3E, 0x18, 0x00, +0x2D, 0xE9, 0xF8, 0x43, 0x90, 0xF8, 0x63, 0x30, 0x3F, 0x4D, 0x40, 0x49, 0x40, 0x4F, 0xDF, 0xF8, 0x1C, 0x91, 0x04, 0x46, +0x03, 0xEB, 0x83, 0x02, 0x3E, 0x48, 0x4F, 0xF4, 0x1A, 0x76, 0x03, 0xEB, 0x42, 0x02, 0x06, 0xFB, 0x03, 0x11, 0x05, 0xEB, +0xC2, 0x02, 0x00, 0xEB, 0x83, 0x13, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xFD, 0xF8, 0x94, 0xF8, 0x63, 0x30, 0x37, 0x49, +0xDF, 0xF8, 0xF0, 0xC0, 0x36, 0x48, 0x06, 0x22, 0xA4, 0xF8, 0xCE, 0x20, 0x00, 0x25, 0x01, 0xEB, 0xC3, 0x02, 0x4F, 0xF0, +0x05, 0x0E, 0xFF, 0x26, 0xA4, 0xF8, 0xD8, 0x60, 0x84, 0xF8, 0xD7, 0x50, 0xA4, 0xF8, 0xD0, 0x50, 0x84, 0xF8, 0xDA, 0x50, +0x04, 0x26, 0x01, 0xF8, 0x33, 0xE0, 0x56, 0x70, 0x94, 0xF8, 0xD7, 0x10, 0x91, 0x70, 0x01, 0x21, 0x15, 0x71, 0x55, 0x71, +0xD1, 0x70, 0x94, 0xF8, 0xD9, 0x10, 0x03, 0xEB, 0x83, 0x08, 0xC3, 0xEB, 0x83, 0x16, 0x00, 0xEB, 0x86, 0x00, 0x0C, 0xEB, +0xC8, 0x06, 0x01, 0x44, 0x07, 0xEB, 0x88, 0x03, 0x31, 0x62, 0x02, 0xEB, 0x0E, 0x01, 0xC6, 0xE9, 0x03, 0x15, 0x4C, 0xF8, +0x38, 0x90, 0xB2, 0x60, 0x73, 0x60, 0xB3, 0x61, 0x29, 0x46, 0xFC, 0x22, 0xC6, 0xF8, 0x14, 0x90, 0xE4, 0xF7, 0xCE, 0xFA, +0x07, 0xEB, 0x88, 0x03, 0x47, 0xF8, 0x28, 0x90, 0x5D, 0x60, 0x1D, 0x61, 0x94, 0xF8, 0xC0, 0x34, 0x93, 0xB1, 0x94, 0xF8, +0x63, 0x30, 0x15, 0x48, 0x15, 0x49, 0x03, 0xEB, 0xC3, 0x02, 0x03, 0xEB, 0x42, 0x02, 0x03, 0xEB, 0x83, 0x03, 0x01, 0xEB, +0x42, 0x01, 0x00, 0xEB, 0x83, 0x02, 0xC2, 0xE9, 0x01, 0x51, 0x40, 0xF8, 0x23, 0x90, 0x15, 0x61, 0xD4, 0xF8, 0xB8, 0x30, +0x0D, 0x49, 0x00, 0x22, 0x5A, 0x63, 0xDA, 0x64, 0x1A, 0x62, 0xD1, 0xF8, 0x88, 0x31, 0xC4, 0xE9, 0x30, 0x34, 0xBD, 0xE8, +0xF8, 0x83, 0x00, 0xBF, 0x9C, 0x40, 0x18, 0x00, 0xFC, 0x41, 0x18, 0x00, 0x4C, 0x40, 0x18, 0x00, 0x4C, 0x3F, 0x18, 0x00, +0x2C, 0x50, 0x18, 0x00, 0x3C, 0x4C, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xDE, 0xFA, 0xFE, 0xCA, 0x9C, 0x4B, 0x18, 0x00, 0x05, 0x4B, 0x5A, 0x68, 0x18, 0x60, 0x12, 0xB1, 0x01, 0x22, 0x9A, 0x72, +0x70, 0x47, 0x03, 0x4B, 0xD3, 0xF8, 0x8C, 0x31, 0x18, 0x47, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x06, 0x4B, 0x5A, 0x68, 0x1A, 0xB9, 0x06, 0x4B, 0xD3, 0xF8, 0xD4, 0x31, 0x18, 0x47, 0xA0, 0xF1, 0x0C, 0x01, 0x03, 0xF1, +0x0C, 0x00, 0x07, 0xF0, 0x05, 0xBB, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, +0x40, 0x4B, 0x41, 0x4A, 0x1B, 0x68, 0x94, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x3F, 0x4E, 0x00, 0x2B, 0x41, 0xDB, 0x75, 0x7A, +0x00, 0x2D, 0x4A, 0xD1, 0x3D, 0x4A, 0x35, 0x72, 0x17, 0x68, 0x7F, 0x01, 0x6C, 0xB1, 0xDF, 0xF8, 0xF8, 0x90, 0xDF, 0xF8, +0xF8, 0x80, 0xAA, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x04, 0xD0, 0x24, 0x68, 0x00, 0x2C, +0xF8, 0xD1, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF8, 0xD6, 0x30, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, +0xF2, 0xD0, 0x94, 0xF8, 0xD5, 0x20, 0x94, 0xF8, 0xD4, 0x30, 0x9A, 0x42, 0xEC, 0xD1, 0xD9, 0xF8, 0x70, 0x31, 0x20, 0x46, +0x98, 0x47, 0x20, 0xB1, 0x98, 0xF8, 0x00, 0x30, 0x01, 0x33, 0x88, 0xF8, 0x00, 0x30, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD0, +0xA7, 0xF1, 0x32, 0x02, 0x40, 0xF6, 0xB6, 0x33, 0x9A, 0x42, 0x18, 0xD8, 0xD5, 0xB9, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFE, +0x83, 0x46, 0xF0, 0xB9, 0x88, 0xF8, 0x00, 0x50, 0xD0, 0xE7, 0x73, 0x68, 0x00, 0x2B, 0xBA, 0xD0, 0x1D, 0x49, 0x1E, 0x48, +0x40, 0xF2, 0x2F, 0x42, 0x08, 0xF0, 0xFE, 0xFE, 0x75, 0x7A, 0x00, 0x2D, 0xB4, 0xD0, 0x01, 0x23, 0x33, 0x72, 0xBD, 0xE8, +0xF8, 0x8F, 0x20, 0x46, 0x02, 0xF0, 0x62, 0xFE, 0x88, 0xF8, 0x00, 0xA0, 0x24, 0x68, 0x4F, 0xF0, 0x00, 0x0B, 0x01, 0x25, +0x00, 0x2C, 0xB1, 0xD1, 0xB7, 0xE7, 0x94, 0xF8, 0x63, 0x30, 0x84, 0xF8, 0x88, 0x30, 0xFF, 0x23, 0x84, 0xF8, 0x89, 0x30, +0x04, 0x21, 0x04, 0xF1, 0x6C, 0x00, 0xF4, 0xF7, 0xDB, 0xF8, 0x73, 0x68, 0x08, 0xB1, 0x01, 0x33, 0x73, 0x60, 0x01, 0x2B, +0x02, 0xD0, 0x4F, 0xF0, 0x00, 0x0B, 0x9F, 0xE7, 0xFC, 0xF7, 0x58, 0xFD, 0x4F, 0xF0, 0x00, 0x0B, 0x9A, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xD8, 0x9C, 0x17, 0x00, 0x40, 0x80, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, +0x20, 0xA0, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x10, 0x2A, 0x17, 0x00, 0xF8, 0xB5, 0x27, 0x4F, 0x7B, 0x68, 0x04, 0x46, +0x0E, 0x46, 0x13, 0xB1, 0x3C, 0x44, 0x21, 0x75, 0xF8, 0xBD, 0x02, 0x29, 0x34, 0xD0, 0x03, 0x29, 0x21, 0xD0, 0x01, 0x29, +0x14, 0xD0, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x1F, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x04, 0x53, 0x3C, 0x44, 0x00, 0x22, 0x22, 0x75, 0x93, 0xF8, 0xC1, 0x04, 0x31, 0x46, 0xBD, 0xE8, 0xF8, 0x40, +0x04, 0xF0, 0xC6, 0xBE, 0x18, 0x4B, 0x19, 0x4A, 0x16, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x03, 0xEB, 0x81, 0x03, 0x02, 0xEB, +0x81, 0x02, 0x5A, 0x60, 0xE6, 0xE7, 0x12, 0x4D, 0x14, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x52, 0x00, 0xEB, +0xC0, 0x03, 0x00, 0xEB, 0x43, 0x03, 0x01, 0xEB, 0x43, 0x01, 0x92, 0xF8, 0xC1, 0x04, 0x04, 0xF0, 0x47, 0xFE, 0xD5, 0xE7, +0x0A, 0x4A, 0x09, 0x4D, 0x00, 0xEB, 0x80, 0x01, 0x02, 0xEB, 0x81, 0x02, 0x53, 0x60, 0xCD, 0xE7, 0x09, 0x49, 0x0A, 0x48, +0x04, 0x4D, 0x40, 0xF2, 0xC6, 0x42, 0x08, 0xF0, 0x71, 0xFE, 0xC5, 0xE7, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x4C, 0x40, 0x18, 0x00, 0xFC, 0x3E, 0x18, 0x00, 0x64, 0x3E, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x04, 0x23, 0x00, 0x22, 0x0C, 0x21, 0x44, 0x20, 0x06, 0xF0, 0x76, 0xFD, +0x23, 0x7E, 0x03, 0x70, 0x04, 0x2B, 0x09, 0xD0, 0x00, 0x23, 0x00, 0x22, 0x43, 0x70, 0xC2, 0x70, 0xA3, 0x7E, 0x83, 0x70, +0xBD, 0xE8, 0x10, 0x40, 0x06, 0xF0, 0x98, 0xBD, 0xE3, 0x89, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0xF1, 0xE7, 0x00, 0xBF, +0x38, 0xB5, 0x05, 0xF0, 0xE1, 0xFA, 0x0C, 0x23, 0x05, 0x46, 0x19, 0x46, 0x00, 0x22, 0x4F, 0x20, 0x06, 0xF0, 0x58, 0xFD, +0x2B, 0x88, 0x03, 0x80, 0x04, 0x46, 0x28, 0x46, 0x05, 0xF0, 0xDE, 0xFA, 0x10, 0x4A, 0x11, 0x4D, 0x11, 0x49, 0xA2, 0xFB, +0x00, 0x03, 0x9B, 0x09, 0x63, 0x60, 0x2B, 0x68, 0xA2, 0xFB, 0x03, 0x23, 0x9B, 0x09, 0x00, 0x22, 0xA3, 0x60, 0xA2, 0x70, +0x0A, 0x23, 0x0A, 0x68, 0x52, 0xB2, 0x01, 0x3B, 0x3A, 0xB9, 0x13, 0xF0, 0xFF, 0x03, 0xF8, 0xD1, 0x20, 0x46, 0xBD, 0xE8, +0x38, 0x40, 0x06, 0xF0, 0x67, 0xBD, 0xA2, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x06, 0xF0, 0x61, 0xBD, 0x00, 0xBF, +0xD3, 0x4D, 0x62, 0x10, 0x20, 0x02, 0x32, 0x40, 0x0C, 0xB2, 0x33, 0x40, 0x10, 0xB5, 0xC1, 0x89, 0x04, 0x46, 0x02, 0x23, +0x00, 0x22, 0x48, 0x20, 0x06, 0xF0, 0x22, 0xFD, 0x22, 0x7E, 0x42, 0x70, 0xA1, 0x7E, 0x05, 0x4A, 0x01, 0x70, 0x13, 0x68, +0x23, 0xF0, 0x04, 0x03, 0xBD, 0xE8, 0x10, 0x40, 0x13, 0x60, 0x06, 0xF0, 0x45, 0xBD, 0x00, 0xBF, 0x94, 0x40, 0x04, 0x40, +0xF0, 0xB5, 0x04, 0x68, 0x0E, 0x68, 0xA5, 0x1B, 0x32, 0xD4, 0x8E, 0x46, 0xAB, 0x42, 0x0C, 0xD2, 0xDE, 0xE9, 0x00, 0x76, +0xDC, 0x19, 0xF6, 0x1B, 0xED, 0x1A, 0xAB, 0x42, 0x06, 0xEB, 0x04, 0x07, 0xA4, 0x46, 0x1C, 0x44, 0xF8, 0xD3, 0xCE, 0xE9, +0x00, 0xC7, 0xB5, 0xEB, 0x53, 0x0F, 0x05, 0xD9, 0xDE, 0xE9, 0x00, 0x54, 0x1D, 0x44, 0x23, 0x44, 0xCE, 0xE9, 0x00, 0x53, +0x43, 0x68, 0x4C, 0x68, 0x1D, 0x1B, 0x00, 0x2D, 0x09, 0xDB, 0xB2, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x53, 0x60, 0x68, 0x1A, +0x00, 0x28, 0x17, 0xDA, 0x58, 0x1B, 0x15, 0x60, 0xF0, 0xBD, 0xAA, 0xB1, 0x05, 0x68, 0x09, 0x68, 0x54, 0x60, 0x6B, 0x1A, +0x00, 0x2B, 0xA8, 0xBF, 0x60, 0x1A, 0x18, 0xDB, 0x11, 0x60, 0xF0, 0xBD, 0x35, 0x1B, 0x86, 0x46, 0xCA, 0xE7, 0x00, 0x68, +0x0A, 0x68, 0x81, 0x1A, 0x00, 0x29, 0x0C, 0xDA, 0x18, 0x1A, 0xF0, 0xBD, 0x58, 0x1A, 0xF1, 0xE7, 0x00, 0x68, 0x0B, 0x68, +0xC1, 0x1A, 0x00, 0x29, 0xA8, 0xBF, 0xE0, 0x1A, 0xE0, 0xDA, 0x20, 0x1A, 0xF0, 0xBD, 0x98, 0x1A, 0xF0, 0xBD, 0x60, 0x1B, +0xD9, 0xE7, 0x00, 0xBF, 0x70, 0xB5, 0x19, 0x4E, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x05, 0x46, +0x93, 0xF8, 0x20, 0x20, 0x0A, 0xB9, 0x1B, 0x7C, 0xFB, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x50, 0x20, +0x12, 0xB9, 0x94, 0xF8, 0x40, 0x30, 0x7B, 0xB9, 0x0F, 0x4B, 0x9B, 0x68, 0x5B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0xFF, 0x20, +0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x08, 0xBF, 0x83, 0xF8, 0x4E, 0x00, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x70, 0xBD, +0x08, 0x4B, 0x01, 0x21, 0xD3, 0xF8, 0x08, 0x32, 0x28, 0x46, 0x98, 0x47, 0xE8, 0xE7, 0x05, 0x4B, 0x11, 0x46, 0xD3, 0xF8, +0x08, 0x32, 0x98, 0x47, 0xD9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0x48, 0x4B, 0x93, 0xF8, 0x5A, 0x30, 0x9B, 0xB0, 0x01, 0x2B, 0x08, 0x90, 0x40, 0xF2, 0x93, 0x81, +0xDF, 0xF8, 0x20, 0x91, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB7, 0x81, 0x08, 0x9C, +0x40, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x23, 0x6C, 0x94, 0xF8, 0x63, 0x20, 0xDA, 0x76, 0x94, 0xF8, +0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, 0xB9, 0x81, 0x02, 0x2A, 0x08, 0xBF, 0x08, 0x9A, 0x39, 0x48, 0x0A, 0xBF, 0xB2, 0xF8, +0xD2, 0x20, 0x4F, 0xF4, 0xC8, 0x32, 0x92, 0x02, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, 0x00, 0xF0, +0xB9, 0x81, 0xC3, 0xEB, 0xC3, 0x04, 0x00, 0xEB, 0x84, 0x04, 0xD9, 0x00, 0x24, 0x7E, 0xFF, 0x2C, 0x0D, 0xD1, 0x01, 0x2A, +0x02, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x02, 0x00, 0xEB, 0x82, 0x02, 0xD9, 0x00, 0x12, 0x7E, +0xFF, 0x2A, 0x00, 0xF0, 0x98, 0x82, 0x28, 0x4A, 0xCB, 0x1A, 0x00, 0xEB, 0x83, 0x03, 0x96, 0x68, 0x5B, 0x7E, 0x06, 0x93, +0x00, 0x2E, 0x00, 0xF0, 0x4A, 0x81, 0x0A, 0x9B, 0x4F, 0xF0, 0x00, 0x0B, 0x5B, 0x00, 0x0B, 0x93, 0x5F, 0x46, 0x03, 0xE0, +0x36, 0x68, 0x00, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0x33, 0x6C, 0x00, 0x2B, 0xF8, 0xD0, 0x08, 0x9A, 0x12, 0x6C, 0x93, 0x42, +0xF4, 0xD0, 0x96, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x93, 0x81, 0x02, 0x2B, 0x0A, 0xBF, 0xB6, 0xF8, 0xD2, 0x30, +0x4F, 0xF4, 0xC8, 0x3B, 0x4F, 0xEA, 0x83, 0x2B, 0x0B, 0x9B, 0x5B, 0x45, 0x04, 0xD8, 0x0A, 0x9B, 0xBB, 0xFB, 0xF3, 0xF2, +0xBB, 0xFB, 0xF2, 0xFB, 0x06, 0x9B, 0x4F, 0xEA, 0x5B, 0x00, 0xB0, 0xFB, 0xF3, 0xF5, 0x09, 0x95, 0xE5, 0xF7, 0x7C, 0xF8, +0x43, 0xF2, 0xB0, 0x64, 0x20, 0x44, 0xA8, 0x42, 0x00, 0xF2, 0x18, 0x81, 0x00, 0x2F, 0x00, 0xF0, 0x1C, 0x81, 0x06, 0x9B, +0x09, 0x9A, 0x03, 0xFB, 0x02, 0xF3, 0x07, 0x93, 0x10, 0xAC, 0x00, 0x25, 0x10, 0xE0, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x01, 0x35, 0xAF, 0x42, +0x04, 0xF1, 0x14, 0x04, 0x00, 0xF0, 0x03, 0x81, 0x22, 0x68, 0x5A, 0x45, 0xF6, 0xD1, 0x72, 0x6A, 0x0C, 0x92, 0xD4, 0xE9, +0x02, 0x01, 0x0D, 0xF1, 0x38, 0x0C, 0x0D, 0xF1, 0x30, 0x0A, 0x02, 0xF5, 0x1C, 0x5E, 0x8C, 0xE8, 0x03, 0x00, 0x0E, 0xF1, +0x10, 0x0E, 0x52, 0x46, 0x61, 0x46, 0x50, 0x46, 0x5B, 0x46, 0xCD, 0xF8, 0x34, 0xE0, 0xFF, 0xF7, 0xB7, 0xFE, 0xD9, 0xF8, +0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x80, 0x46, 0xC0, 0xF2, 0x2D, 0x81, 0x06, 0x9B, 0x5A, 0x1E, 0x07, 0x9B, +0xB3, 0xFB, 0xF2, 0xF2, 0x05, 0x92, 0xE5, 0xF7, 0x31, 0xF8, 0x05, 0x9A, 0x61, 0x68, 0xA2, 0xF5, 0x7A, 0x62, 0x12, 0x1A, +0x8A, 0x42, 0x38, 0xBF, 0x0A, 0x46, 0x42, 0x45, 0xC6, 0xD9, 0x05, 0x92, 0x05, 0xEB, 0x85, 0x05, 0xE5, 0xF7, 0x22, 0xF8, +0x1A, 0xAB, 0x03, 0xEB, 0x85, 0x05, 0x96, 0xF8, 0x63, 0x10, 0x05, 0x9A, 0x55, 0xF8, 0x18, 0x3C, 0x36, 0x68, 0x01, 0x24, +0x8C, 0x40, 0x02, 0x44, 0x9A, 0xE8, 0x03, 0x00, 0x23, 0x43, 0x02, 0xF5, 0x7A, 0x62, 0xA5, 0xF1, 0x20, 0x04, 0x84, 0xE8, +0x03, 0x00, 0x45, 0xF8, 0x24, 0x2C, 0x45, 0xF8, 0x18, 0x3C, 0x00, 0x2E, 0x7F, 0xF4, 0x66, 0xAF, 0x00, 0x2F, 0x00, 0xF0, +0xA2, 0x80, 0xDF, 0xF8, 0x88, 0xA3, 0xDD, 0xF8, 0x20, 0xB0, 0x05, 0x96, 0x09, 0x96, 0x0B, 0x96, 0x07, 0x96, 0x12, 0xAC, +0x06, 0x97, 0x54, 0xF8, 0x08, 0x7C, 0x0A, 0x9B, 0xB7, 0xFB, 0xF3, 0xF2, 0x03, 0xFB, 0x12, 0x72, 0x00, 0x2A, 0x00, 0xF0, +0x3A, 0x81, 0xE4, 0xF7, 0xED, 0xFF, 0x54, 0xE9, 0x01, 0x63, 0xA3, 0xF5, 0xBB, 0x53, 0x10, 0x3B, 0x1D, 0x1A, 0xE4, 0xF7, +0xE5, 0xFF, 0xDA, 0xF8, 0x10, 0x30, 0x54, 0xF8, 0x08, 0x1C, 0xEB, 0x1A, 0x06, 0xF5, 0x7A, 0x66, 0x00, 0x2B, 0x06, 0xEB, +0x00, 0x07, 0xC0, 0xF2, 0xEA, 0x80, 0xDA, 0xF8, 0x10, 0x20, 0x6B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0x80, 0xF2, 0xDB, 0x80, +0xCD, 0xE9, 0x01, 0x75, 0xBE, 0x4B, 0x00, 0x91, 0xD3, 0xF8, 0x04, 0x32, 0xDF, 0xF8, 0x1C, 0x83, 0x1E, 0x46, 0x00, 0x22, +0xFF, 0x23, 0x01, 0x21, 0x58, 0x46, 0xB0, 0x47, 0xEB, 0x19, 0xB9, 0x4E, 0x25, 0x60, 0x63, 0x60, 0x07, 0x46, 0x00, 0x25, +0xA3, 0x68, 0xEB, 0x40, 0xDB, 0x07, 0x22, 0xD5, 0x72, 0x6A, 0x54, 0xF8, 0x08, 0x3C, 0x0E, 0x92, 0x02, 0xF5, 0x1C, 0x5C, +0x0C, 0xF1, 0x10, 0x0C, 0x00, 0x22, 0x0E, 0xA9, 0x20, 0x46, 0xCD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0x21, 0xFE, 0xD9, 0xF8, +0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC3, 0x80, 0x0E, 0x9A, 0x63, 0x68, 0x9B, 0xF8, 0x63, 0x10, +0x86, 0xF8, 0x4E, 0x10, 0x9B, 0x1A, 0x00, 0x22, 0x73, 0x65, 0x86, 0xF8, 0x4F, 0x70, 0xA6, 0xF8, 0x58, 0x20, 0x01, 0x35, +0x04, 0x2D, 0x06, 0xF5, 0xA4, 0x66, 0xD3, 0xD1, 0x05, 0x9B, 0x06, 0x9A, 0x01, 0x33, 0x9A, 0x42, 0x05, 0x93, 0x04, 0xF1, +0x14, 0x04, 0x90, 0xD1, 0x07, 0x9B, 0x33, 0xB3, 0x0B, 0x9B, 0x0A, 0x99, 0x03, 0xF5, 0x9C, 0x50, 0x09, 0x9B, 0x08, 0x30, +0x83, 0x42, 0xA8, 0xBF, 0x03, 0x46, 0x18, 0x46, 0x01, 0xEB, 0xD1, 0x73, 0xB0, 0xEB, 0x63, 0x0F, 0x4F, 0xEA, 0x63, 0x02, +0x00, 0xF3, 0x18, 0x81, 0x52, 0x42, 0x82, 0x42, 0xC4, 0xBF, 0x0A, 0x9B, 0xC0, 0x18, 0x8F, 0x4B, 0xD3, 0xF8, 0x6C, 0x31, +0x98, 0x47, 0x08, 0x9C, 0x8E, 0x4A, 0x94, 0xF8, 0x4D, 0x30, 0x20, 0x65, 0x43, 0xF0, 0x20, 0x03, 0x01, 0x21, 0x84, 0xF8, +0x4D, 0x30, 0x82, 0xF8, 0x31, 0x10, 0x1B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xE4, 0xF7, 0x5C, 0xFF, 0x03, 0x19, 0x09, 0x93, +0x00, 0x2F, 0x7F, 0xF4, 0xE4, 0xAE, 0xD9, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7B, 0xDB, 0x1A, 0xAB, +0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, 0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, +0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, 0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x3C, 0x44, 0x1A, 0xAB, +0x03, 0xEB, 0x84, 0x04, 0x01, 0x23, 0x93, 0x40, 0x01, 0x37, 0x44, 0xF8, 0x18, 0x3C, 0x8F, 0xE6, 0x03, 0x6C, 0xDB, 0x7E, +0xFF, 0x2B, 0x3F, 0xF4, 0x44, 0xAE, 0x90, 0xF8, 0x63, 0x20, 0x9A, 0x42, 0x3F, 0xF4, 0x3F, 0xAE, 0x6E, 0x49, 0x6F, 0x48, +0x40, 0xF2, 0xA7, 0x22, 0x08, 0xF0, 0x8E, 0xFB, 0x37, 0xE6, 0x08, 0x9A, 0x6C, 0x49, 0x92, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, +0x1E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x6A, 0x48, 0x92, 0x68, 0x0A, 0x92, 0x1A, 0x7E, 0x02, 0x2A, 0x02, 0xF1, 0x01, 0x03, +0x7F, 0xF4, 0x47, 0xAE, 0x03, 0x7E, 0xFF, 0x2B, 0x40, 0xF0, 0xEE, 0x80, 0x01, 0x23, 0x4D, 0xE6, 0x06, 0x9B, 0x01, 0x2B, +0x3F, 0xF6, 0xCF, 0xAE, 0x5D, 0x49, 0x61, 0x48, 0x40, 0xF2, 0xD3, 0x22, 0x08, 0xF0, 0x6C, 0xFB, 0xC7, 0xE6, 0x5C, 0x4A, +0x96, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x08, 0xB0, 0x6A, 0xE6, 0xDA, 0xF8, +0x10, 0x20, 0x1D, 0x46, 0x5B, 0x1A, 0x9A, 0x1A, 0x00, 0x2A, 0xF8, 0xDA, 0x1C, 0xE7, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, +0xEB, 0x1A, 0x00, 0x2B, 0xBF, 0xF6, 0x16, 0xAF, 0xDA, 0xF8, 0x10, 0x30, 0x0D, 0x44, 0xEB, 0x1A, 0x00, 0x2B, 0xF2, 0xDB, +0x0E, 0xE7, 0x96, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x38, 0xAF, 0x47, 0x49, 0x4F, 0xF4, 0x58, 0x72, 0x40, 0x46, +0x08, 0xF0, 0x40, 0xFB, 0x30, 0xE7, 0x02, 0x2F, 0x00, 0xF0, 0x98, 0x80, 0x1A, 0xAB, 0x07, 0xEB, 0x87, 0x02, 0x70, 0x6A, +0x03, 0xEB, 0x82, 0x02, 0x09, 0x9B, 0x42, 0xF8, 0x28, 0xBC, 0x00, 0xF5, 0x1C, 0x51, 0x42, 0xE9, 0x09, 0x30, 0x10, 0x31, +0x42, 0xF8, 0x1C, 0x1C, 0xBC, 0x00, 0x96, 0xF8, 0x63, 0x20, 0x1F, 0x2A, 0x7F, 0xF6, 0x7E, 0xAF, 0x37, 0x49, 0x3C, 0x48, +0x40, 0xF2, 0xED, 0x22, 0x08, 0xF0, 0x20, 0xFB, 0x74, 0xE7, 0x3A, 0x4B, 0xDA, 0xF8, 0x10, 0x00, 0x19, 0x68, 0x0A, 0x9B, +0x00, 0xEB, 0x41, 0x10, 0x9F, 0x42, 0x28, 0xBF, 0x1F, 0x46, 0x00, 0xF5, 0x1C, 0x55, 0x10, 0x35, 0x3B, 0x46, 0x0E, 0xA9, +0x0E, 0x90, 0x20, 0x46, 0x0F, 0x95, 0xFF, 0xF7, 0x17, 0xFD, 0x0E, 0x9E, 0x23, 0x68, 0x54, 0xF8, 0x04, 0x5C, 0x9A, 0x1B, +0x00, 0x2A, 0x1D, 0x44, 0x62, 0x68, 0xA5, 0xF5, 0xFA, 0x65, 0xB4, 0xBF, 0xB6, 0x1A, 0x3E, 0x1A, 0xAD, 0x1A, 0xE4, 0xF7, +0x91, 0xFE, 0x00, 0xF5, 0x7A, 0x60, 0xA8, 0x42, 0x34, 0xDC, 0x54, 0xE9, 0x02, 0x78, 0xE4, 0xF7, 0x89, 0xFE, 0xA7, 0xF5, +0x5A, 0x53, 0x30, 0x3B, 0xA3, 0xEB, 0x08, 0x03, 0x07, 0x9A, 0xAD, 0x1B, 0x1B, 0x1A, 0x2B, 0x44, 0xDA, 0xB1, 0x09, 0x9A, +0xAA, 0x42, 0x1F, 0xDB, 0x0B, 0x9A, 0x9A, 0x42, 0x0A, 0xDD, 0x0A, 0x9A, 0x13, 0x44, 0x15, 0x44, 0x09, 0x9A, 0xAA, 0x42, +0xFF, 0xF6, 0x83, 0xAE, 0x0B, 0x9A, 0x9A, 0x42, 0x3F, 0xF7, 0x7F, 0xAE, 0x0B, 0x9A, 0xAA, 0x42, 0xB8, 0xBF, 0x2A, 0x46, +0x0B, 0x92, 0x09, 0x9A, 0x9A, 0x42, 0xA8, 0xBF, 0x1A, 0x46, 0x09, 0x92, 0x73, 0xE6, 0x09, 0x93, 0x01, 0x23, 0x0B, 0x95, +0x07, 0x93, 0x6E, 0xE6, 0x40, 0x1A, 0xEA, 0xE6, 0x0A, 0x9A, 0xAD, 0x1A, 0x9B, 0x1A, 0xE1, 0xE7, 0xE4, 0xF7, 0x56, 0xFE, +0x00, 0xF5, 0x7A, 0x65, 0xC5, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x48, 0xA0, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xD0, 0xA0, 0x15, 0x00, +0x00, 0xA1, 0x15, 0x00, 0x40, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x10, 0xA1, 0x15, 0x00, 0x40, 0xF2, 0xE7, 0x22, +0x14, 0x49, 0x15, 0x48, 0x08, 0xF0, 0x9E, 0xFA, 0xD9, 0xF8, 0x00, 0x20, 0x09, 0x9B, 0xB2, 0xF9, 0x00, 0x20, 0xCD, 0xF8, +0x68, 0xB0, 0x1B, 0x93, 0x73, 0x6A, 0x1C, 0x93, 0x03, 0xF5, 0x1C, 0x53, 0x10, 0x33, 0x00, 0x2A, 0x1D, 0x93, 0x4F, 0xF0, +0x08, 0x04, 0xFF, 0xF6, 0x60, 0xAF, 0xDF, 0xE6, 0x00, 0x23, 0x19, 0x46, 0x67, 0xE5, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0xAE, 0x22, 0x08, 0xF0, 0x7B, 0xFA, 0x00, 0x23, +0x5B, 0x7E, 0xFF, 0xDE, 0x70, 0x79, 0x15, 0x00, 0xE4, 0xA0, 0x15, 0x00, 0xC4, 0xA0, 0x15, 0x00, 0x0A, 0x4B, 0x03, 0xF1, +0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDA, 0x7E, 0xFF, 0x2A, 0x04, 0xD1, 0x1C, 0x33, 0x8B, 0x42, 0xF6, 0xD1, +0x00, 0x20, 0x70, 0x47, 0x04, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x60, 0x01, 0x20, 0x70, 0x47, +0x90, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0E, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x05, 0x46, +0x00, 0x28, 0x54, 0xD0, 0x07, 0x46, 0x00, 0x2C, 0x3A, 0xD0, 0xA3, 0x7A, 0xFF, 0x2B, 0x37, 0xD0, 0x3D, 0x4A, 0x23, 0x7A, +0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x5E, 0xD0, 0x02, 0x2A, 0x52, 0xD0, +0x4F, 0xF4, 0x48, 0x4A, 0x4F, 0xF4, 0xC8, 0x39, 0x60, 0x68, 0xDF, 0xF8, 0xE0, 0x80, 0x00, 0xF5, 0x1C, 0x5B, 0xE4, 0xF7, +0xC9, 0xFD, 0x0B, 0xF1, 0x10, 0x0B, 0x03, 0x46, 0xE1, 0x7A, 0xD8, 0xF8, 0xFC, 0x21, 0x28, 0x46, 0x9B, 0x44, 0x90, 0x47, +0x83, 0x1B, 0x13, 0xEB, 0x0A, 0x0F, 0x05, 0xD5, 0xAA, 0xEB, 0x06, 0x03, 0x48, 0x44, 0xC3, 0x42, 0xFC, 0xD4, 0x83, 0x1B, +0x00, 0x2B, 0x0B, 0xF5, 0x0C, 0x53, 0xB8, 0xBF, 0x00, 0xF1, 0xFF, 0x36, 0x28, 0x33, 0x9B, 0x1B, 0x00, 0x2B, 0x31, 0xDB, +0x0B, 0xF5, 0x7A, 0x60, 0x80, 0x1B, 0x06, 0xE0, 0xE4, 0xF7, 0xA6, 0xFD, 0xDF, 0xF8, 0x8C, 0x80, 0x00, 0xF5, 0x5A, 0x50, +0x30, 0x30, 0x00, 0x22, 0x01, 0x23, 0xCD, 0xE9, 0x01, 0x06, 0xD8, 0xF8, 0x04, 0x42, 0x00, 0x92, 0x38, 0x46, 0x19, 0x46, +0xA0, 0x47, 0xFF, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x17, 0x4B, 0x03, 0xF1, 0x54, 0x01, +0x1A, 0x7E, 0xFF, 0x2A, 0x02, 0xD0, 0xDF, 0x7E, 0xFF, 0x2F, 0x1C, 0xD1, 0x1C, 0x33, 0x99, 0x42, 0xF6, 0xD1, 0x00, 0x20, +0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB3, 0xF8, 0xD2, 0x30, 0x4F, 0xEA, 0x83, 0x29, 0x4F, 0xEA, 0x43, 0x2A, 0xA9, 0xE7, +0x41, 0xF2, 0x88, 0x30, 0xD5, 0xE7, 0x93, 0xF8, 0x6C, 0x30, 0x0A, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, +0xD3, 0xF8, 0x08, 0x90, 0x4F, 0xEA, 0x59, 0x0A, 0x9A, 0xE7, 0x03, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x37, +0x7F, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x70, 0xB5, 0x0C, 0x46, 0x02, 0x7A, 0x17, 0x49, 0x23, 0x7A, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x02, 0x12, 0x05, 0xFB, +0x03, 0x13, 0x12, 0x6C, 0x1B, 0x6C, 0x9A, 0x42, 0x0D, 0xD0, 0x45, 0x68, 0xE4, 0xF7, 0x4A, 0xFD, 0x64, 0x68, 0x06, 0x46, +0xE4, 0xF7, 0x46, 0xFD, 0x2A, 0x1B, 0x06, 0xD4, 0x63, 0x1B, 0x00, 0x2B, 0x0C, 0xDB, 0xA5, 0x42, 0x08, 0xD0, 0x00, 0x20, +0x70, 0xBD, 0xA4, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x5B, 0x1B, 0x9E, 0x1B, 0x00, 0x2E, 0xF1, 0xDA, 0x01, 0x20, 0x70, 0xBD, +0xA2, 0xF5, 0x5A, 0x53, 0x30, 0x3B, 0x1B, 0x1A, 0x00, 0x2B, 0xF7, 0xDB, 0xA5, 0x42, 0xEC, 0xD1, 0xF4, 0xE7, 0x00, 0xBF, +0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x83, 0xB0, 0x0D, 0x46, 0x00, 0xF1, 0x44, 0x08, 0x91, 0x46, +0x22, 0xB9, 0x90, 0xF8, 0x4D, 0x30, 0xDB, 0x07, 0x00, 0xF1, 0xA3, 0x80, 0xDF, 0xF8, 0x64, 0xA1, 0xD7, 0xF8, 0x40, 0xB0, +0xDA, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x79, 0xD1, 0xDA, 0xF8, 0x50, 0x30, 0x0B, 0xB1, 0x9B, 0x45, 0x2E, 0xD1, 0xBD, 0x64, +0xE4, 0xF7, 0x0A, 0xFD, 0x05, 0xF5, 0x5A, 0x53, 0xDA, 0xF8, 0x10, 0x40, 0x2F, 0x33, 0x1E, 0x18, 0x00, 0x2C, 0x00, 0xF0, +0x88, 0x80, 0xDF, 0xF8, 0x38, 0xA1, 0x0B, 0xE0, 0xDA, 0xF8, 0xA0, 0x30, 0x98, 0x47, 0xD3, 0x46, 0x40, 0xBB, 0x63, 0x68, +0xEB, 0x1A, 0x00, 0x2B, 0x08, 0xDB, 0x24, 0x68, 0x00, 0x2C, 0x78, 0xD0, 0x63, 0x68, 0xF3, 0x1A, 0x00, 0x2B, 0x21, 0x46, +0x40, 0x46, 0xED, 0xDA, 0x3F, 0x48, 0x42, 0x46, 0x21, 0x46, 0x06, 0xF0, 0xD9, 0xFD, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, +0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x54, 0x60, 0xE4, 0xF7, 0xDA, 0xFC, +0xAE, 0x1B, 0xA6, 0xF5, 0x7A, 0x66, 0x30, 0x1A, 0xC4, 0x0F, 0x00, 0x2C, 0xC5, 0xD0, 0xDF, 0xF8, 0xDC, 0xB0, 0x00, 0x24, +0x97, 0xF8, 0xC0, 0x34, 0x4B, 0xB1, 0x31, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, +0x70, 0x30, 0x01, 0x2B, 0x1D, 0xD0, 0x97, 0xF8, 0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x7B, 0xB1, 0x02, 0x2B, 0x0A, 0xBF, +0xB7, 0xF8, 0xD2, 0x10, 0x4F, 0xF4, 0xC8, 0x31, 0x89, 0x02, 0x09, 0xF1, 0x01, 0x02, 0x29, 0x44, 0x38, 0x46, 0x23, 0x46, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x22, 0x4A, 0x97, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, +0x03, 0x23, 0x99, 0x68, 0xED, 0xE7, 0xDB, 0xF8, 0x90, 0x30, 0x22, 0x46, 0x29, 0x46, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, +0x62, 0x30, 0xDB, 0xF8, 0x2C, 0x40, 0x00, 0x2B, 0xDA, 0xD1, 0xE9, 0xE7, 0xDA, 0xF8, 0x24, 0x20, 0x01, 0x92, 0x56, 0x68, +0xE4, 0xF7, 0x92, 0xFC, 0x01, 0x9A, 0x93, 0x68, 0x06, 0xF5, 0x7A, 0x66, 0x9B, 0x45, 0x06, 0xEB, 0x00, 0x04, 0x0A, 0xD0, +0xE4, 0xF7, 0x88, 0xFC, 0x01, 0x9A, 0xD3, 0x68, 0x04, 0xF5, 0x7A, 0x64, 0x04, 0x44, 0x13, 0xB1, 0x04, 0xF5, 0x1C, 0x54, +0x10, 0x34, 0x2C, 0x1B, 0xE4, 0x0F, 0x00, 0x2C, 0x3F, 0xF4, 0x6D, 0xAF, 0xA5, 0xE7, 0x00, 0x24, 0x8A, 0xE7, 0x05, 0x48, +0x41, 0x46, 0x06, 0xF0, 0xD9, 0xFC, 0x97, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x51, 0xE7, +0x40, 0x9D, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x81, 0x46, 0x1A, 0x48, 0x88, 0x46, 0x17, 0x46, 0x06, 0xF0, 0xB4, 0xFC, 0x18, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0C, 0xDB, 0x16, 0x4D, 0x28, 0x46, 0x21, 0x46, 0x50, 0xF8, 0x20, 0x6F, +0xE7, 0x60, 0xC4, 0xE9, 0x01, 0x98, 0x06, 0xF0, 0x5F, 0xFC, 0x4E, 0xB1, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x28, 0xF0, 0xD1, +0x0F, 0x49, 0x10, 0x48, 0xD6, 0x22, 0x08, 0xF0, 0xA9, 0xF8, 0xEA, 0xE7, 0x0E, 0x4B, 0x61, 0x68, 0x1B, 0x69, 0xAC, 0x64, +0xCB, 0x1A, 0x14, 0x2B, 0x07, 0xD4, 0x0C, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, +0x18, 0x47, 0x6B, 0x6C, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x48, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x30, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA1, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0xC1, 0x4B, 0xDF, 0xF8, 0x0C, 0x83, 0x1D, 0x69, 0xD0, 0xF8, 0x40, 0x90, 0x2F, 0x7A, 0x6B, 0x68, +0x89, 0xB0, 0x4F, 0xF4, 0xA4, 0x6A, 0xA3, 0xF5, 0x7A, 0x63, 0x0A, 0xFB, 0x07, 0x8B, 0x0C, 0x46, 0x03, 0x92, 0x01, 0x93, +0x06, 0x46, 0xE4, 0xF7, 0x05, 0xFC, 0x01, 0x9B, 0xDB, 0xF8, 0x40, 0x20, 0x1B, 0x1B, 0x1B, 0x1A, 0x4A, 0x45, 0x01, 0x93, +0x66, 0xD0, 0x6B, 0x68, 0x02, 0x93, 0xE4, 0xF7, 0xF9, 0xFB, 0x02, 0x9B, 0x99, 0xF8, 0x1B, 0x20, 0x04, 0x90, 0xA3, 0xF5, +0x7A, 0x63, 0x19, 0x1A, 0xFF, 0x2A, 0x02, 0x91, 0x20, 0xD1, 0x96, 0xF8, 0x4E, 0x60, 0x05, 0x93, 0xFF, 0x2E, 0x40, 0xF0, +0x8F, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x18, 0x46, 0x10, 0x44, 0xB2, 0xEB, 0x50, 0x0F, 0x4F, 0xEA, 0x50, 0x03, 0x00, 0xF2, +0xA9, 0x80, 0x03, 0x9A, 0xA4, 0x4E, 0xA4, 0x1A, 0x1C, 0x44, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x2A, 0x46, +0xD6, 0xF8, 0x88, 0x30, 0x39, 0x6C, 0x20, 0x46, 0x98, 0x47, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x0A, 0xFB, 0x02, 0x8A, +0x50, 0x46, 0x07, 0xAA, 0x06, 0xA9, 0xDB, 0xF8, 0x40, 0x90, 0x01, 0x93, 0x03, 0xF0, 0xE8, 0xFB, 0x83, 0x46, 0x00, 0x28, +0x00, 0xF0, 0x8C, 0x80, 0x07, 0x9C, 0x02, 0x99, 0x01, 0x9B, 0x0A, 0x1B, 0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x81, 0x06, 0x9A, +0xD1, 0x1A, 0x04, 0x9B, 0xD9, 0x42, 0x7D, 0xD5, 0x14, 0x1B, 0xE4, 0xF7, 0xB1, 0xFB, 0x00, 0xF5, 0x0C, 0x50, 0x28, 0x30, +0x84, 0x42, 0x40, 0xF2, 0x3B, 0x81, 0x8B, 0x4E, 0x07, 0x98, 0xD6, 0xF8, 0x88, 0x30, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, +0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x9F, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0x20, 0x1A, 0xDA, 0xF8, 0x40, 0x10, +0x02, 0x9C, 0x00, 0x22, 0xC8, 0x47, 0xBA, 0xE7, 0xE4, 0xF7, 0x94, 0xFB, 0x01, 0x9B, 0xA3, 0xF5, 0x7A, 0x62, 0x12, 0x1A, +0x41, 0xF2, 0x87, 0x33, 0x9A, 0x42, 0x01, 0x92, 0xB9, 0xDD, 0x6F, 0x68, 0xE4, 0xF7, 0x88, 0xFB, 0x99, 0xF8, 0x1B, 0xB0, +0x02, 0x97, 0x3B, 0x1A, 0xBB, 0xF1, 0xFF, 0x0F, 0x01, 0x9A, 0x04, 0x90, 0xA3, 0xF5, 0x7A, 0x67, 0x70, 0xD0, 0x0A, 0xFB, +0x0B, 0x80, 0x07, 0xAA, 0x06, 0xA9, 0x03, 0xF0, 0x9B, 0xFB, 0x00, 0x28, 0x40, 0xF0, 0xE6, 0x80, 0xE4, 0xF7, 0x72, 0xFB, +0x06, 0x9E, 0xC6, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0xF5, 0x7A, 0x60, 0x22, 0x44, 0x12, 0xEB, 0x40, 0x03, 0x00, 0xF1, +0xF9, 0x80, 0xE4, 0xF7, 0x65, 0xFB, 0x07, 0x9C, 0x04, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x8C, 0xD5, +0x64, 0x4E, 0xDF, 0xF8, 0x98, 0xA1, 0x5F, 0xE0, 0x07, 0xAA, 0x0A, 0xFB, 0x06, 0x80, 0x06, 0xA9, 0x03, 0xF0, 0x78, 0xFB, +0x83, 0x46, 0xE4, 0xF7, 0x51, 0xFB, 0x06, 0x9A, 0xA2, 0xF5, 0x7A, 0x62, 0x10, 0x1A, 0xDD, 0xE9, 0x04, 0x23, 0x06, 0x90, +0xA2, 0xEB, 0x03, 0x0A, 0xBB, 0xF1, 0x00, 0x0F, 0x05, 0xD1, 0x02, 0x9B, 0x10, 0xEB, 0x0A, 0x0F, 0x54, 0xBF, 0x1C, 0x46, +0x04, 0x46, 0xE4, 0xF7, 0x3D, 0xFB, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0x53, 0x44, 0xC3, 0x42, 0x65, 0xD4, +0x50, 0x4E, 0x58, 0xE7, 0x06, 0x9E, 0x02, 0x9B, 0x9A, 0x1B, 0x00, 0x2A, 0xF8, 0xDB, 0xE4, 0xF7, 0x2D, 0xFB, 0x00, 0xF5, +0x0C, 0x50, 0x36, 0x1B, 0x28, 0x30, 0x86, 0x42, 0x49, 0x4E, 0x11, 0xD9, 0x49, 0x46, 0x20, 0x46, 0x5A, 0x46, 0xD6, 0xF8, +0x88, 0x30, 0x98, 0x47, 0x06, 0x9C, 0xD6, 0xF8, 0x88, 0x90, 0xE4, 0xF7, 0x1B, 0xFB, 0xA4, 0xF5, 0x7A, 0x64, 0xDA, 0xF8, +0x40, 0x10, 0x20, 0x1A, 0x5A, 0x46, 0xC8, 0x47, 0x07, 0x9C, 0x02, 0x9B, 0x1B, 0x1B, 0x00, 0x2B, 0xBF, 0xF6, 0x33, 0xAF, +0x02, 0x9C, 0x30, 0xE7, 0x96, 0xF8, 0x4E, 0x00, 0x01, 0x93, 0xFF, 0x28, 0x51, 0xD1, 0x03, 0x99, 0x0A, 0x44, 0xB1, 0xEB, +0x52, 0x0F, 0x4F, 0xEA, 0x52, 0x03, 0xA1, 0xD8, 0x03, 0x9A, 0x35, 0x4E, 0xDF, 0xF8, 0xD8, 0xA0, 0xA4, 0x1A, 0x1C, 0x44, +0x99, 0xF8, 0x18, 0x30, 0xD6, 0xF8, 0x88, 0x80, 0x02, 0x2B, 0x03, 0xF1, 0x01, 0x01, 0x7B, 0xD0, 0xC1, 0xEB, 0xC1, 0x01, +0x0A, 0xEB, 0x81, 0x01, 0x0A, 0x7E, 0xFF, 0x2A, 0x0E, 0xD1, 0x01, 0x2B, 0x03, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, +0xC3, 0xEB, 0xC3, 0x03, 0x0A, 0xEB, 0x83, 0x0A, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x14, 0xBF, 0x51, 0x46, 0x00, 0x21, +0x20, 0x46, 0x00, 0x22, 0xC0, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x2A, 0x46, 0x49, 0x46, 0x38, 0x46, 0x98, 0x47, 0x09, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x83, 0x1B, 0x4E, 0x19, 0x6C, 0xD6, 0xF8, 0x88, 0x30, +0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0xD6, 0xF8, 0x88, 0x30, 0x07, 0x98, 0x49, 0x46, 0x00, 0x22, 0x98, 0x47, 0xBB, 0xF1, +0x00, 0x0F, 0xAD, 0xD0, 0x06, 0x9C, 0x02, 0x9B, 0x1A, 0xEB, 0x04, 0x0F, 0x58, 0xBF, 0x1C, 0x46, 0xD9, 0xE6, 0x07, 0xAA, +0x06, 0xA9, 0x0A, 0xFB, 0x00, 0x80, 0x03, 0xF0, 0xD3, 0xFA, 0x06, 0x9C, 0xE4, 0xF7, 0xAC, 0xFA, 0x01, 0x9B, 0x1B, 0x1B, +0xC3, 0x42, 0x3F, 0xF5, 0xD6, 0xAE, 0x06, 0x9C, 0x08, 0x4E, 0xDF, 0xF8, 0x28, 0xA0, 0xE4, 0xF7, 0xA1, 0xFA, 0x07, 0x9B, +0xA4, 0xF5, 0x7A, 0x64, 0xFA, 0x1A, 0x24, 0x1A, 0x17, 0xEA, 0x22, 0x07, 0x38, 0xBF, 0x1F, 0x46, 0x9C, 0xE7, 0x00, 0xBF, +0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0xDD, 0xE9, 0x06, 0x64, +0xE4, 0xF7, 0x8A, 0xFA, 0x02, 0x9B, 0x04, 0x9A, 0xF6, 0x1A, 0x32, 0x44, 0x13, 0x1A, 0x00, 0x2B, 0x5B, 0xDB, 0xE4, 0xF7, +0x81, 0xFA, 0x3B, 0x1B, 0xA3, 0xF5, 0x0C, 0x53, 0x28, 0x3B, 0x18, 0x1A, 0x00, 0x28, 0xBF, 0xF6, 0x1B, 0xAF, 0xA6, 0xE6, +0x37, 0x4E, 0x67, 0xE7, 0x9A, 0xF8, 0x18, 0x30, 0xFF, 0x2B, 0x5F, 0xD1, 0x01, 0x23, 0x89, 0xE7, 0x02, 0x9C, 0x37, 0xE7, +0xE4, 0xF7, 0x6C, 0xFA, 0x02, 0x9B, 0xF6, 0x1A, 0x04, 0x9B, 0x33, 0x44, 0x1B, 0x1A, 0x00, 0x2B, 0x4A, 0xDB, 0x01, 0x97, +0xE4, 0xF7, 0x62, 0xFA, 0x07, 0x9B, 0x03, 0xF5, 0x0C, 0x53, 0x28, 0x33, 0xDB, 0x1B, 0xC3, 0x42, 0x4A, 0xD5, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x0B, 0x83, 0x27, 0x4E, 0x1A, 0x6C, 0xDF, 0xF8, 0x9C, 0xA0, 0x11, 0x7E, 0xD6, 0xF8, 0x88, 0x30, +0x02, 0x29, 0x01, 0xF1, 0x01, 0x02, 0x2B, 0xD0, 0xC2, 0xEB, 0xC2, 0x00, 0x0A, 0xEB, 0x80, 0x00, 0x00, 0x7E, 0xFF, 0x28, +0x37, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x02, 0x08, 0xBF, 0x00, 0x22, 0xC2, 0xEB, 0xC2, 0x01, 0x0A, 0xEB, 0x81, 0x01, +0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x21, 0x29, 0xD1, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x0B, 0x88, 0x01, 0x98, 0xD8, 0xF8, 0x40, 0x10, 0xD6, 0xF8, 0x88, 0x30, 0x00, 0x22, 0x98, 0x47, 0x07, 0x9C, +0x2C, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x24, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x37, 0x1A, 0x9C, 0xE7, 0x9A, 0xF8, 0x18, 0x20, +0xFF, 0x2A, 0x0D, 0xD1, 0x01, 0x22, 0xD9, 0xE7, 0x06, 0x9E, 0xE4, 0xF7, 0x17, 0xFA, 0xA6, 0xF5, 0x7A, 0x66, 0x33, 0x1A, +0x01, 0x93, 0xAD, 0xE7, 0x05, 0x49, 0x33, 0xE7, 0x01, 0x9F, 0xAF, 0xE6, 0x00, 0x22, 0x1C, 0x21, 0x01, 0xFB, 0x02, 0xA1, +0xD1, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x30, 0xB5, 0x0E, 0x48, 0x83, 0xB0, 0x06, 0xF0, +0x59, 0xFA, 0x01, 0x90, 0xA0, 0xB1, 0x0C, 0x4B, 0x0C, 0x4C, 0xD3, 0xF8, 0xD8, 0x31, 0x0C, 0x48, 0x98, 0x47, 0x00, 0x23, +0x01, 0x99, 0xA3, 0x64, 0x04, 0xF1, 0x18, 0x05, 0x20, 0x34, 0x28, 0x46, 0x06, 0xF0, 0x04, 0xFA, 0x20, 0x46, 0x06, 0xF0, +0x45, 0xFA, 0x01, 0x46, 0x00, 0x28, 0xF6, 0xD1, 0x03, 0xB0, 0x30, 0xBD, 0x50, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x4C, 0x4B, 0x42, 0x69, 0x1F, 0x69, 0x4C, 0x4B, +0x4C, 0x4C, 0x98, 0x42, 0x83, 0xB0, 0x05, 0x46, 0x17, 0x44, 0x6F, 0xD0, 0xA3, 0x6A, 0xAB, 0x42, 0x04, 0xD0, 0xE4, 0xF7, +0xCD, 0xF9, 0x07, 0xF5, 0x7A, 0x67, 0x07, 0x44, 0x94, 0xF8, 0x5B, 0x80, 0x94, 0xF8, 0x58, 0x30, 0xC4, 0xE9, 0x14, 0x57, +0xB8, 0xF1, 0x00, 0x0F, 0x57, 0xD1, 0x42, 0x4E, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x73, 0x6B, 0x98, 0x47, +0xD6, 0xF8, 0x88, 0x30, 0x42, 0x46, 0x41, 0x46, 0x38, 0x46, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, +0x3A, 0xD0, 0x3A, 0x4B, 0xDF, 0xF8, 0xF8, 0x90, 0xDB, 0x1B, 0x01, 0x93, 0x4F, 0xF4, 0xA4, 0x68, 0x0C, 0xE0, 0x02, 0x2A, +0x04, 0xBF, 0xB0, 0xF8, 0xD2, 0x20, 0x91, 0x02, 0x61, 0x44, 0x00, 0x22, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, +0x00, 0x0F, 0x25, 0xD0, 0xDB, 0xF8, 0x04, 0xA0, 0xE4, 0xF7, 0x96, 0xF9, 0x01, 0x9B, 0xAA, 0xEB, 0x00, 0x00, 0xD8, 0x42, +0x1C, 0xD5, 0x9B, 0xF8, 0x08, 0x00, 0xDB, 0xF8, 0x04, 0xC0, 0xF3, 0x6A, 0x08, 0xFB, 0x00, 0x90, 0x4F, 0xF4, 0xC8, 0x31, +0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xDC, 0xD1, 0x90, 0xF8, 0x6C, 0x20, 0x24, 0x4F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, +0x02, 0x72, 0x91, 0x68, 0x00, 0x22, 0x61, 0x44, 0x98, 0x47, 0xD4, 0xF8, 0x10, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0xD9, 0xD1, +0xE3, 0x6A, 0xD3, 0xB1, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1B, 0xDB, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0xF8, 0x58, 0x30, +0x5A, 0x07, 0x8B, 0xD4, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD6, 0xF8, +0x9C, 0x30, 0x28, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, 0x58, 0x30, 0x13, 0xF0, 0x0C, 0x0F, +0xDE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0x86, 0x62, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x07, 0xF0, 0xAC, 0xBD, +0x00, 0x10, 0x50, 0x40, 0x00, 0x9E, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x60, 0xF0, 0xFF, 0xFF, +0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x5C, 0xA1, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, +0x10, 0xB5, 0x22, 0x4C, 0x94, 0xF8, 0x58, 0x30, 0xD8, 0x07, 0x11, 0xD5, 0x20, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, +0x00, 0x2A, 0x22, 0xDB, 0x23, 0xF0, 0x01, 0x03, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x1B, 0x4B, 0x1C, 0x48, +0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x03, 0xF0, 0x06, 0x02, 0x02, 0x2A, 0x11, 0xD1, 0x15, 0x4A, 0x12, 0x68, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x17, 0xDB, 0x23, 0xF0, 0x02, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, +0x10, 0x4B, 0x12, 0x48, 0xDB, 0x6D, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x59, 0x07, 0xDA, 0xD5, 0x0F, 0x49, +0x0F, 0x48, 0x40, 0xF2, 0x9B, 0x62, 0x07, 0xF0, 0x61, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xD1, 0xE7, 0x1A, 0x07, 0xE5, 0xD5, +0x09, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xA6, 0x62, 0x07, 0xF0, 0x56, 0xFD, 0x94, 0xF8, 0x58, 0x30, 0xDC, 0xE7, 0x00, 0xBF, +0x30, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x8C, 0xA1, 0x15, 0x00, 0xC0, 0xA1, 0x15, 0x00, 0x0D, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0xD9, 0x06, +0x14, 0xD4, 0x92, 0xF8, 0x5A, 0x00, 0x43, 0xF0, 0x10, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x50, 0xB1, 0x08, 0x49, 0x09, 0x4B, +0x09, 0x69, 0xD3, 0xF8, 0xE0, 0x31, 0x01, 0xF5, 0xEA, 0x41, 0x02, 0xF1, 0x30, 0x00, 0x30, 0x31, 0x18, 0x47, 0x04, 0x4B, +0xDB, 0x6B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x70, 0xB5, 0x32, 0x4C, 0x00, 0x23, 0x05, 0x46, 0xA3, 0x62, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x4A, 0x2E, 0x4E, 0x11, 0x68, 0x73, 0x68, 0x48, 0x1C, 0x23, 0xF0, 0x02, 0x03, +0x10, 0x60, 0x73, 0x60, 0x18, 0xB1, 0x28, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0xF9, 0xB1, 0x29, 0x49, 0x94, 0xF8, 0x5C, 0x30, +0x0A, 0x68, 0x9B, 0x00, 0x22, 0xF0, 0x04, 0x02, 0x03, 0xF0, 0x04, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x2B, 0x7E, 0x03, 0x2B, +0x26, 0xD0, 0x04, 0x2B, 0x94, 0xF8, 0x58, 0x30, 0x19, 0xD0, 0x23, 0xF0, 0x10, 0x02, 0xFF, 0x21, 0x9B, 0x07, 0x29, 0x76, +0x84, 0xF8, 0x58, 0x20, 0x02, 0xD0, 0x1D, 0x4B, 0x1B, 0x6C, 0x98, 0x47, 0xE3, 0x6A, 0x23, 0xB1, 0x70, 0xBD, 0x00, 0x2B, +0xDD, 0xD0, 0x62, 0xB6, 0xDB, 0xE7, 0x18, 0x4B, 0xD3, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xBD, 0xE8, 0x70, 0x40, 0xFB, 0xF7, +0x93, 0xBA, 0x23, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x58, 0x20, 0xEA, 0x89, 0x92, 0xB9, 0x03, 0xF0, 0xDB, 0x03, 0xDC, 0xE7, +0x94, 0xF8, 0x58, 0x30, 0x23, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0x84, 0xFE, 0xFF, 0x22, 0x02, 0x21, +0x86, 0x20, 0x05, 0xF0, 0x49, 0xFC, 0x94, 0xF8, 0x58, 0x30, 0xCC, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xB1, 0xFE, 0x94, 0xF8, +0x58, 0x30, 0xC6, 0xE7, 0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x6B, 0x4F, 0x6C, 0x4E, 0x04, 0x46, 0x6C, 0x48, +0x06, 0xF0, 0x96, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0xC0, 0xF2, 0x85, 0x80, 0x33, 0x78, +0x00, 0x2B, 0x44, 0xD0, 0x66, 0x4C, 0x01, 0x2B, 0x42, 0xD1, 0x94, 0xF8, 0x58, 0x30, 0x19, 0x07, 0x00, 0xF1, 0x9D, 0x80, +0x5A, 0x07, 0x40, 0xF1, 0xB0, 0x80, 0x62, 0x4F, 0xE3, 0x6A, 0xBB, 0x42, 0x02, 0xD0, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, +0xA3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, 0x00, 0x23, 0xC4, 0xE9, 0x0A, 0x73, 0x39, 0x7E, 0x04, 0x23, 0x03, 0x29, +0x3B, 0x74, 0x00, 0xF0, 0xA0, 0x80, 0x02, 0x29, 0x24, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x55, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x55, 0x4A, 0x55, 0x48, 0x17, 0x68, 0x43, 0x68, 0x79, 0x1C, 0x43, 0xF0, 0x02, 0x03, +0x11, 0x60, 0x43, 0x60, 0x29, 0xB1, 0x4F, 0x4B, 0x17, 0x60, 0x1B, 0x68, 0x0F, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x4F, 0x4A, +0xA3, 0x6A, 0x11, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x84, 0xF8, 0x5C, 0x10, 0x11, 0x68, 0x21, 0xF0, 0x04, 0x01, 0x11, 0x60, +0x01, 0xE0, 0x44, 0x4C, 0xA3, 0x6A, 0x01, 0x22, 0x1A, 0x74, 0x22, 0x6D, 0x00, 0x23, 0x33, 0x70, 0x00, 0x2A, 0x31, 0xD0, +0x94, 0xF8, 0x5A, 0x20, 0x23, 0x65, 0x00, 0x2A, 0x53, 0xD0, 0x01, 0x2A, 0x53, 0xD0, 0x23, 0x69, 0x00, 0x2B, 0x50, 0xD0, +0x1B, 0x7A, 0x40, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x18, 0x6C, 0xA8, 0x60, 0x18, 0xB1, 0x3D, 0x4B, +0xD3, 0xF8, 0x9C, 0x30, 0x98, 0x47, 0x3C, 0x48, 0x29, 0x46, 0x05, 0xF0, 0xDF, 0xFF, 0xA0, 0x6A, 0x03, 0x7E, 0x02, 0x2B, +0x02, 0xD9, 0x37, 0x4B, 0x9B, 0x6B, 0x98, 0x47, 0x20, 0x6A, 0xA0, 0x64, 0x58, 0xB3, 0x36, 0x4B, 0x41, 0x68, 0x1B, 0x69, +0xCB, 0x1A, 0x14, 0x2B, 0x27, 0xD4, 0x31, 0x4B, 0x33, 0x48, 0xD3, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, +0xA8, 0x68, 0xDD, 0xE7, 0x84, 0x42, 0x32, 0xD0, 0x2F, 0x49, 0x30, 0x48, 0x40, 0xF2, 0x4F, 0x72, 0x07, 0xF0, 0x12, 0xFC, +0x33, 0x78, 0x00, 0x2B, 0x7F, 0xF4, 0x72, 0xAF, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x1D, 0x4C, +0xA3, 0x6A, 0x00, 0x2B, 0xAF, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x51, 0x72, 0x07, 0xF0, 0xFF, 0xFB, 0x33, 0x78, +0x61, 0xE7, 0xBD, 0xE8, 0xF0, 0x81, 0x63, 0x6C, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x22, 0x4F, 0x64, 0xE7, 0xAA, 0x60, +0xBB, 0xE7, 0x21, 0x48, 0x02, 0x7E, 0xFF, 0x2A, 0xB1, 0xD1, 0x90, 0xF8, 0x34, 0x20, 0xFF, 0x2A, 0x12, 0xD1, 0x90, 0xF8, +0x50, 0x20, 0xFF, 0x2A, 0x10, 0xD1, 0xAB, 0x60, 0xAD, 0xE7, 0x33, 0x78, 0x00, 0x2B, 0xD8, 0xD0, 0x44, 0xE7, 0xE7, 0x6A, +0x00, 0x2F, 0x87, 0xD0, 0x52, 0xE7, 0x02, 0x20, 0x05, 0xF0, 0xF2, 0xFC, 0x39, 0x7E, 0x5A, 0xE7, 0x1C, 0x30, 0x98, 0xE7, +0x38, 0x30, 0x96, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, +0x00, 0x9E, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, +0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x9D, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xF4, 0xA1, 0x15, 0x00, 0x10, 0xA2, 0x15, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, +0x0D, 0x4B, 0x93, 0xF8, 0x58, 0x20, 0x11, 0x07, 0x03, 0xD4, 0x52, 0x07, 0x0D, 0xD5, 0x0B, 0x49, 0x00, 0xE0, 0x0B, 0x49, +0xDA, 0x6A, 0x8A, 0x42, 0x03, 0xD0, 0x0A, 0xB1, 0x01, 0x20, 0x10, 0x74, 0xD9, 0x62, 0x08, 0x4B, 0xD3, 0xF8, 0x98, 0x30, +0x18, 0x47, 0xDB, 0x6A, 0x00, 0x2B, 0xF8, 0xD1, 0x05, 0x49, 0x08, 0x20, 0x07, 0xF0, 0x68, 0xB9, 0x30, 0x9D, 0x17, 0x00, +0x00, 0x9E, 0x17, 0x00, 0xE4, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x28, 0xA2, 0x15, 0x00, 0x0B, 0x4A, 0x92, 0xF8, +0x59, 0x30, 0x43, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x82, 0xF8, 0x59, 0x30, 0x1B, 0xB9, 0x08, 0x4A, 0x11, 0x78, 0x01, 0x29, +0x00, 0xD0, 0x70, 0x47, 0x10, 0xB5, 0x06, 0x4C, 0x13, 0x70, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xE3, 0x6F, 0xBD, 0xE8, +0x10, 0x40, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x17, 0x2C, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x1D, 0x4B, +0x1D, 0x49, 0x1E, 0x4A, 0xD3, 0xF8, 0xE0, 0x33, 0x8C, 0x68, 0x95, 0x6A, 0x98, 0x47, 0x1C, 0x4B, 0x5B, 0x78, 0x23, 0xB1, +0x1B, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x1A, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x13, 0x60, +0x1C, 0xB3, 0x18, 0x4F, 0x8C, 0x26, 0x01, 0xE0, 0x24, 0x68, 0xF4, 0xB1, 0x23, 0x6C, 0xAB, 0x42, 0xFA, 0xD1, 0x94, 0xF8, +0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x22, +0x11, 0x46, 0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x06, 0xFB, 0x03, 0x73, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xE5, 0xD0, +0x94, 0xF8, 0x6C, 0x00, 0xF2, 0xF7, 0xD6, 0xFD, 0x24, 0x68, 0x00, 0x2C, 0xE0, 0xD1, 0xF8, 0xBD, 0x88, 0x1A, 0x17, 0x00, +0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, +0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x08, 0x81, 0x3D, 0x4A, 0x3E, 0x4E, 0xD8, 0xF8, 0xDC, 0x33, +0x94, 0x68, 0x96, 0xF8, 0x59, 0x90, 0x83, 0xB0, 0x98, 0x47, 0xB5, 0x6A, 0x00, 0x2D, 0x5E, 0xD0, 0x39, 0x4A, 0x3A, 0x49, +0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x4B, 0x78, 0x4F, 0x46, 0x00, 0x2B, 0x4D, 0xD1, 0x00, 0x2C, 0x3A, 0xD0, +0xDF, 0xF8, 0xD8, 0xB0, 0xDF, 0xF8, 0xD8, 0xA0, 0x4F, 0xF0, 0x06, 0x09, 0x01, 0xE0, 0x24, 0x68, 0x7C, 0xB3, 0x23, 0x6C, +0x9D, 0x42, 0xFA, 0xD1, 0x94, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xF6, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, +0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x4F, 0xF0, 0x8C, 0x01, 0x4F, 0xF0, 0x00, 0x02, 0xEA, 0xD0, 0x94, 0xF8, 0xC0, 0x34, +0x3B, 0xB1, 0x94, 0xF8, 0xC1, 0x34, 0x01, 0xFB, 0x03, 0xA3, 0x93, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0xDF, 0xD0, 0x2B, 0x7C, +0x85, 0xF8, 0x10, 0x90, 0xD8, 0xF8, 0xB0, 0x10, 0x01, 0x93, 0xF2, 0xF7, 0x79, 0xFD, 0x01, 0x9B, 0x00, 0xB9, 0x01, 0x37, +0x01, 0x22, 0x2B, 0x74, 0x8B, 0xF8, 0x00, 0x20, 0x24, 0x68, 0x00, 0x2C, 0xCF, 0xD1, 0x5F, 0xFA, 0x87, 0xF9, 0x96, 0xF8, +0x59, 0x40, 0xF5, 0x6A, 0x86, 0xF8, 0x59, 0x90, 0x3C, 0x1B, 0xAD, 0xB1, 0x27, 0xB1, 0x03, 0x23, 0x2B, 0x74, 0xD8, 0xF8, +0x60, 0x31, 0x98, 0x47, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD2, 0xF8, 0xE8, 0x33, 0x43, 0xF0, 0x00, 0x43, +0xC2, 0xF8, 0xE8, 0x33, 0xAA, 0xE7, 0x00, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xD8, 0xF8, 0x60, 0x31, +0x98, 0x47, 0x00, 0x2F, 0xF5, 0xD0, 0x96, 0xF8, 0x59, 0x30, 0x01, 0x3B, 0x2C, 0x46, 0x86, 0xF8, 0x59, 0x30, 0xE3, 0xE7, +0x00, 0x88, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x17, 0x2C, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0xD4, 0xF8, 0xA4, 0x31, 0x98, 0x47, 0xA3, 0x6E, +0x98, 0x47, 0x18, 0xB9, 0xE3, 0x6F, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x10, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x43, 0x4D, 0x4E, 0x4E, 0x4F, 0xF4, 0x6A, 0x85, 0xB0, 0x00, 0x25, 0xE2, 0x88, 0x61, 0x79, 0x23, 0x89, +0x20, 0x79, 0x02, 0x95, 0x65, 0x7B, 0x01, 0x95, 0x65, 0x89, 0x00, 0x95, 0xE3, 0xF7, 0x72, 0xFD, 0xD7, 0xF8, 0x3C, 0x33, +0x94, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x21, 0x79, 0x44, 0x4B, 0x45, 0x4A, 0x03, 0xEB, 0x81, 0x03, 0x5B, 0x69, 0x13, 0x60, +0x23, 0x7E, 0x03, 0x2B, 0x02, 0xD0, 0x20, 0x46, 0xFE, 0xF7, 0xFE, 0xFB, 0xB3, 0x6A, 0x0B, 0xB1, 0x01, 0x22, 0x1A, 0x74, +0x00, 0x23, 0xC6, 0xE9, 0x0A, 0x43, 0x23, 0x7E, 0x04, 0x22, 0x02, 0x2B, 0x22, 0x74, 0x4E, 0xD9, 0x96, 0xF8, 0x5A, 0x20, +0x00, 0x2A, 0x4A, 0xD0, 0x03, 0x2B, 0x52, 0xD0, 0x04, 0x2B, 0x24, 0xD0, 0xFB, 0x6E, 0x98, 0x47, 0x23, 0x7E, 0x02, 0x2B, +0x1F, 0xD8, 0x34, 0x4B, 0x9D, 0x68, 0x00, 0x2D, 0x37, 0xD0, 0xDF, 0xF8, 0xE4, 0x90, 0x4F, 0xF0, 0x01, 0x08, 0x01, 0xE0, +0x2D, 0x68, 0x8D, 0xB1, 0x2B, 0x6C, 0xA3, 0x42, 0xFA, 0xD1, 0x95, 0xF8, 0x63, 0x30, 0xD7, 0xF8, 0x5C, 0x24, 0xC3, 0xEB, +0xC3, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x28, 0x46, 0x83, 0xF8, 0x1B, 0x80, 0x90, 0x47, 0x2D, 0x68, 0x00, 0x2D, 0xED, 0xD1, +0x23, 0x7E, 0x02, 0x2B, 0x1B, 0xD9, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x22, 0x4A, 0x22, 0x4C, 0x11, 0x68, 0x63, 0x68, 0x48, 0x1C, 0x43, 0xF0, 0x02, 0x03, 0x10, 0x60, 0x63, 0x60, +0x28, 0xBB, 0x1F, 0x4B, 0x19, 0x68, 0x1A, 0x68, 0xC1, 0xF3, 0x80, 0x01, 0x22, 0xF0, 0x04, 0x02, 0x86, 0xF8, 0x5C, 0x10, +0x1A, 0x60, 0xD7, 0xF8, 0x60, 0x31, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x18, 0x4A, 0x92, 0xF8, 0xFF, 0x21, +0x00, 0x2A, 0xAF, 0xD0, 0xF1, 0xF7, 0xA2, 0xFB, 0x23, 0x7E, 0x03, 0x2B, 0xAC, 0xD1, 0x14, 0x4B, 0x00, 0x22, 0x1A, 0x60, +0x02, 0x21, 0xFF, 0x22, 0x85, 0x20, 0x05, 0xF0, 0x77, 0xF9, 0x23, 0x7E, 0x02, 0x2B, 0xE4, 0xD9, 0xC7, 0xE7, 0x09, 0x4B, +0x11, 0x60, 0x1B, 0x68, 0x00, 0x29, 0xD4, 0xD1, 0x00, 0x2B, 0xD2, 0xD0, 0x62, 0xB6, 0xD0, 0xE7, 0x30, 0x9D, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0xDC, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x20, 0x62, 0x17, 0x00, 0x20, 0x02, 0x32, 0x40, +0x80, 0x9F, 0x17, 0x00, 0x70, 0xB5, 0x25, 0x4D, 0xEA, 0x6A, 0x04, 0x46, 0x0A, 0xB1, 0xE8, 0x62, 0x70, 0xBD, 0xAE, 0x6A, +0x86, 0x42, 0x3D, 0xD0, 0x5E, 0xB1, 0x33, 0x7E, 0x03, 0x2B, 0x08, 0xD0, 0x01, 0x23, 0x0C, 0x21, 0x45, 0x20, 0x05, 0xF0, +0xD7, 0xF8, 0x33, 0x7E, 0x03, 0x70, 0x05, 0xF0, 0x03, 0xF9, 0x1B, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0x1C, 0xDD, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x17, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x17, 0x4E, 0x33, 0x68, 0x04, 0x20, +0x01, 0x33, 0x33, 0x60, 0xF1, 0xF7, 0x42, 0xF8, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xF1, 0xF7, 0xDD, 0xF8, 0x33, 0x68, +0x33, 0xB1, 0x0F, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x33, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x02, 0x22, 0xEC, 0x62, +0x04, 0x23, 0x22, 0x74, 0x00, 0x21, 0xFF, 0x22, 0x84, 0x20, 0x05, 0xF0, 0xA9, 0xF8, 0x09, 0x4B, 0x1B, 0x6E, 0x03, 0x60, +0xBD, 0xE8, 0x70, 0x40, 0x05, 0xF0, 0xD2, 0xB8, 0x04, 0x23, 0x33, 0x74, 0x70, 0xBD, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, +0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x0A, 0x4D, +0x04, 0x46, 0xD5, 0xF8, 0x6C, 0x31, 0x00, 0x6D, 0x98, 0x47, 0xD5, 0xF8, 0x00, 0x32, 0x20, 0x65, 0x01, 0x46, 0x20, 0x46, +0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x38, 0xBD, +0x88, 0x1A, 0x17, 0x00, 0x02, 0x6D, 0x41, 0x6A, 0x70, 0xB5, 0x17, 0x4D, 0x04, 0x46, 0xD5, 0xF8, 0xE0, 0x31, 0x11, 0x44, +0x18, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x20, 0x02, 0xDB, 0x07, 0x84, 0xF8, 0x4D, 0x20, 0x0E, 0xD5, +0x10, 0x4B, 0x5B, 0x6A, 0x23, 0xB1, 0xDA, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, 0x07, 0xD0, 0xEB, 0x6A, 0x61, 0x6A, +0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x70, 0xBD, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, +0x20, 0x46, 0x00, 0x22, 0x98, 0x47, 0x06, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, +0x70, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x2D, 0xE9, 0xF8, 0x43, +0xDF, 0xF8, 0xB8, 0x80, 0x90, 0xF8, 0x4E, 0x70, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x07, 0x85, 0x95, 0xF8, 0x4D, 0x60, +0x16, 0xF0, 0x60, 0x06, 0x1F, 0xD1, 0x26, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xFC, 0x31, 0x89, 0x46, 0x90, 0xF8, 0x4F, 0x10, +0x28, 0x46, 0x98, 0x47, 0x63, 0x6D, 0xA0, 0xEB, 0x09, 0x01, 0x58, 0x1A, 0x00, 0xB2, 0x80, 0xEA, 0xE0, 0x73, 0xA3, 0xEB, +0xE0, 0x73, 0x9B, 0xB2, 0xB3, 0xF5, 0xFA, 0x6F, 0xA4, 0xF8, 0x58, 0x00, 0x09, 0xD9, 0x95, 0xF8, 0x4D, 0x30, 0x23, 0xF0, +0x40, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF8, 0x83, 0xC8, 0x2B, 0xFB, 0xD9, 0x15, 0x4B, +0x9B, 0x68, 0x9B, 0xB1, 0x95, 0xF8, 0x63, 0x10, 0x30, 0x46, 0x93, 0xF8, 0x4E, 0x20, 0x8A, 0x42, 0x07, 0xD1, 0xB3, 0xF9, +0x58, 0x20, 0x90, 0x42, 0xA8, 0xBF, 0x10, 0x46, 0x96, 0x42, 0xB8, 0xBF, 0x16, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF0, 0xD1, +0x60, 0xB9, 0x73, 0x10, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x87, 0x97, 0xF8, 0x4D, 0x20, 0x3B, 0x65, 0x42, 0xF0, +0x40, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xD8, 0xE7, 0x00, 0x2E, 0xD6, 0xD1, 0x00, 0xEB, 0xD0, 0x73, 0x5B, 0x10, 0xED, 0xE7, +0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x23, 0x48, 0x2D, 0xE9, 0xF0, 0x41, 0x60, 0x22, +0x00, 0x21, 0x22, 0x4F, 0x06, 0x46, 0xE2, 0xF7, 0xD3, 0xFB, 0x00, 0x25, 0x3C, 0x46, 0xA8, 0x46, 0x00, 0x21, 0x1C, 0x22, +0x20, 0x46, 0xE2, 0xF7, 0xCB, 0xFB, 0xFF, 0x23, 0x02, 0x2D, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0x21, 0x46, 0x30, 0x46, +0x04, 0xD8, 0x05, 0xF0, 0x55, 0xFC, 0x01, 0x35, 0x1C, 0x34, 0xED, 0xE7, 0x03, 0x2D, 0x22, 0xD0, 0x04, 0x2D, 0xF8, 0xD1, +0x14, 0x48, 0x05, 0xF0, 0x47, 0xFC, 0x14, 0x48, 0x05, 0xF0, 0x44, 0xFC, 0x13, 0x49, 0x11, 0x48, 0x05, 0xF0, 0x44, 0xFC, +0x12, 0x49, 0x0F, 0x48, 0x05, 0xF0, 0x40, 0xFC, 0x11, 0x49, 0x0D, 0x48, 0x05, 0xF0, 0x3C, 0xFC, 0x10, 0x49, 0x0B, 0x48, +0x05, 0xF0, 0x38, 0xFC, 0x0F, 0x4A, 0x07, 0x4B, 0xD2, 0xF8, 0xAC, 0x10, 0xD0, 0x6B, 0x58, 0x63, 0x00, 0x22, 0xC3, 0xE9, +0x11, 0x12, 0xBD, 0xE8, 0xF0, 0x81, 0xA7, 0xF8, 0x5E, 0x80, 0x87, 0xF8, 0x59, 0x80, 0xD2, 0xE7, 0x30, 0x9D, 0x17, 0x00, +0x90, 0x9D, 0x17, 0x00, 0x48, 0x9D, 0x17, 0x00, 0x50, 0x9D, 0x17, 0x00, 0xF0, 0x9C, 0x17, 0x00, 0x00, 0x9D, 0x17, 0x00, +0x10, 0x9D, 0x17, 0x00, 0x20, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x21, 0x4C, 0x24, 0x68, +0xB4, 0xF9, 0x00, 0x40, 0x83, 0xB0, 0x00, 0x2C, 0x9D, 0xF8, 0x28, 0x90, 0x9D, 0xF8, 0x2C, 0x80, 0x1D, 0x4C, 0x07, 0x46, +0x0D, 0x46, 0x16, 0x46, 0x27, 0xDB, 0x1C, 0x49, 0x84, 0xF8, 0x58, 0x70, 0x91, 0xF8, 0x58, 0x20, 0xA4, 0xF8, 0x5C, 0x50, +0xA4, 0xF8, 0x5A, 0x50, 0x42, 0xF0, 0x02, 0x07, 0x84, 0xF8, 0x60, 0x60, 0xFF, 0x25, 0x03, 0x26, 0x01, 0x20, 0xA3, 0x66, +0xD3, 0x06, 0x84, 0xF8, 0x61, 0x90, 0x84, 0xF8, 0x6E, 0x80, 0x81, 0xF8, 0x58, 0x70, 0x84, 0xF8, 0x6C, 0x60, 0xA4, 0xF8, +0x62, 0x50, 0x84, 0xF8, 0x64, 0x00, 0x05, 0xD4, 0x0D, 0x4B, 0x1B, 0x6C, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x94, 0xF8, 0x6C, 0x20, 0xFF, 0x2A, 0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x01, 0x93, +0x40, 0xF6, 0x8C, 0x22, 0x07, 0xF0, 0x26, 0xF8, 0x01, 0x9B, 0xCA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, +0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x48, 0xA2, 0x15, 0x00, 0xF0, 0xB5, 0x65, 0x4F, +0x04, 0x46, 0x83, 0xB0, 0x97, 0xF8, 0x80, 0x00, 0xE3, 0x68, 0x22, 0x78, 0x00, 0x90, 0x0E, 0x46, 0x08, 0x20, 0x61, 0x49, +0x06, 0xF0, 0xE0, 0xFD, 0x25, 0x78, 0x25, 0xB3, 0x01, 0x2D, 0x2F, 0xD1, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x1A, 0xD0, +0x97, 0xF8, 0x80, 0x30, 0x03, 0x2B, 0x2B, 0xD8, 0x01, 0x2B, 0x5A, 0x4C, 0x44, 0xD8, 0x09, 0xD1, 0x94, 0xF8, 0x58, 0x30, +0x07, 0xF1, 0x70, 0x00, 0x23, 0xF0, 0x05, 0x03, 0x84, 0xF8, 0x58, 0x30, 0xFE, 0xF7, 0xE4, 0xF9, 0x94, 0xF8, 0x58, 0x30, +0x03, 0xF0, 0x12, 0x02, 0xFF, 0x21, 0x10, 0x2A, 0x87, 0xF8, 0x88, 0x10, 0x24, 0xD0, 0x00, 0x25, 0x28, 0x46, 0x03, 0xB0, +0xF0, 0xBD, 0x97, 0xF8, 0x88, 0x30, 0xFF, 0x2B, 0x3A, 0xD0, 0x4B, 0x4A, 0x92, 0xF8, 0x58, 0x30, 0x99, 0x06, 0x03, 0xD5, +0x23, 0xF0, 0x20, 0x03, 0x82, 0xF8, 0x58, 0x30, 0x01, 0x25, 0x28, 0x46, 0x03, 0xB0, 0xF0, 0xBD, 0x04, 0x2B, 0x17, 0xD1, +0x44, 0x48, 0x45, 0x4D, 0xA0, 0xF1, 0x40, 0x04, 0xD5, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x22, 0xD5, 0xF8, 0xAC, 0x30, +0x20, 0x6A, 0xA2, 0x64, 0x98, 0x47, 0xD1, 0xE7, 0x3E, 0x4A, 0x3F, 0x48, 0xD2, 0xF8, 0xD8, 0x21, 0x23, 0xF0, 0x10, 0x03, +0x84, 0xF8, 0x58, 0x30, 0x90, 0x47, 0xD0, 0xE7, 0x37, 0x4C, 0xC5, 0xE7, 0x94, 0xF8, 0x58, 0x30, 0xE2, 0x6A, 0x23, 0xF0, +0x04, 0x03, 0x84, 0xF8, 0x58, 0x30, 0x2A, 0xB1, 0x07, 0xF1, 0x70, 0x03, 0x9A, 0x42, 0x50, 0xD0, 0x00, 0x23, 0xE3, 0x62, +0x33, 0x48, 0xFE, 0xF7, 0x99, 0xF9, 0xB3, 0xE7, 0x97, 0xF8, 0x80, 0x30, 0x04, 0x2B, 0xC0, 0xD0, 0x04, 0x20, 0x05, 0xF0, +0x5D, 0xF9, 0x01, 0x28, 0xBB, 0xD0, 0x04, 0x23, 0x87, 0xF8, 0x88, 0x30, 0xA3, 0x78, 0x87, 0xF8, 0x74, 0x30, 0xE3, 0x78, +0x87, 0xF8, 0x75, 0x30, 0xA3, 0x88, 0xE2, 0x88, 0xA7, 0xF8, 0x76, 0x30, 0x01, 0x21, 0x23, 0x89, 0x87, 0xF8, 0x80, 0x10, +0xA7, 0xF8, 0x78, 0x20, 0xE2, 0x68, 0xA7, 0xF8, 0x7A, 0x30, 0x4F, 0xF4, 0x7A, 0x73, 0x03, 0xFB, 0x02, 0xF3, 0x23, 0x2A, +0x84, 0xBF, 0xA3, 0xF5, 0x08, 0x43, 0xB8, 0x3B, 0xA7, 0xF8, 0x7E, 0x60, 0xC7, 0xF8, 0x84, 0x30, 0x63, 0x78, 0x17, 0x4A, +0x87, 0xF8, 0x8A, 0x30, 0x23, 0x7C, 0x87, 0xF8, 0x7C, 0x30, 0x16, 0x49, 0x92, 0xF8, 0x58, 0x30, 0x66, 0xB9, 0x43, 0xF0, +0x04, 0x03, 0xC9, 0x6D, 0x14, 0x48, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0x13, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, +0x13, 0x60, 0x8A, 0xE7, 0x43, 0xF0, 0x01, 0x03, 0x09, 0x6C, 0x82, 0xF8, 0x58, 0x30, 0x88, 0x47, 0xF2, 0xE7, 0x23, 0x6D, +0x93, 0x42, 0xAB, 0xD1, 0x08, 0x4B, 0x04, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x00, 0x23, 0xA3, 0x64, +0xA2, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x68, 0xA2, 0x15, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x60, 0x9D, 0x17, 0x00, 0x00, 0x9E, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x2D, 0xE9, 0xF0, 0x41, +0x36, 0x4E, 0x84, 0xB0, 0x04, 0x46, 0x0F, 0x46, 0x33, 0x46, 0x00, 0x25, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0x1A, 0x79, +0x20, 0x78, 0x90, 0x42, 0x1B, 0xD0, 0x01, 0x35, 0x03, 0x2D, 0x03, 0xF1, 0x1C, 0x03, 0xF3, 0xD1, 0x2E, 0x48, 0x05, 0xF0, +0x15, 0xFB, 0x03, 0x46, 0x70, 0xB3, 0x2D, 0x4A, 0x86, 0x1B, 0xB6, 0x10, 0x02, 0xFB, 0x06, 0xF6, 0xF6, 0xB2, 0x06, 0x76, +0x3E, 0x70, 0x20, 0x68, 0x61, 0x68, 0x04, 0x33, 0x03, 0xC3, 0x22, 0x89, 0x1A, 0x80, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, +0xF0, 0x81, 0xD9, 0x88, 0x62, 0x88, 0x8A, 0x42, 0xDF, 0xD1, 0x93, 0xF8, 0x05, 0xC0, 0x61, 0x78, 0x8C, 0x45, 0x08, 0xD0, +0x02, 0xD2, 0xBC, 0xF1, 0x03, 0x0F, 0x13, 0xD1, 0x8C, 0x45, 0xD4, 0xD9, 0x03, 0x29, 0xD2, 0xD0, 0x07, 0xE0, 0x19, 0x89, +0xA2, 0x88, 0x91, 0x42, 0xCD, 0xD1, 0x59, 0x89, 0xE2, 0x88, 0x91, 0x42, 0xC9, 0xD1, 0x3D, 0x70, 0x00, 0x20, 0xDF, 0xE7, +0x01, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xDF, 0xF8, 0x48, 0xE0, 0xB4, 0xF8, 0x04, 0x80, 0xB4, 0xF8, 0x06, 0xC0, +0xDE, 0xF8, 0x28, 0x30, 0xC5, 0xEB, 0xC5, 0x04, 0x06, 0xEB, 0x84, 0x04, 0xA3, 0x42, 0x61, 0x71, 0xA4, 0xF8, 0x08, 0x80, +0xA4, 0xF8, 0x0A, 0xC0, 0xE5, 0xD1, 0x9E, 0xF8, 0x5A, 0x40, 0x01, 0x2C, 0xE1, 0xD1, 0x1C, 0x24, 0x04, 0xFB, 0x05, 0x66, +0x00, 0x24, 0x76, 0x7B, 0xCD, 0xF8, 0x00, 0xC0, 0xCD, 0xE9, 0x01, 0x64, 0x43, 0x46, 0xE3, 0xF7, 0xCF, 0xF9, 0xD4, 0xE7, +0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0xB7, 0x6D, 0xDB, 0xB6, 0x2D, 0xE9, 0xF0, 0x41, 0xDF, 0xF8, 0x98, 0x80, +0x20, 0x4D, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0xC0, 0xEB, 0xC0, 0x06, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xEB, +0x86, 0x06, 0x12, 0xDB, 0xC7, 0x00, 0x1B, 0x48, 0x31, 0x46, 0x3C, 0x1B, 0x05, 0xF0, 0x5C, 0xFA, 0x05, 0xEB, 0x84, 0x04, +0x30, 0x46, 0x1C, 0x22, 0x00, 0x21, 0xE2, 0xF7, 0xC1, 0xF9, 0xFF, 0x23, 0xE3, 0x81, 0x23, 0x76, 0xE3, 0x76, 0xBD, 0xE8, +0xF0, 0x81, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, 0x83, 0x03, 0xC7, 0x00, 0x1B, 0x7E, 0xFF, 0x2B, 0x0C, 0xD0, 0x3B, 0x1B, +0x05, 0xEB, 0x83, 0x03, 0x5B, 0x7E, 0x00, 0x2B, 0xDF, 0xD0, 0x0C, 0x49, 0x0C, 0x48, 0x40, 0xF6, 0x5C, 0x32, 0x06, 0xF0, +0x8F, 0xFE, 0xD8, 0xE7, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x5A, 0x32, 0x06, 0xF0, 0x88, 0xFE, 0xD8, 0xF8, 0x00, 0x30, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE6, 0xDB, 0xCB, 0xE7, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x84, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0xDF, 0xF8, 0x4C, 0x82, 0xDF, 0xF8, 0x24, 0xA2, 0xD8, 0xF8, 0x00, 0x20, 0x84, 0x4F, 0xB2, 0xF9, 0x00, 0x30, 0xC1, 0xEB, +0xC1, 0x06, 0x00, 0x2B, 0x85, 0xB0, 0x0C, 0x46, 0x05, 0x46, 0x0A, 0xEB, 0x86, 0x06, 0x5F, 0xDB, 0x4F, 0xEA, 0xC4, 0x0B, +0xAB, 0xEB, 0x04, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x4F, 0xF4, 0xA4, 0x63, 0x4A, 0x7E, 0xDF, 0xF8, 0x1C, 0x92, 0x01, 0x32, +0x03, 0xFB, 0x05, 0x73, 0xD2, 0xB2, 0x00, 0x20, 0x01, 0x2A, 0x4A, 0x76, 0x1E, 0x64, 0x83, 0xF8, 0x4D, 0x00, 0x6B, 0xD0, +0xDF, 0xF8, 0x04, 0x82, 0x99, 0xF8, 0x5B, 0x10, 0x99, 0xF8, 0x5A, 0x30, 0x4F, 0xF4, 0x80, 0x70, 0xCD, 0xE9, 0x00, 0x31, +0x6F, 0x49, 0x23, 0x46, 0x06, 0xF0, 0x12, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xFF, 0x21, 0x93, 0xF8, +0xC0, 0x24, 0x83, 0xF8, 0x4E, 0x10, 0x4A, 0xB1, 0x69, 0x49, 0x93, 0xF8, 0xC1, 0x24, 0x8C, 0x20, 0x00, 0xFB, 0x02, 0x12, +0x92, 0xF8, 0x70, 0x20, 0x01, 0x2A, 0x20, 0xD0, 0x65, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, +0xDA, 0x7E, 0xFF, 0x2A, 0x40, 0xF0, 0xAA, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xD8, 0xF8, 0xB4, 0x30, 0x30, 0x46, +0x98, 0x47, 0x5E, 0x4B, 0x1B, 0x7C, 0xAB, 0x42, 0x08, 0xD0, 0xFF, 0x2B, 0x06, 0xD0, 0xD8, 0xF8, 0x50, 0x30, 0x20, 0x46, +0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x93, 0xF8, 0x4D, 0x20, 0x42, 0xF0, +0x10, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0xE4, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x73, 0x1B, 0x6C, 0x5B, 0xB1, +0x50, 0x49, 0x51, 0x48, 0x40, 0xF6, 0x6B, 0x32, 0x06, 0xF0, 0xF4, 0xFD, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x8D, 0xDA, 0xC4, 0xEB, 0xC4, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0xC4, 0x0B, 0x1B, 0x7E, 0xFF, 0x2B, +0x86, 0xD1, 0x46, 0x49, 0x47, 0x48, 0x40, 0xF6, 0x6C, 0x32, 0x06, 0xF0, 0xDF, 0xFD, 0x7F, 0xE7, 0x99, 0xF8, 0x5A, 0x00, +0x0A, 0x74, 0x42, 0x1C, 0xD8, 0xF8, 0x00, 0x30, 0xD2, 0xB2, 0x89, 0xF8, 0x5A, 0x20, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x28, 0xDB, 0x02, 0x2A, 0x3C, 0xD0, 0x3E, 0x48, 0x31, 0x46, 0x05, 0xF0, 0x77, 0xF9, 0x99, 0xF8, 0x58, 0x30, 0x13, 0xF0, +0x0C, 0x0F, 0x0F, 0xD0, 0xD8, 0xF8, 0x00, 0x20, 0xD9, 0xF8, 0x20, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x20, 0xDB, +0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0x9E, 0x60, 0x9A, 0xF8, 0x19, 0x20, 0x6B, 0xE7, 0xD9, 0xF8, 0x2C, 0x30, +0x8B, 0xB3, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xDF, 0xF8, 0xD0, 0x80, 0x9A, 0xF8, 0x19, 0x20, 0xC9, 0xF8, +0x2C, 0x60, 0x5F, 0xE7, 0x02, 0x2A, 0xD4, 0xD9, 0x40, 0xF6, 0x81, 0x32, 0x25, 0x49, 0x29, 0x48, 0x06, 0xF0, 0xA0, 0xFD, +0x99, 0xF8, 0x5A, 0x20, 0xCB, 0xE7, 0x00, 0x2B, 0xDC, 0xD1, 0x21, 0x49, 0x25, 0x48, 0x03, 0x93, 0x4F, 0xF4, 0x39, 0x62, +0x06, 0xF0, 0x94, 0xFD, 0x03, 0x9B, 0xD3, 0xE7, 0x22, 0x48, 0x05, 0xF0, 0x37, 0xF9, 0x16, 0x4B, 0x03, 0xF5, 0xA4, 0x51, +0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, 0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, +0xB1, 0xE7, 0xDF, 0xF8, 0x74, 0x80, 0xAB, 0xEB, 0x04, 0x0B, 0x0A, 0xEB, 0x8B, 0x0A, 0xD8, 0xF8, 0x9C, 0x30, 0x30, 0x46, +0x98, 0x47, 0x9A, 0xF8, 0x19, 0x20, 0x2B, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x72, 0x12, 0x6C, 0xB2, 0x42, +0x3F, 0xF4, 0x51, 0xAF, 0x03, 0xFB, 0x05, 0x77, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, +0x47, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0xE0, 0xA2, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, +0x00, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0xA4, 0x88, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, +0xB8, 0xA2, 0x15, 0x00, 0xD4, 0xA2, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xBC, 0xA2, 0xDF, 0xF8, 0xB4, 0x82, 0xDA, 0xF8, 0x00, 0x30, +0x4F, 0xF4, 0xA4, 0x69, 0xB3, 0xF9, 0x00, 0x30, 0x09, 0xFB, 0x00, 0xF9, 0x08, 0xEB, 0x09, 0x02, 0x00, 0x2B, 0x14, 0x6C, +0x85, 0xB0, 0x05, 0x46, 0xC0, 0xF2, 0x99, 0x80, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x05, 0x86, 0x9A, 0x4F, 0x96, 0xF8, +0x4D, 0x00, 0x21, 0x7C, 0x97, 0xF8, 0x5A, 0x30, 0x62, 0x7E, 0x00, 0x93, 0xCD, 0xE9, 0x01, 0x01, 0x97, 0xF8, 0x5B, 0x30, +0x95, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0x06, 0xF0, 0xEF, 0xFA, 0x09, 0xF1, 0x44, 0x01, 0x07, 0xF1, 0x10, 0x00, 0x41, 0x44, +0x05, 0xF0, 0x0E, 0xF9, 0x96, 0xF8, 0x4D, 0x30, 0x23, 0xF0, 0x01, 0x02, 0x86, 0xF8, 0x4D, 0x20, 0x9A, 0x07, 0x09, 0xD5, +0x97, 0xF8, 0x5B, 0x30, 0x97, 0xF8, 0x5A, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x01, 0x2A, 0x87, 0xF8, 0x5B, 0x30, 0x5D, 0xD9, +0xDF, 0xF8, 0x3C, 0xB2, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x05, 0x85, 0x00, 0x23, 0x85, 0xF8, 0x4D, 0x30, 0x2B, 0x64, +0x66, 0x7E, 0x23, 0x7C, 0x01, 0x3E, 0xF6, 0xB2, 0x66, 0x76, 0x00, 0x2B, 0x45, 0xD0, 0x95, 0xF8, 0x63, 0x30, 0xE2, 0x7E, +0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x7C, 0x4B, 0x03, 0xF1, 0x54, 0x01, 0x1A, 0x7E, 0xFF, 0x2A, 0x03, 0xD0, 0xD8, 0x7E, +0xFF, 0x28, 0x40, 0xF0, 0xBD, 0x80, 0x1C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x00, 0x2E, 0x4E, 0xD0, 0xDB, 0xF8, 0xB4, 0x30, +0x20, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x97, 0xF8, 0x5A, 0x30, 0x00, 0x20, 0xB8, 0x62, 0x00, 0x2B, +0x59, 0xD0, 0x21, 0x7E, 0xDB, 0xF8, 0x9C, 0x50, 0x6C, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x00, 0xF0, 0xC0, 0x80, +0xC3, 0xEB, 0xC3, 0x06, 0x02, 0xEB, 0x86, 0x06, 0xD8, 0x00, 0x36, 0x7E, 0xFF, 0x2E, 0x40, 0xF0, 0xC3, 0x80, 0x01, 0x29, +0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, 0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, +0xFF, 0x29, 0x08, 0xBF, 0x00, 0x20, 0x40, 0xF0, 0xB3, 0x80, 0xA8, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0xCC, 0xD1, 0xDB, 0xF8, +0x48, 0x30, 0x20, 0x7E, 0x98, 0x47, 0xC7, 0xE7, 0x00, 0x2B, 0x9F, 0xD1, 0x97, 0xF8, 0x58, 0x30, 0xDF, 0xF8, 0x78, 0xB1, +0x5B, 0x06, 0x9B, 0xD5, 0x38, 0x6D, 0xDB, 0xF8, 0x5C, 0x30, 0x98, 0x47, 0x96, 0xE7, 0x00, 0x2C, 0x7F, 0xF4, 0x64, 0xAF, +0x51, 0x49, 0x52, 0x48, 0x40, 0xF6, 0xC4, 0x32, 0x06, 0xF0, 0x8C, 0xFC, 0x5C, 0xE7, 0x50, 0x48, 0x21, 0x46, 0x05, 0xF0, +0x83, 0xF8, 0x26, 0x74, 0x97, 0xF8, 0x5A, 0x30, 0xDA, 0xF8, 0x00, 0x20, 0x01, 0x3B, 0xDB, 0xB2, 0x87, 0xF8, 0x5A, 0x30, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x0A, 0xDB, 0x03, 0xBB, 0xBB, 0x6A, 0xA3, 0x42, 0xA2, 0xD0, 0xFB, 0x6A, 0xA3, 0x42, +0x31, 0xD0, 0x66, 0x7E, 0x00, 0x2E, 0xC8, 0xD0, 0x94, 0xE7, 0x01, 0x2B, 0xF2, 0xD9, 0x3F, 0x49, 0x41, 0x48, 0x4F, 0xF4, +0x40, 0x62, 0x06, 0xF0, 0x67, 0xFC, 0x97, 0xF8, 0x5A, 0x30, 0xE9, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x08, 0xEB, 0x09, 0x00, +0x98, 0x47, 0x66, 0x7E, 0xFF, 0x23, 0xE3, 0x76, 0x00, 0x2E, 0x7F, 0xF4, 0x7F, 0xAF, 0xCC, 0xE7, 0x38, 0x48, 0x04, 0xF0, +0xFD, 0xFF, 0x38, 0x4B, 0x03, 0xF5, 0xA4, 0x51, 0x93, 0xF8, 0x4D, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x4D, 0x20, +0x03, 0xF5, 0xA4, 0x63, 0x99, 0x42, 0xF5, 0xD1, 0x3B, 0x6D, 0x00, 0x2B, 0xCB, 0xD1, 0xDB, 0xF8, 0x34, 0x30, 0x98, 0x47, +0xC7, 0xE7, 0x21, 0x7E, 0x27, 0x4A, 0x02, 0x29, 0x01, 0xF1, 0x01, 0x03, 0x29, 0xD0, 0xC3, 0xEB, 0xC3, 0x05, 0x02, 0xEB, +0x85, 0x05, 0xD8, 0x00, 0x2D, 0x7E, 0xFF, 0x2D, 0x35, 0xD1, 0x01, 0x29, 0x01, 0xF1, 0x02, 0x03, 0x08, 0xBF, 0x00, 0x23, +0xC3, 0xEB, 0xC3, 0x01, 0x02, 0xEB, 0x81, 0x01, 0xD8, 0x00, 0x09, 0x7E, 0xFF, 0x29, 0x08, 0xBF, 0x00, 0x22, 0x26, 0xD1, +0xFA, 0x62, 0xAE, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x80, 0x03, 0x6C, 0xA3, 0x42, 0x3F, 0xF4, 0x3E, 0xAF, +0x66, 0xB1, 0xDB, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, 0x38, 0xAF, 0x85, 0xE7, 0x13, 0x7E, +0xFF, 0x2B, 0x0E, 0xD1, 0x01, 0x23, 0xDD, 0xE7, 0xDB, 0xF8, 0x94, 0x30, 0x98, 0x47, 0x66, 0x7E, 0x00, 0x2E, 0x7F, 0xF4, +0x2B, 0xAF, 0x78, 0xE7, 0x13, 0x7E, 0xFF, 0x2B, 0x07, 0xD1, 0x01, 0x23, 0x48, 0xE7, 0x00, 0x23, 0x18, 0x46, 0xC3, 0x1A, +0x02, 0xEB, 0x83, 0x02, 0xD4, 0xE7, 0x03, 0x46, 0xC0, 0x1A, 0x02, 0xEB, 0x80, 0x00, 0x48, 0xE7, 0x30, 0x9D, 0x17, 0x00, +0x08, 0xA3, 0x15, 0x00, 0x90, 0x9D, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA2, 0x15, 0x00, 0x38, 0x9D, 0x17, 0x00, +0x28, 0xA3, 0x15, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x43, 0x03, 0x46, 0x05, 0x78, 0x29, 0x4E, 0x2A, 0x4A, 0x04, 0x46, 0x53, 0xF8, 0x02, 0x0F, 0x97, 0x6A, +0x59, 0x68, 0xB3, 0xF8, 0x08, 0xC0, 0xC5, 0xEB, 0xC5, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x04, 0x33, 0x03, 0xC3, 0xC5, 0xEB, +0xC5, 0x02, 0x06, 0xEB, 0x82, 0x02, 0x97, 0x42, 0x85, 0xB0, 0xA3, 0xF8, 0x00, 0xC0, 0x02, 0xD0, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x83, 0x4F, 0xEA, 0xC5, 0x08, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x1A, 0x4F, 0xDF, 0xF8, 0x68, 0x90, 0x3B, 0x68, 0xD9, 0xF8, 0xA0, 0x22, 0x01, 0x33, 0x3B, 0x60, 0x90, 0x47, +0xD9, 0xF8, 0x88, 0x32, 0x00, 0x20, 0x98, 0x47, 0x3B, 0x68, 0x33, 0xB1, 0x11, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x3B, 0x60, +0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xE2, 0x7A, 0x23, 0x89, 0x00, 0x93, 0x00, 0x21, 0xCD, 0xE9, 0x01, 0x21, 0xA8, 0xEB, +0x05, 0x05, 0xE3, 0x88, 0xA0, 0x78, 0xA2, 0x88, 0xE1, 0x78, 0x06, 0xEB, 0x85, 0x06, 0xE2, 0xF7, 0x91, 0xFE, 0xD9, 0xF8, +0x3C, 0x33, 0x96, 0xF9, 0x0C, 0x00, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x43, 0x18, 0x47, 0x00, 0xBF, 0x90, 0x9D, 0x17, 0x00, +0x30, 0x9D, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, +0x12, 0x4A, 0x2B, 0x7C, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x03, 0x24, 0x06, 0x46, 0x22, 0x6C, 0x4A, 0xB1, 0x0F, 0x4C, +0x18, 0x46, 0x63, 0x6D, 0x98, 0x47, 0xE3, 0x6C, 0x28, 0x7C, 0x31, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x05, 0x22, +0x11, 0x46, 0x02, 0x23, 0x41, 0xF2, 0x17, 0x40, 0x04, 0xF0, 0x7E, 0xFA, 0x01, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x63, 0x20, +0x42, 0x70, 0x04, 0xF0, 0xA7, 0xFA, 0x03, 0x4C, 0xE9, 0xE7, 0x00, 0xBF, 0x00, 0x88, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x6B, 0x4D, 0x2C, 0x69, 0x07, 0x46, 0x8B, 0x46, 0x91, 0x46, 0x8C, 0xB3, +0x63, 0x68, 0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x8B, 0x42, 0x12, 0xD0, 0x05, 0xF1, 0x10, 0x06, 0xA3, 0xEB, +0x0B, 0x03, 0x00, 0x2B, 0x21, 0x46, 0x30, 0x46, 0x26, 0xDA, 0x04, 0xF0, 0x33, 0xFF, 0x63, 0x7A, 0x23, 0xF0, 0x01, 0x03, +0x63, 0x72, 0x2C, 0x69, 0xF4, 0xB1, 0x63, 0x68, 0x5B, 0x45, 0xEE, 0xD1, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, +0x00, 0x04, 0x1B, 0xD8, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, +0xB8, 0xEB, 0x0A, 0x00, 0x03, 0xF1, 0x01, 0x03, 0x18, 0xBF, 0x01, 0x20, 0x85, 0xF8, 0x5B, 0x30, 0xBD, 0xE8, 0xF8, 0x8F, +0xD0, 0xF8, 0x40, 0xA0, 0xD5, 0xF8, 0x28, 0x80, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x4F, 0xF0, 0x01, 0x04, 0xE3, 0xD9, +0x97, 0xF8, 0x4E, 0x30, 0xFF, 0x2B, 0x26, 0xD0, 0x49, 0x4E, 0x59, 0x46, 0x73, 0x6F, 0x38, 0x46, 0x98, 0x47, 0x00, 0x2C, +0x41, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x97, 0xF8, 0xC0, 0x24, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x82, 0xB1, +0x42, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x06, 0xD1, +0xBB, 0x6C, 0x4B, 0x45, 0x03, 0xD0, 0xA3, 0xEB, 0x09, 0x02, 0x32, 0x2A, 0x5D, 0xD4, 0xB8, 0xEB, 0x0A, 0x00, 0x18, 0xBF, +0x01, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x97, 0xF8, 0xC0, 0x34, 0xB3, 0xB3, 0x35, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, +0x01, 0xFB, 0x03, 0x21, 0x91, 0xF8, 0x70, 0x10, 0x01, 0x29, 0x35, 0xD0, 0x00, 0x2C, 0x4F, 0xD1, 0x30, 0x48, 0x07, 0xF1, +0x44, 0x01, 0x04, 0xF0, 0xC9, 0xFE, 0x97, 0xF8, 0x4D, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x87, 0xF8, +0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x33, 0x85, 0xF8, 0x5B, 0x30, 0xD7, 0xE7, 0x97, 0xF8, 0xC0, 0x34, 0x00, 0x2B, +0xE8, 0xD0, 0x24, 0x4A, 0x97, 0xF8, 0xC1, 0x34, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, +0xDE, 0xD1, 0xF3, 0x6A, 0x49, 0x46, 0x00, 0x22, 0x38, 0x46, 0x98, 0x47, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x08, 0x03, +0xDD, 0xE7, 0x00, 0x2C, 0xD2, 0xD0, 0x97, 0xF8, 0x4D, 0x30, 0x43, 0xF0, 0x04, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0xB6, 0xE7, +0x97, 0xF8, 0x4D, 0x10, 0xC8, 0x06, 0x0B, 0xD5, 0x12, 0x4E, 0x38, 0x46, 0xD6, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x97, 0xF8, +0x4D, 0x30, 0x23, 0xF0, 0x10, 0x03, 0x87, 0xF8, 0x4D, 0x30, 0x8A, 0xE7, 0x4E, 0x06, 0x10, 0xD4, 0x54, 0xB9, 0x0B, 0x4E, +0xD7, 0xE7, 0xA9, 0xEB, 0x03, 0x03, 0x32, 0x2B, 0x9D, 0xD5, 0xC7, 0xF8, 0x48, 0x90, 0x9A, 0xE7, 0x97, 0xF8, 0x4D, 0x10, +0x41, 0xF0, 0x04, 0x01, 0x87, 0xF8, 0x4D, 0x10, 0x85, 0xE7, 0x03, 0x4E, 0x38, 0x46, 0x33, 0x6F, 0x98, 0x47, 0x72, 0xE7, +0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x40, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x4D, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x2B, 0xD9, 0x90, 0xF8, 0x4D, 0x20, 0x04, 0x46, 0xD0, 0x06, 0x0F, 0xD5, +0x49, 0x4B, 0x03, 0xF1, 0x54, 0x00, 0x19, 0x7E, 0xFF, 0x29, 0x02, 0xD0, 0xD9, 0x7E, 0xFF, 0x29, 0x3B, 0xD1, 0x1C, 0x33, +0x98, 0x42, 0xF6, 0xD1, 0x02, 0xF0, 0xEF, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x91, 0x07, 0x14, 0xD4, 0x53, 0x07, 0x6E, 0x6A, +0x44, 0xBF, 0x22, 0xF0, 0x04, 0x02, 0x84, 0xF8, 0x4D, 0x20, 0x26, 0xB1, 0xF2, 0x68, 0x04, 0xF1, 0x44, 0x03, 0x9A, 0x42, +0x09, 0xD0, 0x3B, 0x4B, 0x61, 0x6A, 0xDB, 0x6A, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0xBD, 0xE8, +0xF0, 0x81, 0xD4, 0xF8, 0x48, 0x80, 0x67, 0x6A, 0xA8, 0xEB, 0x07, 0x03, 0x00, 0x2B, 0x20, 0xDB, 0xA7, 0xEB, 0x08, 0x03, +0x00, 0x2B, 0x29, 0xDB, 0x30, 0x4D, 0x6B, 0x6B, 0x98, 0x47, 0xEB, 0x6A, 0x61, 0x6A, 0x20, 0x46, 0x00, 0x22, 0x98, 0x47, +0x2D, 0x4A, 0xD5, 0xF8, 0x84, 0x30, 0x11, 0x69, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x2A, 0x4A, +0x27, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x8C, 0x30, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x20, +0xBA, 0xE7, 0xE2, 0xF7, 0xA5, 0xFD, 0xA7, 0xF5, 0x7A, 0x67, 0xA7, 0xEB, 0x08, 0x07, 0x38, 0x1A, 0x00, 0x28, 0x0C, 0xDB, +0x67, 0x6A, 0xD4, 0xF8, 0x48, 0x80, 0xD1, 0xE7, 0xE2, 0xF7, 0x98, 0xFD, 0xA8, 0xF5, 0x7A, 0x68, 0xA8, 0xEB, 0x07, 0x07, +0x3F, 0x1A, 0x00, 0x2F, 0xCC, 0xDA, 0x67, 0x6A, 0xA7, 0x64, 0xE2, 0xF7, 0x8D, 0xFD, 0x73, 0x68, 0xFF, 0x1A, 0x3F, 0x1A, +0xB7, 0xF5, 0x7A, 0x6F, 0xB5, 0xD5, 0xA4, 0x6C, 0xE2, 0xF7, 0x84, 0xFD, 0xAB, 0x6C, 0xA4, 0xF5, 0x7A, 0x64, 0x24, 0x1A, +0xB3, 0x42, 0x74, 0x60, 0xAB, 0xD1, 0x0D, 0x4C, 0x0F, 0x48, 0xD4, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0B, 0x4B, 0x71, 0x68, +0x1B, 0x69, 0xAE, 0x64, 0xCB, 0x1A, 0x14, 0x2B, 0x05, 0xD4, 0xD4, 0xF8, 0xE0, 0x31, 0x09, 0x48, 0xBD, 0xE8, 0xF0, 0x41, +0x18, 0x47, 0x6B, 0x6C, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x90, 0x9D, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x18, 0x88, 0x17, 0x00, 0x70, 0x9D, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x45, 0x4D, 0x95, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x90, 0xF8, 0x4D, 0x30, 0x51, 0xD9, 0x9E, 0x06, 0x04, 0xD5, +0x41, 0x4B, 0x9B, 0x6F, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0x67, 0x6A, 0x13, 0xF0, 0x04, 0x06, 0x3D, 0xD1, 0x99, 0x07, +0x42, 0xD5, 0x03, 0xF0, 0xFD, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x20, 0x01, 0x3A, 0xD2, 0xB2, 0x85, 0xF8, +0x5B, 0x20, 0x4A, 0xB9, 0x95, 0xF8, 0x58, 0x20, 0x52, 0x06, 0x5B, 0xD5, 0x34, 0x4B, 0x28, 0x6D, 0xDB, 0x6D, 0x98, 0x47, +0x94, 0xF8, 0x4D, 0x30, 0xD4, 0xF8, 0x48, 0x80, 0x13, 0xF0, 0x08, 0x02, 0x42, 0xD0, 0x94, 0xF8, 0x62, 0x20, 0x23, 0xF0, +0x08, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0x00, 0x2A, 0x4A, 0xD0, 0x02, 0x2A, 0x0A, 0xBF, 0xB4, 0xF8, 0xD2, 0x30, 0x4F, 0xF4, +0xC8, 0x33, 0x9B, 0x02, 0xA8, 0xEB, 0x03, 0x08, 0xB6, 0xB1, 0xEB, 0x6A, 0x26, 0x4A, 0x15, 0x69, 0x93, 0xB9, 0x24, 0x4E, +0x73, 0x6B, 0x98, 0x47, 0xD6, 0xF8, 0x84, 0x30, 0xA5, 0xEB, 0x08, 0x02, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, +0x18, 0x47, 0x13, 0xF0, 0x01, 0x02, 0x23, 0xD0, 0x23, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x4D, 0x30, 0xBD, 0xE8, 0xF0, 0x81, +0x9A, 0x07, 0xFB, 0xD5, 0x23, 0xF0, 0x02, 0x03, 0x80, 0xF8, 0x4D, 0x30, 0x95, 0xF8, 0x5B, 0x30, 0x01, 0x3B, 0xDB, 0xB2, +0x85, 0xF8, 0x5B, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x95, 0xF8, 0x58, 0x30, 0x5F, 0x06, 0xEB, 0xD5, 0x10, 0x4B, 0x28, 0x6D, +0xDB, 0x6D, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x0D, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0xC7, 0xE7, +0x0A, 0x4B, 0x39, 0x46, 0xDB, 0x6A, 0x20, 0x46, 0x98, 0x47, 0x94, 0xF8, 0x4D, 0x30, 0xD3, 0xE7, 0x01, 0x26, 0xA7, 0xE7, +0x07, 0x4A, 0x94, 0xF8, 0x6C, 0x30, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x9B, 0x68, 0xB2, 0xE7, 0x00, 0xBF, +0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0x28, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2D, 0xE9, 0xF0, 0x41, 0x07, 0x6C, 0x05, 0x46, 0x3E, 0xDB, 0x24, 0x4E, 0x96, 0xF8, +0x58, 0x20, 0x12, 0xF0, 0x20, 0x04, 0x03, 0xD1, 0x96, 0xF8, 0x5A, 0x30, 0x01, 0x2B, 0x01, 0xD8, 0xBD, 0xE8, 0xF0, 0x81, +0x14, 0x23, 0x22, 0x46, 0x21, 0x46, 0x46, 0x20, 0x95, 0xF8, 0x6C, 0x80, 0x04, 0xF0, 0x2E, 0xF8, 0x04, 0x70, 0x95, 0xF8, +0x63, 0x10, 0x41, 0x70, 0x39, 0x79, 0x19, 0x4A, 0x81, 0x70, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x08, 0x28, 0x7A, 0x79, +0xC2, 0x70, 0xD8, 0xF8, 0x08, 0x20, 0x15, 0x4D, 0xB7, 0xF8, 0x06, 0xC0, 0x3C, 0x89, 0x79, 0x89, 0x01, 0x81, 0xA2, 0xF5, +0x9C, 0x52, 0x08, 0x3A, 0xA5, 0xFB, 0x02, 0x52, 0x92, 0x09, 0xA0, 0xF8, 0x04, 0xC0, 0xC4, 0x80, 0xC2, 0x60, 0x3A, 0x7B, +0x02, 0x74, 0x04, 0xF0, 0x3B, 0xF8, 0x96, 0xF8, 0x58, 0x30, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x58, 0x30, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0x2F, 0xBE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF6, 0x71, 0x52, 0x06, 0xF0, 0xDD, 0xF8, 0xB7, 0xE7, +0x38, 0x36, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xD3, 0x4D, 0x62, 0x10, 0x70, 0x79, 0x15, 0x00, +0xC8, 0xA0, 0x15, 0x00, 0x70, 0x47, 0x00, 0xBF, 0x0A, 0x4B, 0x9B, 0x6A, 0x83, 0xB1, 0x1A, 0x7E, 0x02, 0x2A, 0x05, 0xD8, +0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x9B, 0x7E, 0x90, 0xF8, 0x63, 0x00, 0x18, 0x1A, +0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x30, 0x9D, 0x17, 0x00, 0x10, 0x4A, 0x93, 0x6A, +0xDB, 0xB1, 0x19, 0x7E, 0x02, 0x29, 0x0E, 0xD8, 0x00, 0x6C, 0xC0, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x88, 0xB1, +0xD2, 0x6A, 0x7A, 0xB1, 0x18, 0x7C, 0xA0, 0xF1, 0x06, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x90, 0xF8, +0x63, 0x10, 0x98, 0x7E, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x00, 0x28, 0xED, 0xD1, 0x70, 0x47, 0x18, 0x46, +0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x0E, 0x4B, 0x9B, 0x6A, 0x23, 0xB1, 0x02, 0x6C, 0x98, 0x88, 0x91, 0x88, +0x88, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x58, 0x7B, 0x51, 0x7B, 0x88, 0x42, 0xF9, 0xD1, 0xD8, 0x88, 0xD1, 0x88, +0x88, 0x42, 0xF5, 0xD1, 0x18, 0x89, 0x11, 0x89, 0x88, 0x42, 0xF1, 0xD1, 0x5B, 0x89, 0x50, 0x89, 0x18, 0x1A, 0xB0, 0xFA, +0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x30, 0x9D, 0x17, 0x00, 0x43, 0x7E, 0xDB, 0xB1, 0x0E, 0x4B, 0x30, 0xB4, +0x7F, 0x21, 0x03, 0xF5, 0xA4, 0x54, 0x1A, 0x6C, 0x82, 0x42, 0x08, 0xD0, 0x03, 0xF5, 0xA4, 0x63, 0xA3, 0x42, 0xF8, 0xD1, +0x7F, 0x29, 0x30, 0xBC, 0x18, 0xBF, 0x01, 0x73, 0x70, 0x47, 0x93, 0xF9, 0x66, 0x20, 0x93, 0xF9, 0x65, 0x50, 0xAA, 0x42, +0xA8, 0xBF, 0x2A, 0x46, 0x91, 0x42, 0xA8, 0xBF, 0x11, 0x46, 0xEB, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x70, 0xB5, 0x11, 0x4E, 0x11, 0x4A, 0xD6, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xD0, 0xB1, 0x0F, 0x4B, 0x10, 0x4D, +0x5B, 0x78, 0x00, 0x22, 0x2A, 0x77, 0x23, 0xB1, 0x0E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x2B, 0x7A, +0x0B, 0xB1, 0x01, 0x3B, 0x2B, 0x72, 0xD6, 0xF8, 0xD8, 0x31, 0x0A, 0x48, 0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0x63, 0x68, +0x23, 0xF4, 0x01, 0x73, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x70, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xDD, 0xEA, 0x13, 0x00, +0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x70, 0xB5, 0x14, 0x4D, +0x14, 0x4A, 0xD5, 0xF8, 0x4C, 0x32, 0x04, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x12, 0x4A, 0x13, 0x4B, 0x52, 0x78, 0x01, 0x21, +0x19, 0x77, 0x22, 0xB1, 0x11, 0x49, 0x0A, 0x68, 0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, +0x1A, 0x72, 0x0E, 0x4A, 0x0E, 0x49, 0x12, 0x68, 0x09, 0x69, 0xD0, 0x8E, 0x5C, 0x61, 0x04, 0x26, 0x5E, 0x77, 0x01, 0x44, +0xD5, 0xF8, 0xE0, 0x21, 0x0A, 0x48, 0x90, 0x47, 0x63, 0x68, 0x43, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x70, 0xBD, 0x00, 0xBF, +0x88, 0x1A, 0x17, 0x00, 0x3D, 0xEB, 0x13, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, +0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4A, 0x0B, 0x46, 0x0C, 0x46, +0x05, 0x46, 0x0F, 0x49, 0x02, 0x20, 0x05, 0xF0, 0xB3, 0xFD, 0x0E, 0x4B, 0x0E, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, +0x28, 0x46, 0x98, 0x47, 0x30, 0xB1, 0x0C, 0x4A, 0x13, 0x7A, 0x23, 0xB1, 0x01, 0x3B, 0xDB, 0xB2, 0x13, 0x72, 0x03, 0xB1, +0x38, 0xBD, 0x01, 0x23, 0x13, 0x70, 0x51, 0x88, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0x32, 0x20, 0x03, 0xF0, 0x4A, 0xBF, +0x68, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xB1, 0xEB, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0x38, 0xB5, 0x18, 0x4A, 0x0B, 0x46, 0x0C, 0x46, 0x05, 0x46, 0x17, 0x49, 0x02, 0x20, 0x05, 0xF0, 0x87, 0xFD, 0x16, 0x4B, +0x16, 0x4A, 0xD3, 0xF8, 0x4C, 0x32, 0x21, 0x46, 0x28, 0x46, 0x98, 0x47, 0xF8, 0xB1, 0x14, 0x48, 0x03, 0x7A, 0xBB, 0xB9, +0x13, 0x4B, 0x9B, 0x68, 0x63, 0xB1, 0x93, 0xF8, 0x62, 0x20, 0x32, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x1A, 0xB1, 0x5A, 0x68, +0x22, 0xF0, 0x0E, 0x02, 0x5A, 0x60, 0x1B, 0x68, 0x00, 0x2B, 0xF2, 0xD1, 0x00, 0x22, 0x02, 0x70, 0x41, 0x88, 0xBD, 0xE8, +0x38, 0x40, 0x32, 0x20, 0x03, 0xF0, 0x14, 0xBF, 0x01, 0x3B, 0xDB, 0xB2, 0x03, 0x72, 0x00, 0x2B, 0xE2, 0xD0, 0x38, 0xBD, +0x78, 0xA3, 0x15, 0x00, 0x44, 0xA3, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0x00, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x11, 0xF4, 0x00, 0x03, 0x04, 0x46, 0x2A, 0xD1, 0x90, 0xF8, 0x6B, 0x00, 0x25, 0x49, +0x01, 0x30, 0xC0, 0xB2, 0x09, 0x68, 0x84, 0xF8, 0x6B, 0x00, 0x49, 0x78, 0x81, 0x42, 0x29, 0xD0, 0x94, 0xF8, 0x64, 0x50, +0x00, 0x2D, 0x34, 0xD1, 0x1F, 0x4A, 0x20, 0x4B, 0x52, 0x78, 0x01, 0x21, 0x19, 0x77, 0x22, 0xB1, 0x1E, 0x49, 0x0A, 0x68, +0x22, 0xF0, 0x00, 0x42, 0x0A, 0x60, 0x1A, 0x7A, 0x0A, 0xB1, 0x01, 0x3A, 0x1A, 0x72, 0x1B, 0x4A, 0x1B, 0x48, 0xD2, 0xF8, +0xD8, 0x21, 0x00, 0x21, 0x59, 0x77, 0x90, 0x47, 0x63, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x63, 0x60, 0x28, 0x46, 0x38, 0xBD, +0x28, 0xB1, 0x00, 0x23, 0x01, 0x25, 0x80, 0xF8, 0x6B, 0x30, 0x28, 0x46, 0x38, 0xBD, 0x01, 0x25, 0x28, 0x46, 0x38, 0xBD, +0x11, 0x49, 0x84, 0xF8, 0x6B, 0x30, 0x4F, 0xF4, 0x80, 0x60, 0x05, 0xF0, 0x11, 0xFD, 0x0C, 0x4B, 0x20, 0x46, 0xD3, 0xF8, +0xBC, 0x31, 0x01, 0x25, 0x98, 0x47, 0x28, 0x46, 0x38, 0xBD, 0x11, 0x46, 0x1D, 0x46, 0x94, 0xF8, 0x6C, 0x00, 0x22, 0x46, +0xF1, 0xF7, 0xD0, 0xF9, 0x28, 0x46, 0x38, 0xBD, 0xC8, 0x35, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0x34, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x28, 0x9E, 0x17, 0x00, 0x4C, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x13, 0x4D, +0x2B, 0x78, 0x13, 0xB3, 0x2B, 0x7F, 0x03, 0xB3, 0x11, 0x4A, 0x12, 0x49, 0x13, 0x68, 0x8C, 0x68, 0x43, 0xF0, 0x04, 0x03, +0x00, 0x21, 0x13, 0x60, 0x29, 0x72, 0xB4, 0xB1, 0x0E, 0x4E, 0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, +0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, 0x07, 0xD0, 0xD6, 0xF8, 0x34, 0x12, 0xF1, 0xF7, 0xA0, 0xF9, +0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, 0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x1C, 0x9E, 0x17, 0x00, +0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x12, 0x4D, 0x2B, 0x7F, 0xFB, 0xB9, +0x11, 0x49, 0x12, 0x48, 0x0A, 0x68, 0x84, 0x68, 0x2B, 0x72, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0xB4, 0xB1, 0x0F, 0x4E, +0x94, 0xF8, 0x62, 0x30, 0x7B, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x63, 0xB1, 0x94, 0xF8, 0x6C, 0x00, 0xFF, 0x28, 0x22, 0x46, +0x07, 0xD0, 0xD6, 0xF8, 0x58, 0x12, 0xF1, 0xF7, 0x73, 0xF9, 0x10, 0xB9, 0x2B, 0x7A, 0x01, 0x33, 0x2B, 0x72, 0x24, 0x68, +0x00, 0x2C, 0xE9, 0xD1, 0x70, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x2E, 0x4B, 0x2E, 0x4D, 0x1B, 0x68, 0x2E, 0x4A, 0x1B, 0x78, 0xD2, 0xF8, 0xF8, 0x21, +0x01, 0x2B, 0x6B, 0x68, 0x04, 0x46, 0x03, 0xF0, 0x20, 0x03, 0x44, 0xD0, 0x13, 0x43, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, +0x94, 0xF8, 0xAC, 0x30, 0x53, 0xB1, 0x27, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x13, 0xB1, 0x94, 0xF8, 0x64, 0x30, 0x33, 0xBB, +0x00, 0x23, 0x6B, 0x77, 0x63, 0x60, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x00, 0x2B, 0xF6, 0xD0, 0x94, 0xF8, +0x64, 0x30, 0x00, 0x2B, 0xF2, 0xD0, 0xC0, 0xB1, 0x1D, 0x4B, 0x1A, 0x68, 0x92, 0x01, 0x05, 0xD4, 0x1B, 0x68, 0x9B, 0x01, +0x11, 0xD4, 0x95, 0xF8, 0x24, 0x30, 0x73, 0xB1, 0x6B, 0x7F, 0x05, 0x2B, 0x05, 0xD1, 0x63, 0x68, 0x00, 0x22, 0x23, 0xF0, +0x02, 0x03, 0x63, 0x60, 0x6A, 0x77, 0x15, 0x4B, 0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x50, 0x32, 0x18, 0x47, 0x13, 0x4B, +0x13, 0x4A, 0x19, 0x68, 0x10, 0x4B, 0xC9, 0x8E, 0x6C, 0x61, 0x01, 0x20, 0x68, 0x77, 0x12, 0x69, 0xD3, 0xF8, 0xE0, 0x31, +0x0F, 0x48, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x44, 0x18, 0x47, 0x13, 0x43, 0x01, 0xD0, 0x00, 0x20, 0xBA, 0xE7, 0xE9, 0xF7, +0x37, 0xFD, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xB4, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x28, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x28, 0x22, 0x20, 0x46, 0x00, 0x21, 0xE1, 0xF7, +0x5F, 0xF9, 0x04, 0x4A, 0x01, 0x23, 0xD2, 0xF8, 0x38, 0x22, 0x22, 0x61, 0x23, 0x77, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x4C, 0x23, 0x78, 0x33, 0xB9, 0x0B, 0x4B, 0xD3, 0xF8, 0xF8, 0x31, 0x98, 0x47, +0x08, 0xB9, 0x00, 0x20, 0x10, 0xBD, 0x63, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x07, 0x4B, 0x9B, 0x68, 0x13, 0xB9, 0x05, 0xE0, +0x1B, 0x68, 0x1B, 0xB1, 0x5A, 0x68, 0x00, 0x2A, 0xFA, 0xD0, 0xF0, 0xE7, 0x01, 0x20, 0x10, 0xBD, 0x1C, 0x9E, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x08, 0x4B, 0x09, 0x4A, 0x1B, 0x68, 0x51, 0x80, 0x1B, 0x78, 0x02, 0x2B, +0x07, 0x4B, 0x03, 0xD0, 0x07, 0x49, 0x00, 0x28, 0x18, 0xBF, 0x0B, 0x46, 0x00, 0x20, 0x10, 0x72, 0x4F, 0xF4, 0x00, 0x01, +0x18, 0x47, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x09, 0xEC, 0x13, 0x00, 0xB1, 0xEB, 0x13, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x92, 0xF8, 0x6C, 0x30, 0x42, 0x4C, 0x43, 0x4E, 0x51, 0x68, 0x4F, 0xF4, 0x1E, 0x75, 0x91, 0x46, +0x05, 0xFB, 0x03, 0x43, 0x32, 0x78, 0x1D, 0x8C, 0x21, 0xF0, 0x01, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x00, 0x2A, 0x49, 0xD0, +0x04, 0x46, 0x00, 0x28, 0x46, 0xD0, 0x99, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0x44, 0xD0, 0x00, 0xF1, 0x04, 0x08, 0x98, 0xF8, +0x00, 0x30, 0x03, 0xF0, 0xFE, 0x03, 0xB3, 0xEB, 0xD5, 0x0F, 0x4F, 0xEA, 0xD5, 0x00, 0x31, 0xD8, 0x61, 0x78, 0x04, 0x39, +0x19, 0x44, 0x88, 0x42, 0x2C, 0xD8, 0x20, 0x44, 0xC3, 0x1A, 0x05, 0xF0, 0x07, 0x05, 0x59, 0x79, 0x01, 0x23, 0x03, 0xFA, +0x05, 0xF5, 0x29, 0x42, 0x22, 0xD0, 0x2C, 0x4B, 0x19, 0x68, 0x8A, 0x05, 0x03, 0xD5, 0x19, 0x68, 0x21, 0xF4, 0x00, 0x71, +0x19, 0x60, 0x29, 0x4C, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x28, 0x48, 0xD9, 0xF8, 0x04, 0x30, 0x00, 0x68, 0x27, 0x49, +0xD4, 0xF8, 0xE0, 0x41, 0x40, 0x8F, 0x43, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x09, 0x69, 0xC6, 0xF8, 0x14, 0x90, +0x06, 0x23, 0x73, 0x77, 0x01, 0x44, 0x23, 0x46, 0x20, 0x48, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xD9, 0xF8, 0x04, 0x30, +0x23, 0xF0, 0x04, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0xBD, 0xE8, 0xF0, 0x87, 0x03, 0x79, 0x00, 0xF1, 0x04, 0x08, 0xD8, 0x07, +0x1E, 0xD5, 0x14, 0x4B, 0x47, 0xF0, 0x02, 0x07, 0xC9, 0xF8, 0x04, 0x70, 0x19, 0x68, 0x89, 0x05, 0x03, 0xD5, 0x19, 0x68, +0x21, 0xF4, 0x00, 0x71, 0x19, 0x60, 0x73, 0x7F, 0x00, 0x2B, 0xA8, 0xD1, 0x0E, 0x4B, 0x0F, 0x49, 0x1B, 0x68, 0x09, 0x69, +0x1F, 0x8F, 0x0B, 0x4B, 0xC6, 0xF8, 0x14, 0x90, 0x05, 0x20, 0x70, 0x77, 0xD3, 0xF8, 0xE0, 0x31, 0x0A, 0x48, 0x39, 0x44, +0x98, 0x47, 0x98, 0xE7, 0x21, 0xF0, 0x03, 0x01, 0xC9, 0xF8, 0x04, 0x10, 0x93, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, +0x1C, 0x9E, 0x17, 0x00, 0x90, 0xB3, 0x33, 0x40, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, +0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4E, 0x14, 0x46, 0x52, 0x68, 0x35, 0x78, 0x22, 0xF0, 0x01, 0x03, +0x63, 0x60, 0x00, 0x2D, 0x32, 0xD0, 0x0F, 0x46, 0x94, 0xF8, 0x6A, 0x10, 0xA1, 0xB9, 0x00, 0x28, 0x2E, 0xD0, 0x1B, 0x4A, +0x1B, 0x49, 0x10, 0x68, 0x1B, 0x4A, 0x00, 0x8F, 0xD2, 0xF8, 0xE0, 0x21, 0x43, 0xF0, 0x02, 0x03, 0x63, 0x60, 0x09, 0x69, +0x74, 0x61, 0x05, 0x23, 0x01, 0x44, 0x73, 0x77, 0x06, 0xF1, 0x0C, 0x00, 0x90, 0x47, 0x63, 0x68, 0xAF, 0xB1, 0x13, 0x4D, +0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD5, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x0D, 0x4B, 0x0E, 0x4A, 0x1B, 0x68, 0x11, 0x69, +0x58, 0x8F, 0x74, 0x61, 0x06, 0x22, 0xD5, 0xF8, 0xE0, 0x31, 0x72, 0x77, 0x01, 0x44, 0xBD, 0xE8, 0xF0, 0x41, 0x0A, 0x48, +0x18, 0x47, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x22, 0xF0, 0x03, 0x03, 0x00, 0x2F, 0xF6, 0xD0, +0xDF, 0xE7, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x28, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x21, 0x4D, 0x2B, 0x78, 0xAB, 0xB1, 0x03, 0x79, 0x06, 0x88, 0xDF, 0x07, +0x14, 0x46, 0x12, 0xD5, 0x6B, 0x7F, 0x05, 0x2B, 0x07, 0xD1, 0x1D, 0x4B, 0x05, 0xF1, 0x0C, 0x00, 0xD3, 0xF8, 0xD8, 0x31, +0x98, 0x47, 0x00, 0x23, 0x6B, 0x77, 0xB5, 0x04, 0x23, 0xD4, 0x63, 0x68, 0x23, 0xF0, 0x02, 0x03, 0x63, 0x60, 0xBD, 0xE8, +0xF0, 0x81, 0x88, 0x05, 0xFB, 0xD4, 0x15, 0x4A, 0x15, 0x4B, 0x12, 0x68, 0x1B, 0x69, 0xD1, 0x8E, 0x11, 0x4F, 0x6C, 0x61, +0x02, 0x22, 0x19, 0x44, 0x6A, 0x77, 0xD7, 0xF8, 0xE0, 0x31, 0x05, 0xF1, 0x0C, 0x00, 0x98, 0x47, 0xB1, 0x04, 0x63, 0x68, +0x0E, 0xD5, 0x5A, 0x07, 0x5C, 0xBF, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xD7, 0xF8, 0x54, 0x32, 0xBD, 0xE8, 0xF0, 0x41, +0x18, 0x47, 0x94, 0xF8, 0x6A, 0x30, 0x00, 0x2B, 0xDB, 0xD0, 0xD6, 0xE7, 0x23, 0xF0, 0x04, 0x03, 0x63, 0x60, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, +0x38, 0xB5, 0x23, 0x4B, 0x1A, 0x78, 0x00, 0x2A, 0x3F, 0xD0, 0xFF, 0x28, 0x3D, 0xD0, 0xFF, 0x29, 0x3B, 0xD0, 0x20, 0x4A, +0x20, 0x49, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x20, 0x4F, 0xF4, 0xA4, 0x64, 0x90, 0xF8, 0x22, 0x20, 0x04, 0xFB, +0x02, 0x12, 0x92, 0xF8, 0x62, 0x10, 0x00, 0x29, 0x2B, 0xD1, 0x92, 0xF8, 0x64, 0x10, 0x41, 0xB3, 0x18, 0x48, 0x19, 0x49, +0x00, 0x68, 0x09, 0x69, 0xC5, 0x8E, 0x18, 0x4C, 0x5A, 0x61, 0x03, 0x20, 0x58, 0x77, 0xD4, 0xF8, 0xE0, 0x21, 0x03, 0xF1, +0x0C, 0x00, 0x29, 0x44, 0x90, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0x5B, 0x07, 0x15, 0xD5, 0x13, 0x4B, 0x93, 0xF8, 0xB6, 0x30, +0x73, 0xB1, 0x12, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x02, 0x2B, 0x09, 0xD1, 0x10, 0x49, 0x11, 0x4A, 0x0B, 0x68, 0x23, 0xF4, +0x00, 0x73, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0xD4, 0xF8, 0x54, 0x32, 0x98, 0x47, 0x00, 0x20, +0x38, 0xBD, 0x00, 0xBF, 0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, +0x90, 0xB3, 0x33, 0x40, 0x8C, 0x00, 0x32, 0x40, 0x3B, 0x4A, 0xDF, 0xF8, 0x1C, 0xC1, 0x13, 0x68, 0x3A, 0x49, 0xF0, 0xB5, +0x3A, 0x4F, 0x3B, 0x4C, 0xB7, 0xF8, 0xB2, 0x00, 0x3A, 0x4D, 0x3B, 0x4E, 0x43, 0xF0, 0x80, 0x43, 0x13, 0x60, 0x23, 0x68, +0x39, 0x4A, 0x43, 0xF0, 0x80, 0x53, 0x23, 0x60, 0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF4, 0x70, 0x23, 0xCC, 0xF8, 0x00, 0x30, +0xDC, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0xFF, 0x03, 0x43, 0xF0, 0x10, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x23, 0xF0, +0xFC, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x0B, 0x68, 0x40, 0x09, 0x00, 0xF1, 0x20, 0x0C, 0xC3, 0xF3, 0x15, 0x03, +0x43, 0xEA, 0x8C, 0x53, 0x0B, 0x60, 0x83, 0xB0, 0x33, 0x68, 0x29, 0x49, 0x1B, 0x78, 0xCD, 0xF8, 0x00, 0xC0, 0x02, 0x20, +0x05, 0xF0, 0x0A, 0xFA, 0x32, 0x68, 0x13, 0x78, 0x01, 0x2B, 0x15, 0xD0, 0x02, 0x2B, 0x11, 0xD1, 0x23, 0x48, 0x24, 0x49, +0x03, 0x68, 0x24, 0x4C, 0x1D, 0x4A, 0x43, 0xF4, 0x80, 0x33, 0x03, 0x60, 0x0B, 0x68, 0x3F, 0x20, 0x23, 0xF0, 0x00, 0x73, +0x0B, 0x60, 0x20, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x03, 0xB0, 0xF0, 0xBD, 0x97, 0xF8, 0xB5, 0x10, +0x69, 0xB1, 0x19, 0x49, 0x19, 0x48, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x73, 0x0B, 0x60, 0x2B, 0x68, 0x24, 0x21, 0x43, 0xF4, +0x00, 0x13, 0x2B, 0x60, 0x01, 0x60, 0x13, 0x78, 0xD8, 0xE7, 0x12, 0x48, 0x12, 0x4E, 0x01, 0x68, 0x12, 0x4D, 0x41, 0xF0, +0x00, 0x71, 0x01, 0x60, 0x04, 0x21, 0x31, 0x60, 0x2B, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, 0x23, 0xF0, 0x01, 0x03, +0x23, 0x60, 0x13, 0x78, 0xC6, 0xE7, 0x00, 0xBF, 0x90, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, +0x74, 0x80, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x74, 0x36, 0x17, 0x00, 0x88, 0xA3, 0x15, 0x00, 0x5C, 0xA3, 0x15, 0x00, +0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x78, 0x00, 0x32, 0x40, +0x15, 0x48, 0x16, 0x4A, 0x16, 0x49, 0x38, 0xB5, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x02, 0x20, 0x05, 0xF0, +0xA7, 0xF9, 0x13, 0x4B, 0x9B, 0x7C, 0x23, 0xB9, 0x12, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x11, 0x4C, +0x11, 0x48, 0x23, 0x68, 0x0E, 0x49, 0x11, 0x4D, 0x11, 0x4A, 0x23, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x23, 0xF0, +0x80, 0x43, 0x03, 0x60, 0x0B, 0x68, 0x00, 0x20, 0x23, 0xF0, 0x80, 0x53, 0x0B, 0x60, 0x28, 0x60, 0x13, 0x68, 0x23, 0xF0, +0x01, 0x03, 0x13, 0x60, 0x38, 0xBD, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xA3, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, +0x00, 0x88, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x44, 0x00, 0x32, 0x40, 0x90, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, +0x6C, 0x00, 0x32, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x72, 0x30, 0x01, 0x2B, 0x04, 0x46, 0x11, 0xD0, 0x02, 0x2B, 0x00, 0xD0, +0x70, 0xBD, 0x0C, 0x4D, 0x41, 0x6F, 0x01, 0x23, 0x80, 0xF8, 0x72, 0x30, 0xD5, 0xF8, 0xE0, 0x31, 0x60, 0x30, 0x98, 0x47, +0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x04, 0x4B, 0x00, 0x22, 0x80, 0xF8, 0x72, 0x20, +0xBD, 0xE8, 0x70, 0x40, 0xD3, 0xF8, 0x18, 0x32, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x4F, 0xF0, 0x00, 0x0C, 0x4F, 0xF0, 0x01, 0x0E, 0x83, 0xB0, 0x06, 0x46, 0x04, 0x46, 0x00, 0xF1, 0x60, 0x05, 0x03, 0x46, +0x67, 0x46, 0x71, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x13, 0xD1, 0xDA, 0x7C, 0x01, 0x2A, 0x10, 0xD8, 0x96, 0xF8, 0x87, 0x20, +0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, 0x06, 0xD0, 0xDA, 0x68, 0x00, 0x29, +0x00, 0xF0, 0xC0, 0x80, 0x01, 0x37, 0x94, 0x46, 0x00, 0x21, 0x30, 0x33, 0x9D, 0x42, 0xE5, 0xD1, 0x01, 0x22, 0x8E, 0x46, +0x33, 0x46, 0x4F, 0xF0, 0x00, 0x09, 0x00, 0x92, 0xA0, 0x46, 0x1A, 0x7C, 0x02, 0x2A, 0x1D, 0xD1, 0xD9, 0x7C, 0x01, 0x29, +0x1A, 0xD9, 0x96, 0xF8, 0x87, 0x20, 0x32, 0xB1, 0x93, 0xF8, 0x21, 0x20, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x20, 0x01, 0x2A, +0x10, 0xD0, 0xD3, 0xE9, 0x06, 0x04, 0xDA, 0x68, 0x04, 0xEB, 0x02, 0x0A, 0xAA, 0xEB, 0x00, 0x00, 0xBE, 0xF1, 0x00, 0x0F, +0x42, 0xD0, 0x00, 0x21, 0x00, 0x91, 0x01, 0x37, 0x81, 0x46, 0x94, 0x46, 0x4F, 0xF0, 0x00, 0x0E, 0x30, 0x33, 0x9D, 0x42, +0xDB, 0xD1, 0x01, 0x96, 0x44, 0x46, 0x00, 0x9E, 0x18, 0xE0, 0x00, 0x2F, 0x5F, 0xD1, 0xA1, 0xEB, 0x09, 0x02, 0x00, 0x2A, +0x58, 0xDB, 0xAC, 0xEB, 0x03, 0x02, 0x00, 0x2A, 0x0B, 0xDB, 0xA3, 0xEB, 0x09, 0x00, 0xAC, 0xEB, 0x01, 0x02, 0x39, 0xEA, +0x20, 0x09, 0x28, 0xBF, 0x99, 0x46, 0x3C, 0xEA, 0x22, 0x0C, 0x28, 0xBF, 0x8C, 0x46, 0x30, 0x34, 0xA5, 0x42, 0x0F, 0xD0, +0x23, 0x7C, 0x01, 0x2B, 0xF9, 0xD1, 0xE3, 0x68, 0xA1, 0x69, 0x19, 0x44, 0xBE, 0xF1, 0x00, 0x0F, 0xDD, 0xD0, 0x30, 0x34, +0x00, 0x26, 0xA5, 0x42, 0x99, 0x46, 0x8C, 0x46, 0xB6, 0x46, 0xEF, 0xD1, 0x33, 0x46, 0x01, 0x9E, 0xC6, 0xF8, 0x80, 0xC0, +0x0B, 0xB1, 0x0C, 0xF1, 0x0A, 0x09, 0xC6, 0xF8, 0x7C, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA0, 0xEB, 0x0C, 0x0A, +0xBA, 0xF1, 0x00, 0x0F, 0x80, 0xF2, 0x88, 0x80, 0xA4, 0xEB, 0x02, 0x0B, 0x02, 0xEB, 0x0C, 0x0A, 0x01, 0x39, 0x83, 0x44, +0xA0, 0xEB, 0x0A, 0x0A, 0x01, 0xE0, 0x01, 0x39, 0xB2, 0xD0, 0x0B, 0xEB, 0x02, 0x00, 0x22, 0x44, 0x1A, 0xEB, 0x02, 0x0F, +0xF7, 0xD4, 0xAC, 0xEB, 0x02, 0x04, 0x3C, 0xEA, 0x24, 0x0C, 0x28, 0xBF, 0x94, 0x46, 0x01, 0x29, 0x3D, 0xD0, 0x62, 0x46, +0x00, 0x99, 0x00, 0x29, 0x99, 0xD1, 0xA0, 0xEB, 0x09, 0x01, 0x10, 0xEA, 0x21, 0x00, 0x38, 0xBF, 0x48, 0x46, 0x94, 0xE7, +0x99, 0x46, 0x8C, 0x46, 0xB3, 0xE7, 0xA1, 0xEB, 0x0C, 0x02, 0x00, 0x2A, 0x94, 0xF8, 0x13, 0x80, 0x61, 0xDA, 0x08, 0xF1, +0xFF, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0xA8, 0xD0, 0xD4, 0xF8, 0x1C, 0xB0, 0x9A, 0x46, 0x03, 0xE0, 0x42, 0x1E, 0x00, 0x28, +0xA1, 0xD0, 0x10, 0x46, 0xDA, 0x44, 0x01, 0xEB, 0x0A, 0x08, 0xA8, 0xEB, 0x0C, 0x02, 0xD2, 0x1A, 0x00, 0x2A, 0xA8, 0xEB, +0x03, 0x08, 0xF1, 0xDB, 0xA6, 0xB1, 0xAC, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x29, 0xDB, 0x58, 0xB3, 0xE3, 0x69, 0xC4, 0x46, +0x0A, 0xEB, 0x03, 0x09, 0x00, 0x26, 0x8A, 0xE7, 0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, +0x38, 0xE7, 0x48, 0x46, 0x62, 0x46, 0x5E, 0xE7, 0xA9, 0xEB, 0x0A, 0x03, 0x00, 0x2B, 0x11, 0xDB, 0xAC, 0xEB, 0x0A, 0x03, +0x00, 0x2B, 0x15, 0xDB, 0xA8, 0xEB, 0x09, 0x03, 0x00, 0x2B, 0x14, 0xDB, 0x1B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x29, 0xDB, 0xE3, 0x69, 0xC4, 0x46, 0x0A, 0xEB, 0x03, 0x09, 0x4F, 0xF0, 0x00, 0x0E, 0x67, 0xE7, 0xD1, 0x46, +0x00, 0x26, 0x64, 0xE7, 0xC4, 0x46, 0x62, 0xE7, 0xD1, 0x46, 0xB6, 0x46, 0x5F, 0xE7, 0x01, 0x28, 0x15, 0xDD, 0xE3, 0x69, +0x9A, 0x44, 0xAA, 0xEB, 0x09, 0x03, 0xC4, 0x46, 0x39, 0xEA, 0x23, 0x09, 0x28, 0xBF, 0xD1, 0x46, 0xB6, 0x46, 0x52, 0xE7, +0xAC, 0xEB, 0x02, 0x01, 0x12, 0xEA, 0x21, 0x02, 0x38, 0xBF, 0x62, 0x46, 0x8A, 0xE7, 0x40, 0x46, 0x9A, 0x46, 0x88, 0x46, +0xB0, 0xE7, 0xC4, 0x46, 0xB6, 0x46, 0x44, 0xE7, 0x04, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x4D, 0x12, 0x05, 0xF0, 0x64, 0xFA, +0xCE, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x03, 0x7C, 0x02, 0x2B, 0x83, 0xB0, 0x04, 0x46, 0x69, 0xD0, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x54, 0xD0, 0x94, 0xF8, +0x73, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x18, 0xD1, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x40, 0xF0, 0xD2, 0x80, 0x94, 0xF8, +0x70, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xB8, 0x80, 0xDF, 0xF8, 0x24, 0x93, 0xC3, 0x4B, 0x94, 0xF8, 0x71, 0x20, 0xD3, 0xF8, +0x5C, 0x34, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x90, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x94, 0xF8, +0x72, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0x54, 0x81, 0x94, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x00, 0xF0, 0xB9, 0x81, 0xB9, 0x4A, +0x92, 0xF8, 0x00, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xA8, 0x80, 0x52, 0x68, 0x11, 0x07, 0x00, 0xF1, 0xD4, 0x81, +0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, 0x00, 0xF0, 0x8F, 0x80, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0xD0, 0x92, 0x02, 0x23, +0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x15, 0xF9, 0x01, 0x25, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, +0x03, 0xF0, 0x3E, 0xF9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x00, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, +0x29, 0x46, 0xFF, 0xF7, 0x15, 0xF9, 0x55, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x7B, 0xD0, 0xFF, 0x23, 0x00, 0x21, +0x94, 0xF8, 0x51, 0x20, 0x00, 0x2A, 0x6F, 0xD0, 0x94, 0xF8, 0x50, 0x20, 0x01, 0x2A, 0x6B, 0xD1, 0x00, 0x29, 0x9A, 0xD0, +0x11, 0xE0, 0x90, 0xF8, 0x87, 0x30, 0x00, 0x2B, 0x5F, 0xD0, 0x90, 0xF8, 0x21, 0x30, 0x23, 0xB1, 0x90, 0xF8, 0x20, 0x30, +0x01, 0x2B, 0x00, 0xF0, 0xA6, 0x81, 0x94, 0xF8, 0x40, 0x20, 0x23, 0x7D, 0x02, 0x2A, 0x00, 0xF0, 0x9E, 0x81, 0x01, 0x2B, +0xB8, 0xD0, 0x94, 0xF8, 0x86, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x0D, 0x81, 0x94, 0xF8, 0x72, 0x50, 0x94, 0xF8, +0x85, 0x30, 0xA5, 0xF1, 0x01, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB3, 0x42, 0x00, 0xF0, 0x4C, 0x81, 0x02, 0x23, +0x0C, 0x21, 0x52, 0x46, 0x4D, 0x20, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x20, 0x92, 0x03, 0xF0, 0xC1, 0xF8, 0x6F, 0x1E, +0x18, 0xBF, 0x01, 0x27, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x47, 0x70, 0x03, 0xF0, 0xE8, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x08, 0x93, 0x84, 0xF8, 0x85, 0x60, 0x18, 0x6C, 0x39, 0x46, 0xFF, 0xF7, 0xC0, 0xF8, 0x01, 0x2D, 0x4C, 0xD0, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0x00, 0xF0, 0xF1, 0x80, 0x94, 0xF8, +0x70, 0x30, 0x7B, 0xB9, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x07, 0xD0, +0x6E, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x01, 0x22, 0x83, 0xF8, 0x24, 0x20, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x90, 0xF8, 0x40, 0x20, 0x03, 0x7D, 0x02, 0x2A, 0xA8, 0xD1, 0x94, 0xF8, 0x44, 0x20, 0x93, 0x42, 0x28, 0xBF, +0x13, 0x46, 0xA2, 0xE7, 0xFF, 0x23, 0xF7, 0xE7, 0x94, 0xF8, 0x85, 0x20, 0x01, 0x2A, 0x3F, 0xF4, 0x30, 0xAF, 0x94, 0xF8, +0x71, 0x80, 0xDF, 0xF8, 0x88, 0x91, 0x02, 0x23, 0x0C, 0x21, 0x00, 0x22, 0x4D, 0x20, 0x03, 0xF0, 0x71, 0xF8, 0x00, 0x25, +0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, 0x45, 0x70, 0x03, 0xF0, 0x9A, 0xF8, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, +0x01, 0x22, 0x84, 0xF8, 0x85, 0x20, 0x18, 0x6C, 0x29, 0x46, 0xFF, 0xF7, 0x71, 0xF8, 0x94, 0xF8, 0x70, 0xE0, 0xBE, 0xF1, +0x00, 0x0F, 0x40, 0xF0, 0xD4, 0x80, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x08, 0x97, 0x97, 0xF8, 0x6C, 0x10, 0xFF, 0x29, +0x00, 0xF0, 0xF0, 0x80, 0x4A, 0x4D, 0x01, 0x94, 0x4F, 0xF4, 0x1E, 0x7B, 0xA4, 0x23, 0x0B, 0xFB, 0x01, 0xF0, 0x03, 0xFB, +0x08, 0xF3, 0x05, 0xF5, 0x16, 0x7B, 0x2E, 0x18, 0x9E, 0x33, 0x58, 0x44, 0x00, 0x90, 0x09, 0xEB, 0xC3, 0x0B, 0x4F, 0xF0, +0x4F, 0x0C, 0x46, 0x20, 0x1C, 0xFB, 0x01, 0x01, 0x5C, 0x46, 0x40, 0x4A, 0xDD, 0xF8, 0x00, 0xB0, 0x86, 0xF8, 0x24, 0xE0, +0x05, 0xEB, 0xC1, 0x05, 0xD6, 0xF8, 0x08, 0x12, 0x39, 0xB3, 0xEF, 0xF3, 0x10, 0x81, 0xCB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x39, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x11, 0x68, 0xA5, 0xF1, 0x28, 0x00, 0x4B, 0x1C, 0xA4, 0xF1, 0x28, 0x01, 0x13, 0x60, +0x00, 0x90, 0x03, 0xF0, 0x9D, 0xFD, 0xD6, 0xF8, 0x08, 0x12, 0xD6, 0xF8, 0x0C, 0x32, 0x00, 0x98, 0xC7, 0xF8, 0xC8, 0x14, +0xC7, 0xF8, 0xCC, 0x34, 0x03, 0xF0, 0x9C, 0xFC, 0x2C, 0x4A, 0x11, 0x68, 0x48, 0x1E, 0x31, 0xB1, 0x2B, 0x4B, 0x10, 0x60, +0x19, 0x68, 0x10, 0xB9, 0x00, 0x29, 0x40, 0xF0, 0xB5, 0x80, 0xD6, 0xF8, 0x30, 0x32, 0x20, 0x46, 0x29, 0x46, 0x08, 0x36, +0x08, 0x34, 0x08, 0x37, 0x2B, 0xB1, 0x03, 0xF0, 0x7D, 0xFD, 0x28, 0x46, 0x03, 0xF0, 0x84, 0xFC, 0x20, 0x4A, 0x08, 0x35, +0x5D, 0x45, 0xC3, 0xD1, 0x01, 0x9C, 0x40, 0x20, 0x03, 0xF0, 0xDE, 0xFB, 0x94, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x08, 0x98, 0x98, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD0, 0x00, 0x2A, 0x7F, 0xF4, 0x55, 0xAF, 0xBA, 0xF1, +0x00, 0x0F, 0x7F, 0xF4, 0x51, 0xAF, 0x99, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x8E, 0xAE, 0x94, 0xF8, +0x71, 0x80, 0xDF, 0xF8, 0x48, 0x90, 0x4F, 0xF0, 0x00, 0x0A, 0x5C, 0xE7, 0xD8, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, +0xC8, 0xF8, 0x04, 0x30, 0x00, 0x2A, 0x7F, 0xF4, 0x3B, 0xAF, 0xE4, 0xE7, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, +0x35, 0xAF, 0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x1C, 0x90, 0x4F, 0xF0, 0x01, 0x0A, 0x46, 0xE7, 0x88, 0x1A, 0x17, 0x00, +0x1C, 0x9E, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x3C, 0x49, 0x5A, 0x68, 0x49, 0x68, 0x22, 0xF0, 0x20, 0x02, 0x00, 0x29, 0x5A, 0x60, 0x7F, 0xF7, 0x06, 0xAF, 0xEF, 0xF3, +0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x36, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x36, 0x4D, 0x2B, 0x68, 0x04, 0x20, +0x01, 0x33, 0x2B, 0x60, 0xEE, 0xF7, 0x1C, 0xFF, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEE, 0xF7, 0xB7, 0xFF, 0x2B, 0x68, +0x00, 0x2B, 0x3F, 0xF4, 0xEE, 0xAE, 0x2D, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x7F, 0xF4, 0xE7, 0xAE, +0x00, 0x2A, 0x3F, 0xF4, 0xE4, 0xAE, 0x62, 0xB6, 0xE1, 0xE6, 0x40, 0x20, 0x03, 0xF0, 0x6E, 0xFB, 0x94, 0xF8, 0x70, 0x20, +0x8E, 0xE7, 0x94, 0xF8, 0x70, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0xEA, 0xAE, 0x01, 0x2D, 0x7F, 0xF4, 0xE7, 0xAE, 0x2D, 0xE6, +0x94, 0xF8, 0x71, 0x80, 0xDF, 0xF8, 0x80, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x93, 0x93, 0xF8, 0xDE, 0x20, +0x93, 0xF8, 0xC2, 0x34, 0x9A, 0x42, 0x20, 0xD0, 0x94, 0xF8, 0x85, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0xD3, 0xAE, 0x4F, 0xF0, +0x00, 0x0A, 0xE8, 0xE6, 0x97, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0x76, 0xAF, 0x7B, 0x68, 0x43, 0xF0, 0x20, 0x03, +0x7B, 0x60, 0xBA, 0xF1, 0x00, 0x0F, 0x7F, 0xF4, 0xC3, 0xAE, 0x0B, 0xE6, 0x62, 0xB6, 0x48, 0xE7, 0x94, 0xF8, 0x85, 0x20, +0x01, 0x2A, 0x7F, 0xF4, 0x70, 0xAF, 0x00, 0x2B, 0x3F, 0xF4, 0x00, 0xAE, 0xB6, 0xE6, 0x94, 0xF8, 0x85, 0x30, 0x00, 0x2B, +0x7F, 0xF4, 0x27, 0xAE, 0xB0, 0xE6, 0x01, 0x21, 0x42, 0xE6, 0x90, 0xF8, 0x40, 0x30, 0x02, 0x2B, 0x7F, 0xF4, 0xE3, 0xAD, +0x3A, 0xE6, 0x00, 0xBF, 0xD8, 0x9C, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xF4, 0x92, 0x47, 0x7C, 0xB6, 0x49, 0x90, 0xF8, 0x10, 0xB0, 0x8C, 0x23, 0x03, 0xFB, +0x07, 0x93, 0x83, 0xB0, 0x93, 0xF8, 0x71, 0x20, 0x93, 0xF8, 0x70, 0x30, 0x00, 0x92, 0x07, 0xEB, 0x87, 0x06, 0x4F, 0xF4, +0xA4, 0x6A, 0xC6, 0xEB, 0xC6, 0x06, 0x01, 0x2B, 0x05, 0x46, 0x0A, 0xFB, 0x02, 0x1A, 0x09, 0xEB, 0x86, 0x06, 0x00, 0xF0, +0x0B, 0x81, 0xAA, 0x4B, 0xC4, 0x6A, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xD3, 0x80, 0xDA, 0xF8, +0x7C, 0x30, 0xE4, 0x1A, 0xA4, 0x4B, 0xA5, 0x49, 0xDF, 0xF8, 0x94, 0x82, 0xBB, 0xF1, 0x01, 0x0F, 0x17, 0xD0, 0xBB, 0xF1, +0x02, 0x0F, 0x00, 0xF0, 0x82, 0x80, 0x1A, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x7F, 0xDB, 0xD8, 0xF8, 0x10, 0x20, +0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0x80, 0xF2, 0xE9, 0x80, 0xBB, 0xF1, 0x00, 0x0F, 0xE7, 0xD1, +0xDF, 0xF8, 0x70, 0x82, 0x20, 0xE0, 0xA8, 0x69, 0xDF, 0xF8, 0x68, 0x82, 0x95, 0x4B, 0x1B, 0x69, 0x04, 0x44, 0xE3, 0x1A, +0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x80, 0xF2, 0xFA, 0x80, 0xEA, 0x7C, 0xFF, 0x2A, 0x1B, 0xD0, 0x01, 0x3A, +0xD2, 0xB2, 0xEA, 0x74, 0xBA, 0xB9, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x97, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x5D, 0xD0, +0xD8, 0xF8, 0xE8, 0x31, 0x28, 0x46, 0x98, 0x47, 0x87, 0x4B, 0x1B, 0x69, 0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, +0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0x18, 0x47, 0x4F, 0xF0, 0x8C, 0x0E, 0x0E, 0xFB, +0x07, 0x9E, 0xD5, 0xE9, 0x06, 0x0B, 0x9E, 0xF8, 0x70, 0x30, 0xAB, 0xEB, 0x00, 0x01, 0x01, 0x2B, 0x0C, 0x44, 0x47, 0xD0, +0x7A, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xA8, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, +0xBE, 0xDB, 0x53, 0xB9, 0x72, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xB0, 0x80, 0xDA, 0xF8, +0x7C, 0x30, 0x23, 0x44, 0xEB, 0x62, 0x21, 0x46, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, 0x98, 0x47, 0x85, 0xF8, 0x10, 0xB0, +0xD8, 0xF8, 0x1C, 0x32, 0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, +0x63, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA4, 0x80, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0x90, 0x81, 0x9B, 0xE7, 0x5F, 0x48, 0x4F, 0xF4, 0x31, 0x72, 0x04, 0xF0, +0x53, 0xFF, 0x5A, 0x4B, 0x5A, 0x49, 0x77, 0xE7, 0xD8, 0xF8, 0x08, 0x32, 0xA9, 0x7C, 0x50, 0x46, 0x98, 0x47, 0x58, 0x4B, +0x1B, 0x69, 0x9F, 0xE7, 0x9E, 0xF8, 0x84, 0x10, 0x00, 0x29, 0x36, 0xD0, 0xA9, 0x6A, 0x01, 0x91, 0x69, 0x6A, 0x01, 0xEB, +0x0B, 0x0C, 0x01, 0x99, 0x01, 0x39, 0xC5, 0xE9, 0x09, 0xC1, 0x00, 0x29, 0x5E, 0xD1, 0x2A, 0x75, 0xBB, 0xF1, 0x00, 0x0F, +0x05, 0xD0, 0x4F, 0xF0, 0x00, 0x43, 0xB3, 0xFB, 0xFB, 0xF3, 0x01, 0x3B, 0xAB, 0x62, 0x00, 0x9B, 0x19, 0x46, 0x46, 0x4B, +0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x32, 0xD8, 0xF8, 0x90, 0x31, 0x92, 0xF8, 0x63, 0x00, 0x03, 0x21, 0x98, 0x47, +0x43, 0x4B, 0x1B, 0x69, 0xE3, 0x1A, 0xA3, 0xF5, 0x9C, 0x53, 0x08, 0x3B, 0x00, 0x2B, 0x71, 0xDA, 0xA8, 0x69, 0x51, 0xE7, +0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x28, 0xAF, 0x3B, 0x49, 0x3D, 0x48, 0x58, 0x22, 0x04, 0xF0, 0x0E, 0xFF, +0x21, 0xE7, 0x39, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, 0x3E, 0xAF, +0xD8, 0xF8, 0xE0, 0x21, 0x01, 0x93, 0x21, 0x46, 0x28, 0x46, 0x90, 0x47, 0x01, 0x9B, 0x2B, 0x74, 0xD8, 0xF8, 0x1C, 0x32, +0x30, 0x46, 0x98, 0x47, 0xD8, 0xF8, 0x18, 0x32, 0x30, 0x46, 0x98, 0x47, 0x00, 0x9A, 0x11, 0x46, 0x28, 0x4A, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x8A, 0xD1, 0x31, 0xE0, 0xC4, 0x68, 0xFD, 0xE6, +0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x16, 0xAF, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0xDF, 0xF8, 0x98, 0x80, 0x97, 0xF8, +0x70, 0x30, 0x54, 0xE7, 0x1F, 0x4A, 0x12, 0x69, 0xA2, 0x1A, 0xA2, 0xF5, 0x9C, 0x52, 0x08, 0x3A, 0x00, 0x2A, 0xFF, 0xF6, +0x0B, 0xAF, 0x9B, 0x46, 0x9E, 0xF8, 0x70, 0x30, 0x47, 0xE7, 0x9A, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x4B, 0xAF, +0x15, 0x49, 0x18, 0x48, 0x49, 0x22, 0x04, 0xF0, 0xC3, 0xFE, 0x44, 0xE7, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, +0x02, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x34, 0xE7, 0xBB, 0xF1, 0x01, 0x0F, 0x7F, 0xF4, 0x58, 0xAF, 0x00, 0x9A, 0x11, 0x46, +0x09, 0x4A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x01, 0x23, 0x5A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x5A, 0x60, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x8C, 0x23, 0x03, 0xFB, 0x07, 0x97, 0x4F, 0xF0, 0x01, 0x0B, 0x97, 0xF8, 0x70, 0x30, 0x1A, 0xE7, +0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x64, 0x7D, 0x15, 0x00, +0x40, 0x9C, 0x15, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x00, 0x22, 0x04, 0x46, 0x0D, 0x46, +0x10, 0x23, 0x0C, 0x21, 0x55, 0x20, 0x02, 0xF0, 0xA5, 0xFD, 0x05, 0xEB, 0x45, 0x03, 0x94, 0xF8, 0x71, 0x20, 0x02, 0x70, +0x04, 0xEB, 0x03, 0x13, 0x45, 0x70, 0x1A, 0x7C, 0x22, 0xB9, 0xC2, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xC6, 0xBD, +0x1A, 0x7D, 0xC2, 0x70, 0x00, 0x2A, 0xF7, 0xD0, 0x93, 0xF8, 0x20, 0x20, 0x82, 0x70, 0xD3, 0xE9, 0x06, 0x12, 0x5B, 0x6A, +0xC3, 0x60, 0xC0, 0xE9, 0x01, 0x12, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0xF0, 0xB5, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, +0x16, 0x46, 0x2D, 0x4D, 0x4F, 0xF4, 0xA4, 0x62, 0xB3, 0x42, 0x04, 0x46, 0x02, 0xFB, 0x01, 0x58, 0x0B, 0xD3, 0xC2, 0x7C, +0x01, 0x2A, 0x30, 0xD0, 0xC5, 0x69, 0x9B, 0x1B, 0xB3, 0xFB, 0xF5, 0xF3, 0x03, 0xFB, 0x05, 0x55, 0x2E, 0x44, 0x5F, 0x1C, +0x00, 0xE0, 0x00, 0x27, 0x23, 0x4B, 0xE6, 0x62, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0xE3, 0x7C, +0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0x31, 0xD0, 0xBB, 0x42, 0x94, 0xBF, 0xDB, 0x1A, 0xDB, 0x1B, +0x1B, 0x4A, 0xDB, 0xB2, 0xE3, 0x74, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0x0C, 0xDA, 0x18, 0x49, 0x5B, 0xB1, 0xE5, 0x69, +0xFF, 0x2B, 0x28, 0x44, 0x0A, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0xE3, 0x74, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xF3, 0xDB, +0x03, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x0A, 0x69, 0x82, 0x1A, 0x00, 0x2A, 0xED, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, +0x98, 0xF8, 0x62, 0x30, 0x00, 0x2B, 0xD2, 0xD0, 0x0B, 0x48, 0x0C, 0x49, 0x58, 0x22, 0x04, 0xF0, 0x15, 0xFE, 0xE3, 0x7C, +0xD8, 0xF8, 0x7C, 0x00, 0xFF, 0x2B, 0xA6, 0xEB, 0x00, 0x00, 0xCD, 0xD1, 0x04, 0x4A, 0x12, 0x69, 0x82, 0x1A, 0x00, 0x2A, +0xD3, 0xDB, 0xE1, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x40, 0x9C, 0x15, 0x00, +0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x08, 0x4E, 0xD6, 0xF8, 0xEC, 0x41, 0x05, 0x46, 0xA0, 0x47, 0x04, 0x46, 0x30, 0xB1, +0xD6, 0xF8, 0xE0, 0x31, 0x01, 0x46, 0x28, 0x46, 0x98, 0x47, 0x01, 0x23, 0x2B, 0x74, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0xBF, +0x88, 0x1A, 0x17, 0x00, 0x03, 0x7C, 0x43, 0xB1, 0x10, 0xB5, 0x04, 0x4B, 0x04, 0x46, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, +0x00, 0x23, 0x23, 0x74, 0x10, 0xBD, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x5C, 0x4F, 0x00, 0xEB, +0x80, 0x04, 0xC4, 0xEB, 0xC4, 0x04, 0x4F, 0xEA, 0x84, 0x0A, 0x83, 0xB0, 0x05, 0x46, 0x07, 0xEB, 0x84, 0x04, 0x0E, 0x46, +0x00, 0x29, 0x74, 0xD0, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x73, 0x91, 0x46, 0xCA, 0x78, 0x93, 0xF8, 0x84, 0x10, 0x00, 0x29, +0x40, 0xF0, 0x8A, 0x80, 0x4F, 0xF0, 0x8C, 0x08, 0x08, 0xFB, 0x05, 0x78, 0x01, 0x21, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, +0x78, 0x20, 0x88, 0xF8, 0x84, 0x10, 0xAB, 0xB1, 0xDF, 0xF8, 0x30, 0xB1, 0x20, 0x46, 0xDB, 0xF8, 0xE8, 0x31, 0x98, 0x47, +0x00, 0x22, 0x0A, 0xF1, 0x30, 0x00, 0xDB, 0xF8, 0xE8, 0x31, 0x88, 0xF8, 0x79, 0x20, 0x38, 0x44, 0x98, 0x47, 0x00, 0x22, +0xDB, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x20, 0x20, 0x46, 0x98, 0x47, 0xB6, 0xF8, 0x01, 0x20, 0x3F, 0x49, 0x02, 0x3A, +0x81, 0xFB, 0x02, 0x31, 0xD3, 0x17, 0xC3, 0xEB, 0xA1, 0x03, 0x13, 0xF0, 0xFF, 0x0B, 0x2E, 0xD0, 0x8C, 0x23, 0x03, 0xFB, +0x05, 0x73, 0x00, 0x93, 0x06, 0xF1, 0x05, 0x08, 0x4F, 0xF0, 0x00, 0x0A, 0x01, 0x95, 0x98, 0xF8, 0x00, 0x20, 0x36, 0x49, +0x22, 0x75, 0x0A, 0xF1, 0x01, 0x0A, 0x20, 0x46, 0x4B, 0x46, 0x9A, 0xB1, 0x01, 0x2A, 0xD8, 0xF8, 0x05, 0x50, 0x00, 0xD9, +0x75, 0xB1, 0xD8, 0xF8, 0x01, 0xC0, 0xE2, 0x74, 0xC4, 0xE9, 0x06, 0xC5, 0x00, 0x9A, 0xD1, 0xF8, 0xF4, 0x51, 0x92, 0xF8, +0x71, 0x10, 0xD8, 0xF8, 0x09, 0x20, 0xA8, 0x47, 0x00, 0x28, 0x45, 0xD1, 0x5F, 0xFA, 0x8A, 0xF3, 0x5B, 0x45, 0x08, 0xF1, +0x0D, 0x08, 0x04, 0xF1, 0x30, 0x04, 0xDA, 0xD3, 0x01, 0x9D, 0x96, 0xF9, 0x04, 0x20, 0x33, 0x79, 0x00, 0x2A, 0x2D, 0xDB, +0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x00, 0x23, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xF0, +0x8C, 0x08, 0x08, 0xFB, 0x00, 0x78, 0x98, 0xF8, 0x79, 0x30, 0x88, 0xF8, 0x84, 0x10, 0x00, 0x2B, 0xEC, 0xD0, 0xDF, 0xF8, +0x60, 0x90, 0x20, 0x46, 0xD9, 0xF8, 0xE8, 0x31, 0x98, 0x47, 0x0A, 0xF1, 0x30, 0x00, 0xD9, 0xF8, 0xE8, 0x31, 0x88, 0xF8, +0x79, 0x60, 0x38, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x18, 0x32, 0x88, 0xF8, 0x79, 0x60, 0x20, 0x46, 0x98, 0x47, 0xD7, 0xE7, +0x93, 0xF8, 0x78, 0x30, 0x93, 0x42, 0x7F, 0xF4, 0x71, 0xAF, 0xD7, 0xE7, 0x8C, 0x20, 0x00, 0xFB, 0x05, 0x75, 0x03, 0xF0, +0x7F, 0x03, 0x85, 0xF8, 0x73, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x9A, 0x92, 0xF8, 0x79, 0x30, 0x01, 0x33, +0x82, 0xF8, 0x79, 0x30, 0xB2, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x4F, 0xEC, 0xC4, 0x4E, 0x88, 0x1A, 0x17, 0x00, +0x08, 0xB5, 0x01, 0x22, 0x05, 0x48, 0x00, 0x21, 0xE0, 0xF7, 0x2C, 0xF8, 0x04, 0x4B, 0xFF, 0x22, 0x83, 0xF8, 0x71, 0x20, +0x83, 0xF8, 0xFD, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, +0x25, 0x4C, 0x94, 0xF8, 0x71, 0x30, 0xFF, 0x2B, 0x07, 0x46, 0x0E, 0x46, 0x08, 0xD0, 0x94, 0xF8, 0xFD, 0x30, 0xFF, 0x2B, +0x18, 0xBF, 0xFF, 0x25, 0x36, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x25, 0xA8, 0x46, 0x4F, 0xF0, 0x30, 0x0A, +0xA1, 0x46, 0x8C, 0x22, 0x00, 0x21, 0x48, 0x46, 0xE0, 0xF7, 0x04, 0xF8, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x43, 0x01, 0x2E, +0x83, 0xF8, 0x71, 0x70, 0x83, 0xF8, 0x70, 0x60, 0x03, 0xD1, 0x15, 0x4A, 0x13, 0x78, 0x01, 0x33, 0x13, 0x70, 0x8C, 0x23, +0x03, 0xFB, 0x08, 0x43, 0x12, 0x4A, 0xC3, 0xF8, 0x08, 0x90, 0x54, 0x44, 0x00, 0x21, 0x01, 0x26, 0x9C, 0x63, 0x99, 0x74, +0x0F, 0x4C, 0xD2, 0xF8, 0x10, 0x12, 0x5D, 0x74, 0x83, 0xF8, 0x41, 0x50, 0xC3, 0xF8, 0x68, 0x90, 0x83, 0xF8, 0x42, 0x60, +0x5C, 0x66, 0x59, 0x60, 0x59, 0x63, 0x48, 0x46, 0xD2, 0xF8, 0x18, 0x32, 0x98, 0x47, 0xC8, 0xE7, 0x01, 0x25, 0xA8, 0x46, +0x4F, 0xF0, 0xBC, 0x0A, 0x04, 0xF1, 0x8C, 0x09, 0xC9, 0xE7, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x41, 0xF4, 0x13, 0x00, 0x0E, 0x4A, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x23, 0x10, 0xB4, 0x93, 0xF8, +0x71, 0x40, 0xFF, 0x2C, 0x0A, 0xD0, 0x93, 0xF8, 0x70, 0x30, 0x01, 0x2B, 0x09, 0xD0, 0x29, 0xB1, 0x8C, 0x23, 0x03, 0xFB, +0x00, 0x20, 0xFF, 0x23, 0x80, 0xF8, 0x71, 0x30, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x04, 0x4C, 0x23, 0x78, 0x01, 0x3B, +0x23, 0x70, 0x00, 0x29, 0xF6, 0xD0, 0xEF, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x44, 0x9E, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, +0xBB, 0xB3, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x40, 0x0C, 0x43, 0x2F, 0xD1, 0x90, 0xF8, 0xC1, 0x54, 0xDF, 0xF8, +0x64, 0x80, 0x17, 0x4F, 0x05, 0xEB, 0x85, 0x00, 0xC0, 0xEB, 0xC0, 0x00, 0x08, 0xEB, 0x80, 0x09, 0xD7, 0xF8, 0xE8, 0x31, +0x86, 0x00, 0x48, 0x46, 0x98, 0x47, 0x06, 0xF1, 0x30, 0x00, 0xD7, 0xF8, 0xE8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x8C, 0x23, +0x03, 0xFB, 0x05, 0x85, 0x95, 0xF8, 0x72, 0x30, 0x85, 0xF8, 0x73, 0x40, 0x85, 0xF8, 0x78, 0x40, 0x85, 0xF8, 0x84, 0x40, +0x3B, 0xB1, 0x06, 0xF1, 0x60, 0x00, 0xD7, 0xF8, 0xD8, 0x31, 0x40, 0x44, 0x98, 0x47, 0x85, 0xF8, 0x72, 0x40, 0xD7, 0xF8, +0x18, 0x32, 0x48, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, +0x48, 0x9E, 0x17, 0x00, 0x03, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x85, 0x00, 0x70, 0x47, 0x00, 0xBF, +0x48, 0x9E, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x70, 0xB5, 0x05, 0x46, 0x0C, 0x46, +0x16, 0x46, 0x0E, 0xDB, 0x95, 0xF8, 0xC1, 0x34, 0x0C, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0xD3, 0xF8, 0x80, 0x20, +0x22, 0x60, 0xD8, 0x6F, 0x30, 0x60, 0x23, 0x68, 0xC0, 0x1A, 0xC0, 0x0F, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, +0xEC, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x06, 0x52, 0x04, 0xF0, 0x23, 0xFC, 0xE5, 0xE7, 0x38, 0x36, 0x17, 0x00, +0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA4, 0xA3, 0x15, 0x00, 0x70, 0xB5, 0x35, 0x4E, 0x33, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x12, 0xDB, 0x90, 0xF8, 0xC1, 0x24, 0x31, 0x48, 0x8C, 0x23, 0x01, 0xEB, +0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x28, 0xD0, +0x02, 0x2B, 0x1D, 0xD0, 0x00, 0x20, 0x70, 0xBD, 0x90, 0xF8, 0xC0, 0x34, 0x0B, 0xB1, 0x01, 0x29, 0x30, 0xD9, 0x27, 0x49, +0x27, 0x48, 0x40, 0xF2, 0x14, 0x52, 0x04, 0xF0, 0xF3, 0xFB, 0x95, 0xF8, 0xC1, 0x24, 0x22, 0x48, 0x8C, 0x23, 0x04, 0xEB, +0x44, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, 0x1B, 0x7C, 0x01, 0x2B, 0x0A, 0xD0, +0x02, 0x2B, 0x13, 0xD1, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x11, 0x01, 0x44, 0xC8, 0x68, +0x70, 0xBD, 0x8C, 0x23, 0x0C, 0x44, 0x03, 0xFB, 0x02, 0xF1, 0x01, 0xEB, 0x04, 0x14, 0x01, 0x19, 0xC8, 0x68, 0x8B, 0x69, +0x18, 0x44, 0x70, 0xBD, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC8, 0xDA, 0x10, 0xE0, 0x90, 0xF8, 0xC1, 0x24, +0x0C, 0x48, 0x8C, 0x23, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xFB, 0x02, 0xF3, 0x03, 0xEB, 0x01, 0x13, 0x03, 0x44, 0x61, 0x00, +0x1B, 0x7C, 0x01, 0x2B, 0xDF, 0xD0, 0x02, 0x2B, 0xD4, 0xD0, 0x06, 0x49, 0x07, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x04, 0xF0, +0xC9, 0xFB, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xB0, 0xA3, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x43, 0xD0, 0x2D, 0xE9, 0xF0, 0x41, +0x28, 0x4F, 0x90, 0xF8, 0xC1, 0x24, 0x44, 0x68, 0x8C, 0x26, 0x06, 0xFB, 0x02, 0x76, 0x02, 0xEB, 0x82, 0x03, 0x96, 0xF8, +0x73, 0xC0, 0x01, 0x25, 0xC3, 0xEB, 0xC3, 0x03, 0x24, 0xF0, 0x40, 0x04, 0x86, 0xF8, 0x86, 0x50, 0x4F, 0xEA, 0x83, 0x0E, +0x07, 0xEB, 0x83, 0x05, 0x44, 0x60, 0xBC, 0xF1, 0x00, 0x0F, 0x06, 0xD1, 0x1C, 0x4E, 0x28, 0x46, 0xD6, 0xF8, 0x18, 0x32, +0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x96, 0xF8, 0x70, 0x30, 0x01, 0xEB, 0x8C, 0x24, 0x3B, 0xB9, 0x17, 0x4B, 0x18, 0x69, +0x01, 0xF5, 0x96, 0x73, 0xC1, 0x1A, 0x11, 0xF1, 0x32, 0x0F, 0x14, 0xD4, 0x8C, 0x23, 0x03, 0xFB, 0x02, 0x72, 0x11, 0x4E, +0x0E, 0xF1, 0x60, 0x00, 0x01, 0x23, 0x38, 0x44, 0x21, 0x46, 0x82, 0xF8, 0x72, 0x30, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, +0xD6, 0xF8, 0x18, 0x32, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x70, 0x47, 0x08, 0x4D, 0x74, 0x67, 0x0E, 0xF1, +0x60, 0x00, 0x02, 0x22, 0x38, 0x44, 0x19, 0x46, 0x86, 0xF8, 0x72, 0x20, 0xD5, 0xF8, 0xE0, 0x31, 0xBD, 0xE8, 0xF0, 0x41, +0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0x0A, 0x49, +0x90, 0xF8, 0xC1, 0x34, 0x09, 0x4C, 0x8C, 0x20, 0x03, 0xEB, 0x83, 0x02, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x25, 0xC2, 0xEB, +0xC2, 0x02, 0x83, 0xF8, 0x86, 0x50, 0x01, 0xEB, 0x82, 0x00, 0xD4, 0xF8, 0x18, 0x32, 0x30, 0xBC, 0x18, 0x47, 0x00, 0xBF, +0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x90, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0x3E, 0xD0, +0x90, 0xF8, 0x62, 0x30, 0x05, 0x46, 0x00, 0x2B, 0x3C, 0xD1, 0x27, 0x4B, 0x90, 0xF8, 0xC1, 0x74, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x88, 0x46, 0x16, 0x46, 0x36, 0xDB, 0xD8, 0xF8, 0x08, 0x00, 0xB2, 0x8B, 0x00, 0xF1, 0x24, 0x03, +0x10, 0x44, 0x83, 0x42, 0x02, 0xD3, 0x38, 0xE0, 0x98, 0x42, 0x36, 0xD9, 0x5D, 0x78, 0x1A, 0x78, 0xA9, 0x1C, 0xDD, 0x2A, +0x1C, 0x46, 0x0B, 0x44, 0xF6, 0xD1, 0x62, 0x79, 0x09, 0x2A, 0xF3, 0xD1, 0x06, 0x34, 0x04, 0x3D, 0x14, 0xFA, 0x85, 0xF5, +0xAC, 0x42, 0x06, 0xD3, 0xEC, 0xE7, 0xB4, 0xF8, 0x01, 0x10, 0x03, 0x31, 0x0C, 0x44, 0xA5, 0x42, 0xE6, 0xD9, 0x22, 0x78, +0x0C, 0x2A, 0xF6, 0xD1, 0x00, 0x2C, 0xE1, 0xD0, 0xB2, 0x68, 0x0F, 0x4B, 0x92, 0x68, 0xD3, 0xF8, 0xF0, 0x31, 0x92, 0x69, +0x38, 0x46, 0x21, 0x46, 0x98, 0x47, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, +0x01, 0x2F, 0xC6, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x73, 0x52, 0x04, 0xF0, 0xD8, 0xFA, 0x95, 0xF8, 0xC1, 0x74, +0xBD, 0xE7, 0x00, 0x24, 0xE2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xD8, 0xA3, 0x15, 0x00, 0xF0, 0xB5, 0x0C, 0x7E, 0x7F, 0x2C, 0x83, 0xB0, 0x23, 0xD1, 0x4A, 0x7F, 0x0A, 0xBB, 0xCA, 0x7F, +0xDD, 0x2A, 0x1E, 0xD1, 0x91, 0xF8, 0x24, 0x20, 0x09, 0x2A, 0x1A, 0xD1, 0x91, 0xF8, 0x25, 0x20, 0x0C, 0x2A, 0x01, 0xF1, +0x25, 0x04, 0x14, 0xD1, 0x11, 0x4A, 0x12, 0x49, 0x12, 0x68, 0xD1, 0xF8, 0xF0, 0x61, 0xB2, 0xF9, 0x00, 0x20, 0x90, 0xF8, +0xC1, 0x74, 0x00, 0x2A, 0x05, 0x46, 0x0A, 0xDB, 0xEA, 0x6F, 0x21, 0x46, 0x1A, 0x44, 0x38, 0x46, 0x33, 0x46, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x40, 0x18, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x90, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0xF0, 0xD0, 0x06, 0x49, +0x06, 0x48, 0x01, 0x93, 0x49, 0x22, 0x04, 0xF0, 0x95, 0xFA, 0x01, 0x9B, 0xE8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0x9C, 0x15, 0x00, 0x12, 0x4B, 0x18, 0x78, 0xF8, 0xB1, 0x12, 0x4B, +0x58, 0x7C, 0xD8, 0xB9, 0x9A, 0x7C, 0x01, 0x2A, 0x19, 0xD8, 0x9B, 0x68, 0x13, 0xB9, 0x16, 0xE0, 0x1B, 0x68, 0xAB, 0xB1, +0x93, 0xF8, 0x62, 0x20, 0x02, 0x2A, 0xF9, 0xD1, 0x93, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xF5, 0xD0, 0x93, 0xF8, 0xC1, 0x34, +0x08, 0x4A, 0x8C, 0x21, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x85, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, +0x00, 0x20, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x44, 0x9E, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, +0x18, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC0, 0x34, 0x1B, 0xB1, 0x90, 0xF8, 0x62, 0x30, +0x02, 0x2B, 0x00, 0xD0, 0x70, 0x47, 0x70, 0xB5, 0x90, 0xF8, 0xC1, 0x34, 0x11, 0x4C, 0x8C, 0x22, 0x02, 0xFB, 0x03, 0x42, +0x00, 0x39, 0x03, 0xEB, 0x83, 0x03, 0x92, 0xF8, 0x84, 0x50, 0x18, 0xBF, 0x01, 0x21, 0xC3, 0xEB, 0xC3, 0x03, 0x82, 0xF8, +0x87, 0x10, 0x04, 0xEB, 0x83, 0x04, 0x35, 0xB9, 0x09, 0x4D, 0xD5, 0xF8, 0x18, 0x32, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, +0x18, 0x47, 0x06, 0x4D, 0x92, 0xF8, 0x71, 0x00, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xF1, 0xE7, 0x00, 0xBF, +0x18, 0x88, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0E, 0x4E, 0x90, 0xF8, 0xC1, 0x44, +0x0D, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0x01, 0x22, 0x04, 0xEB, 0x84, 0x04, 0x93, 0xF8, 0x71, 0x00, 0x83, 0xF8, +0x73, 0x10, 0x83, 0xF8, 0x72, 0x20, 0xC4, 0xEB, 0xC4, 0x04, 0xD5, 0xF8, 0x90, 0x31, 0x03, 0x21, 0x98, 0x47, 0xD5, 0xF8, +0x18, 0x32, 0x06, 0xEB, 0x84, 0x00, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x1D, 0x4F, 0x90, 0xF8, 0xC1, 0x44, 0x8C, 0x26, 0x06, 0xFB, 0x04, 0x76, 0x04, 0xEB, 0x84, 0x00, +0x96, 0xF8, 0x72, 0x20, 0xC0, 0xEB, 0xC0, 0x00, 0x4F, 0xF0, 0x00, 0x09, 0x07, 0xEB, 0x80, 0x05, 0x86, 0xF8, 0x73, 0x90, +0x9A, 0xB9, 0xDF, 0xF8, 0x54, 0x80, 0xD8, 0xF8, 0x18, 0x32, 0x28, 0x46, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x04, 0x74, +0x94, 0xF8, 0x79, 0x30, 0x9B, 0xB9, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x02, 0x21, 0xBD, 0xE8, 0xF0, 0x47, +0x18, 0x47, 0x83, 0x00, 0xDF, 0xF8, 0x28, 0x80, 0x03, 0xF1, 0x60, 0x00, 0x38, 0x44, 0xD8, 0xF8, 0xD8, 0x31, 0x98, 0x47, +0x86, 0xF8, 0x72, 0x90, 0xE1, 0xE7, 0xD8, 0xF8, 0x90, 0x31, 0x94, 0xF8, 0x71, 0x00, 0x03, 0x21, 0xBD, 0xE8, 0xF0, 0x47, +0x18, 0x47, 0x00, 0xBF, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x90, 0xF8, 0xC0, 0x34, 0x63, 0xB1, 0x90, 0xF8, +0xC1, 0x34, 0x06, 0x4A, 0x06, 0x48, 0x03, 0xEB, 0x83, 0x03, 0xC3, 0xEB, 0xC3, 0x03, 0x00, 0xEB, 0x83, 0x00, 0xD2, 0xF8, +0x18, 0x32, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x48, 0x9E, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, +0x42, 0x4E, 0x90, 0xF8, 0xC1, 0x84, 0xDD, 0xF8, 0x30, 0xC0, 0x8C, 0x24, 0x04, 0xFB, 0x08, 0x64, 0x94, 0xF8, 0x70, 0x70, +0x01, 0x2F, 0x0F, 0xD1, 0x08, 0xEB, 0x88, 0x05, 0x94, 0xF8, 0x10, 0x90, 0xC5, 0xEB, 0xC5, 0x05, 0xA8, 0x00, 0x06, 0xEB, +0x85, 0x05, 0xB9, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0x94, 0xF8, 0x40, 0x40, 0x00, 0x2C, 0x64, 0xD0, 0x4F, 0xF0, 0xFF, 0x09, +0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x28, 0x46, 0xCA, 0x46, 0x8C, 0x24, 0x4F, 0xEA, 0x4A, 0x07, 0x04, 0xFB, 0x08, 0xF4, +0x07, 0xEB, 0x0A, 0x0B, 0x06, 0xEB, 0x04, 0x0E, 0x04, 0xEB, 0x0B, 0x14, 0x00, 0x29, 0x06, 0xEB, 0x04, 0x01, 0x9E, 0xF8, +0x79, 0xB0, 0xCB, 0x74, 0x0B, 0x75, 0x0A, 0x9B, 0xCB, 0x61, 0x0B, 0xF1, 0x01, 0x0B, 0x0B, 0x9B, 0x8B, 0x61, 0x0C, 0xBF, +0x01, 0x24, 0x00, 0x24, 0xC1, 0xF8, 0x24, 0xC0, 0x81, 0xF8, 0x21, 0x20, 0x81, 0xF8, 0x20, 0x40, 0x8E, 0xF8, 0x79, 0xB0, +0x04, 0xD0, 0x9E, 0xF8, 0x7A, 0x30, 0x01, 0x33, 0x8E, 0xF8, 0x7A, 0x30, 0x0A, 0x9B, 0x73, 0xB1, 0x8C, 0x23, 0x07, 0xEB, +0x0A, 0x02, 0x03, 0xFB, 0x08, 0xF3, 0x03, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x0A, 0x99, 0x4F, 0xF0, 0x00, 0x42, 0xB2, 0xFB, +0xF1, 0xF2, 0x01, 0x3A, 0x9A, 0x62, 0x15, 0x4C, 0x61, 0x46, 0xD4, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, +0x08, 0xF8, 0x57, 0x44, 0x08, 0xEB, 0x07, 0x17, 0x37, 0x44, 0x46, 0x44, 0x01, 0x23, 0x96, 0xF8, 0x71, 0x00, 0x3B, 0x74, +0x03, 0x21, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x47, 0x49, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xA4, 0xFA, 0xD4, 0xF8, 0x1C, 0x32, +0x28, 0x46, 0x98, 0x47, 0x28, 0x46, 0xD4, 0xF8, 0x18, 0x32, 0x98, 0x47, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x30, 0x30, +0xB9, 0x46, 0x30, 0x44, 0xBA, 0x46, 0x9C, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, +0x90, 0xF8, 0xC1, 0x64, 0x37, 0x4D, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xF3, 0xE8, 0x18, 0x90, 0xF8, 0x70, 0x00, 0x01, 0x28, +0x5C, 0xD1, 0x01, 0x29, 0x0C, 0x46, 0x57, 0xD8, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x01, 0x13, 0x2B, 0x44, 0x4F, 0xEA, +0x44, 0x08, 0x19, 0x7C, 0x00, 0x29, 0x4D, 0xD0, 0x1A, 0xB1, 0x93, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x48, 0xD0, 0x06, 0xEB, +0x86, 0x07, 0x04, 0xEB, 0x44, 0x00, 0xDF, 0xF8, 0xA4, 0x90, 0xC7, 0xEB, 0xC7, 0x07, 0x00, 0x01, 0x00, 0xEB, 0x87, 0x00, +0xD9, 0xF8, 0xD8, 0x31, 0x28, 0x44, 0x98, 0x47, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0xFA, 0xA0, 0x44, 0x0A, 0xEB, 0x08, 0x18, +0xA8, 0x44, 0x00, 0x23, 0x05, 0xEB, 0x87, 0x07, 0x88, 0xF8, 0x10, 0x30, 0xD9, 0xF8, 0x1C, 0x22, 0x38, 0x46, 0x90, 0x47, +0xD9, 0xF8, 0x18, 0x22, 0x38, 0x46, 0x90, 0x47, 0x05, 0xEB, 0x0A, 0x03, 0x98, 0xF8, 0x20, 0x10, 0x93, 0xF8, 0x79, 0x20, +0x01, 0x3A, 0xD2, 0xB2, 0x01, 0x29, 0x83, 0xF8, 0x79, 0x20, 0x04, 0xD1, 0x93, 0xF8, 0x7A, 0x10, 0x01, 0x39, 0x83, 0xF8, +0x7A, 0x10, 0x8C, 0x23, 0x03, 0xFB, 0x06, 0x53, 0x93, 0xF8, 0x73, 0x10, 0x01, 0xB9, 0x92, 0xB1, 0x8C, 0x23, 0x03, 0xFB, +0x06, 0x55, 0x03, 0x21, 0xD9, 0xF8, 0x90, 0x31, 0x95, 0xF8, 0x71, 0x00, 0x98, 0x47, 0x38, 0x46, 0x21, 0x46, 0xFF, 0xF7, +0x29, 0xFA, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD9, 0xF8, 0x90, 0x21, 0x93, 0xF8, +0x71, 0x00, 0x02, 0x21, 0x90, 0x47, 0xEE, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, +0x1F, 0x4F, 0x90, 0xF8, 0xC1, 0x84, 0x8C, 0x25, 0x05, 0xFB, 0x08, 0x75, 0x08, 0xEB, 0x88, 0x03, 0x95, 0xF8, 0x20, 0x20, +0xC3, 0xEB, 0xC3, 0x03, 0x0E, 0x46, 0x9C, 0x00, 0xAA, 0xB9, 0x2B, 0x7C, 0x9B, 0xB1, 0xE9, 0x68, 0xDF, 0xF8, 0x5C, 0x90, +0x31, 0x44, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x19, 0x98, 0x47, 0x95, 0xF8, 0x50, 0x30, 0x13, 0xB9, 0x95, 0xF8, 0x40, 0x30, +0x6B, 0xB9, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x95, 0xF8, 0x50, 0x30, 0xAB, 0xB9, +0x95, 0xF8, 0x40, 0x30, 0x93, 0xB1, 0xDF, 0xF8, 0x2C, 0x90, 0x8C, 0x23, 0x03, 0xFB, 0x08, 0x73, 0x04, 0xF1, 0x30, 0x00, +0xD9, 0x6B, 0xD9, 0xF8, 0xE0, 0x31, 0x38, 0x44, 0x31, 0x44, 0x98, 0x47, 0xD9, 0xF8, 0x1C, 0x32, 0x38, 0x19, 0xBD, 0xE8, +0xF0, 0x47, 0x18, 0x47, 0xBD, 0xE8, 0xF0, 0x87, 0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x0A, 0x4B, 0x8C, 0x22, +0x02, 0xFB, 0x00, 0x33, 0x93, 0xF8, 0x71, 0x20, 0xFF, 0x2A, 0x0B, 0xD0, 0x93, 0xF8, 0x84, 0x00, 0x48, 0xB1, 0x93, 0xF8, +0x88, 0x00, 0x00, 0xEB, 0x40, 0x03, 0x00, 0xEB, 0x83, 0x00, 0x0B, 0x30, 0xC0, 0xB2, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, +0x48, 0x9E, 0x17, 0x00, 0x30, 0xB4, 0xDD, 0x23, 0x50, 0x25, 0x6F, 0x24, 0x9A, 0x21, 0x09, 0x22, 0x03, 0x70, 0x0C, 0x23, +0x85, 0x70, 0xC4, 0x70, 0x01, 0x71, 0x42, 0x71, 0x83, 0x71, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x43, +0x2D, 0x4E, 0x8C, 0x23, 0x03, 0xFB, 0x00, 0x63, 0x93, 0xF8, 0x78, 0x20, 0x4A, 0x72, 0x93, 0xF8, 0x73, 0x40, 0x01, 0x32, +0x83, 0xF8, 0x78, 0x20, 0x00, 0x2C, 0x46, 0xD0, 0x64, 0xF0, 0x7F, 0x04, 0x8C, 0x72, 0x00, 0xEB, 0x80, 0x03, 0xC3, 0xEB, +0xC3, 0x03, 0x4F, 0xF0, 0x8C, 0x0C, 0xDF, 0xF8, 0x8C, 0x90, 0xDF, 0xF8, 0x8C, 0x80, 0x06, 0xEB, 0x83, 0x03, 0x0C, 0xFB, +0x00, 0x6C, 0x01, 0xF1, 0x0B, 0x02, 0x01, 0xF1, 0x25, 0x0E, 0x00, 0x24, 0x1D, 0x7C, 0xC5, 0xB1, 0x9C, 0xF8, 0x87, 0x50, +0x15, 0xB1, 0x93, 0xF8, 0x21, 0x50, 0x55, 0xBB, 0x1D, 0x7D, 0x15, 0x70, 0xD3, 0xE9, 0x06, 0x57, 0xC2, 0xF8, 0x01, 0x50, +0xC2, 0xF8, 0x05, 0x70, 0xD9, 0xF8, 0x00, 0x50, 0xD8, 0xF8, 0x10, 0x70, 0xED, 0x1B, 0x5F, 0x6A, 0x01, 0x34, 0x3D, 0x44, +0xE4, 0xB2, 0xC2, 0xF8, 0x09, 0x50, 0x0D, 0x32, 0x72, 0x45, 0x03, 0xF1, 0x30, 0x03, 0xDF, 0xD1, 0x8C, 0x22, 0x04, 0xEB, +0x44, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x02, 0xFB, 0x00, 0x60, 0x03, 0xF1, 0x09, 0x02, 0x80, 0xF8, 0x88, 0x40, 0x02, 0x33, +0x4A, 0x70, 0xA1, 0xF8, 0x07, 0x30, 0xBD, 0xE8, 0xF0, 0x83, 0x8C, 0x72, 0xB9, 0xE7, 0x93, 0xF8, 0x20, 0x50, 0x01, 0x2D, +0xD0, 0xD1, 0xE2, 0xE7, 0x48, 0x9E, 0x17, 0x00, 0xA4, 0x80, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x02, 0x29, 0x20, 0xD0, +0x03, 0x29, 0x0F, 0xD0, 0x01, 0x29, 0x06, 0xD0, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1E, 0xDB, +0x70, 0x47, 0x13, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x80, 0xF8, 0x84, 0x10, 0x70, 0x47, 0x0F, 0x4B, 0x8C, 0x22, +0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0x84, 0x30, 0x00, 0x2B, 0xEF, 0xD1, 0x0C, 0x4B, 0x90, 0xF8, 0x71, 0x00, 0xD3, 0xF8, +0x90, 0x31, 0x01, 0x21, 0x18, 0x47, 0x08, 0x4B, 0x8C, 0x22, 0x02, 0xFB, 0x00, 0x30, 0x00, 0x23, 0x80, 0xF8, 0x84, 0x30, +0x70, 0x47, 0x06, 0x49, 0x06, 0x48, 0x4F, 0xF4, 0xEA, 0x62, 0x03, 0xF0, 0xA5, 0xBF, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x48, 0x9E, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x90, 0xF8, 0xC0, 0x34, +0x33, 0xB1, 0x90, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x43, 0x68, 0x43, 0xF0, 0x40, 0x03, 0x43, 0x60, 0x70, 0x47, 0x00, 0xBF, +0x2D, 0xE9, 0xF0, 0x47, 0x36, 0x4F, 0x02, 0x7E, 0xDF, 0xF8, 0xE0, 0x80, 0x35, 0x49, 0xD8, 0xF8, 0xB0, 0x33, 0x0E, 0x69, +0x05, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x70, 0x98, 0x47, 0xEB, 0x7E, 0x00, 0x2B, 0x3A, 0xD0, 0xD5, 0xE9, +0x04, 0x43, 0x02, 0x2C, 0x8C, 0xBF, 0x01, 0x24, 0x00, 0x24, 0x02, 0x2B, 0x6B, 0x7E, 0x95, 0xF8, 0x18, 0xA0, 0x88, 0xBF, +0x44, 0xF0, 0x02, 0x04, 0x63, 0x40, 0x9B, 0x07, 0x44, 0xD1, 0xD1, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x0A, 0x7A, +0x6C, 0x76, 0xDA, 0xF8, 0xE4, 0x00, 0x18, 0xB3, 0xDF, 0xF8, 0x94, 0xC0, 0x4F, 0xF0, 0x00, 0x0E, 0x90, 0xF8, 0x23, 0x10, +0x00, 0x68, 0x01, 0xEB, 0x41, 0x04, 0x64, 0x44, 0x4B, 0x00, 0x62, 0x78, 0xA4, 0x78, 0x02, 0x2A, 0x0B, 0x44, 0x88, 0xBF, +0x01, 0x22, 0x0C, 0xEB, 0x03, 0x01, 0x98, 0xBF, 0x00, 0x22, 0x02, 0x2C, 0x88, 0xBF, 0x42, 0xF0, 0x02, 0x02, 0x0C, 0xF8, +0x03, 0x20, 0x81, 0xF8, 0x01, 0xE0, 0x81, 0xF8, 0x02, 0xE0, 0x00, 0x28, 0xE2, 0xD1, 0x01, 0xE0, 0x95, 0xF8, 0x18, 0x90, +0x11, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0x77, 0x9B, 0x6A, 0x39, 0x6C, 0x00, 0x22, 0x5B, 0x1A, 0xC5, 0xE9, +0x04, 0x22, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x06, 0xF5, 0xC3, 0x31, 0xEB, 0x76, 0xD8, 0xF8, 0xE0, 0x31, 0x28, 0x46, +0xA0, 0x31, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x21, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0xC4, 0xFC, 0x95, 0xF8, 0x18, 0x90, +0xB4, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x60, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x10, 0x4D, 0xDF, 0xF8, 0x44, 0x80, 0xC0, 0xEB, 0xC0, 0x03, 0x05, 0xEB, +0x83, 0x03, 0xC0, 0xEB, 0xC0, 0x06, 0x9B, 0x7E, 0x04, 0x46, 0x05, 0xEB, 0x86, 0x06, 0xC7, 0x00, 0x1B, 0xB1, 0xD8, 0xF8, +0xD8, 0x31, 0x30, 0x46, 0x98, 0x47, 0x3F, 0x1B, 0x05, 0xEB, 0x87, 0x05, 0x1C, 0x22, 0x00, 0x21, 0x30, 0x46, 0xDF, 0xF7, +0x0F, 0xFA, 0xD8, 0xF8, 0x34, 0x33, 0xAE, 0x60, 0x2C, 0x76, 0x6B, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x80, 0x9F, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x00, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0xD1, 0xFF, 0x02, 0x20, +0xFF, 0xF7, 0xCE, 0xFF, 0x03, 0x20, 0xFF, 0xF7, 0xCB, 0xFF, 0x05, 0x4B, 0x00, 0x22, 0x03, 0xF1, 0x1E, 0x01, 0x5A, 0x70, +0x9A, 0x70, 0x03, 0xF8, 0x03, 0x2B, 0x8B, 0x42, 0xF9, 0xD1, 0x08, 0xBD, 0x60, 0x9F, 0x17, 0x00, 0x0B, 0x4A, 0xC0, 0xEB, +0xC0, 0x03, 0x02, 0xEB, 0x83, 0x03, 0x99, 0x7E, 0x71, 0xB9, 0x30, 0xB4, 0x08, 0x49, 0x09, 0x4C, 0x09, 0x69, 0xD4, 0xF8, +0xE0, 0x41, 0x01, 0x25, 0x01, 0xF5, 0xC3, 0x31, 0x9D, 0x76, 0x18, 0x46, 0xA0, 0x31, 0x23, 0x46, 0x30, 0xBC, 0x18, 0x47, +0x70, 0x47, 0x00, 0xBF, 0x80, 0x9F, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x09, 0x29, 0x08, 0xB5, +0x09, 0xD9, 0x6A, 0xBB, 0x21, 0x4B, 0xC0, 0xEB, 0xC0, 0x00, 0x03, 0xEB, 0x80, 0x00, 0x03, 0x69, 0x01, 0x33, 0x03, 0x61, +0x08, 0xBD, 0x8A, 0xB1, 0x1C, 0x4B, 0x1D, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, +0x11, 0x44, 0x42, 0x69, 0x8B, 0x78, 0x01, 0x32, 0x02, 0x2B, 0x42, 0x61, 0xEE, 0xD8, 0x01, 0x33, 0x8B, 0x70, 0x08, 0xBD, +0x13, 0x4B, 0x14, 0x4A, 0xC0, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x41, 0x01, 0x03, 0xEB, 0x80, 0x00, 0x11, 0x44, 0x03, 0x69, +0x4A, 0x78, 0x01, 0x33, 0x02, 0x2A, 0x03, 0x61, 0xDC, 0xD8, 0x01, 0x32, 0x4A, 0x70, 0x08, 0xBD, 0x0A, 0x4A, 0x0C, 0x4B, +0x1C, 0x21, 0x01, 0xFB, 0x00, 0x20, 0x1A, 0x68, 0x43, 0x69, 0xB2, 0xF9, 0x00, 0x20, 0x01, 0x33, 0x00, 0x2A, 0x43, 0x61, +0x05, 0xDA, 0x07, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x69, 0x12, 0x03, 0xF0, 0x6F, 0xFE, 0x00, 0x23, 0x9B, 0x78, 0xFF, 0xDE, +0x80, 0x9F, 0x17, 0x00, 0x60, 0x9F, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF8, 0xA3, 0x15, 0x00, +0x70, 0xB5, 0x1E, 0x46, 0x0D, 0x46, 0x01, 0x23, 0x31, 0x46, 0x40, 0xF6, 0x01, 0x00, 0x01, 0xF0, 0x77, 0xFD, 0x04, 0x46, +0x02, 0x20, 0x02, 0xF0, 0x15, 0xF8, 0x18, 0x4A, 0x18, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x25, 0xFC, 0x02, 0x20, +0x02, 0xF0, 0x0C, 0xF8, 0xA0, 0xB9, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x16, 0xDB, 0x13, 0x4A, +0x00, 0x23, 0x23, 0x70, 0x28, 0x46, 0x15, 0x60, 0x93, 0x72, 0x16, 0x81, 0x01, 0x25, 0x00, 0xF0, 0x7D, 0xF9, 0x20, 0x46, +0x01, 0xF0, 0x86, 0xFD, 0x28, 0x46, 0x70, 0xBD, 0x08, 0x23, 0x20, 0x46, 0x23, 0x70, 0x00, 0x25, 0x01, 0xF0, 0x7E, 0xFD, +0x28, 0x46, 0x70, 0xBD, 0x95, 0xF8, 0x6F, 0x31, 0x00, 0x2B, 0xE4, 0xD1, 0x06, 0x49, 0x07, 0x48, 0x46, 0x22, 0x03, 0xF0, +0x25, 0xFE, 0xDE, 0xE7, 0x84, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x08, 0xA4, 0x15, 0x00, 0x17, 0x4A, 0x18, 0x4B, 0x12, 0x68, 0x70, 0xB5, 0xB2, 0xF9, 0x00, 0x20, +0x1D, 0x68, 0x9C, 0x7A, 0x00, 0x2A, 0x19, 0xDB, 0x14, 0x4A, 0x15, 0x48, 0xD2, 0xE9, 0x00, 0x63, 0x04, 0xEB, 0x44, 0x04, +0x05, 0xEB, 0x44, 0x04, 0x43, 0xF4, 0x08, 0x53, 0xE1, 0x78, 0x53, 0x60, 0x33, 0x43, 0x03, 0x60, 0xCB, 0x07, 0x03, 0xD4, +0x0E, 0x4B, 0xD3, 0xF8, 0xEC, 0x32, 0x98, 0x47, 0x03, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x0E, 0xFF, 0x00, 0x20, 0x70, 0xBD, +0x02, 0x20, 0x01, 0xF0, 0xB1, 0xFF, 0x02, 0x28, 0xE0, 0xD0, 0x08, 0x49, 0x08, 0x48, 0x9C, 0x22, 0x03, 0xF0, 0xEA, 0xFD, +0xDA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xF4, 0x9F, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, 0x60, 0x00, 0x32, 0x40, +0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xA4, 0x15, 0x00, 0x38, 0xB5, 0x22, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x32, 0xDB, 0x20, 0x49, 0x20, 0x48, 0x21, 0x4C, 0xD1, 0xE9, 0x00, 0x32, 0x22, 0xF4, 0x08, 0x52, +0x13, 0x43, 0x03, 0x60, 0xA3, 0x7A, 0x20, 0x68, 0x4A, 0x60, 0x90, 0xF8, 0x6F, 0x51, 0x01, 0x33, 0xDB, 0xB2, 0x9D, 0x42, +0xA3, 0x72, 0x01, 0xD9, 0xE3, 0x7A, 0x93, 0xB1, 0x0C, 0x38, 0x01, 0xF0, 0x55, 0xFD, 0xE3, 0x7A, 0x8B, 0xB1, 0x16, 0x4B, +0x21, 0x89, 0xD3, 0xF8, 0xF0, 0x32, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0xE3, 0x72, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, +0xC5, 0xFE, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xF0, 0x8D, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x21, 0x89, 0x02, 0x22, 0x40, 0xF6, +0x02, 0x00, 0x01, 0xF0, 0x27, 0xFD, 0xEE, 0xE7, 0x02, 0x20, 0x01, 0xF0, 0x5D, 0xFF, 0x03, 0x28, 0xC7, 0xD0, 0x08, 0x49, +0x08, 0x48, 0xC2, 0x22, 0x03, 0xF0, 0x96, 0xFD, 0xC1, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x98, 0x9C, 0x17, 0x00, +0x60, 0x00, 0x32, 0x40, 0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xA4, 0x15, 0x00, +0x38, 0xB5, 0x02, 0x20, 0x1D, 0x46, 0x01, 0xF0, 0x41, 0xFF, 0x0A, 0x4A, 0x0A, 0x49, 0x04, 0x46, 0x03, 0x46, 0x04, 0x20, +0x03, 0xF0, 0x50, 0xFB, 0x24, 0xB1, 0x08, 0x4B, 0x01, 0x22, 0xDA, 0x72, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x29, 0x46, +0xD3, 0xF8, 0xF0, 0x32, 0x01, 0x20, 0x98, 0x47, 0x00, 0x20, 0x38, 0xBD, 0x9C, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, +0xF4, 0x9F, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x88, 0x11, 0x68, 0x40, 0xF6, 0x6C, 0x12, 0x93, 0x42, +0x08, 0x69, 0x1F, 0xD0, 0x40, 0xF6, 0x85, 0x12, 0x93, 0x42, 0x1B, 0xD0, 0x40, 0xF6, 0x9E, 0x12, 0x93, 0x42, 0x17, 0xD0, +0x40, 0xF6, 0xA8, 0x12, 0x93, 0x42, 0x13, 0xD0, 0x41, 0xF2, 0x3C, 0x42, 0x93, 0x42, 0x0F, 0xD0, 0x41, 0xF2, 0x64, 0x42, +0x93, 0x42, 0x0B, 0xD0, 0x41, 0xF2, 0x85, 0x62, 0x93, 0x42, 0x07, 0xD0, 0x41, 0xF2, 0x99, 0x62, 0x93, 0x42, 0x03, 0xD0, +0x41, 0xF2, 0xAD, 0x62, 0x93, 0x42, 0x02, 0xD1, 0x00, 0xF5, 0x9C, 0x40, 0x20, 0x30, 0x70, 0x47, 0xC8, 0x35, 0x17, 0x00, +0x08, 0xB5, 0x0C, 0x22, 0x00, 0x21, 0x08, 0x48, 0xDF, 0xF7, 0x48, 0xF8, 0x00, 0x21, 0x02, 0x20, 0x01, 0xF0, 0x44, 0xFE, +0x05, 0x4B, 0x06, 0x4A, 0x1A, 0x60, 0x03, 0xF1, 0x14, 0x01, 0x00, 0x22, 0x99, 0x60, 0x1A, 0x61, 0x5A, 0x60, 0x08, 0xBD, +0xF4, 0x9F, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xDE, 0xFA, 0xFE, 0xCA, 0x2D, 0xE9, 0xF0, 0x41, 0x2A, 0x4F, 0xBB, 0x7A, +0x3E, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x06, 0xEB, 0x43, 0x05, 0x82, 0xB0, 0x95, 0xF8, 0x03, 0x80, 0x18, 0xF0, 0x05, 0x0F, +0x4F, 0xEA, 0x43, 0x04, 0x28, 0xD0, 0x24, 0x4B, 0x1B, 0x68, 0x5B, 0x69, 0x96, 0xF8, 0x6E, 0xC1, 0x95, 0xF9, 0x04, 0x20, +0x31, 0x5B, 0xA8, 0x78, 0xCD, 0xE9, 0x00, 0x8C, 0xFC, 0xF7, 0x94, 0xFC, 0x7B, 0x68, 0x93, 0xB1, 0xAA, 0x78, 0x31, 0x5B, +0xDA, 0xB9, 0xA1, 0xF6, 0x6C, 0x10, 0x48, 0x28, 0x0A, 0xD8, 0x40, 0xF6, 0xB4, 0x12, 0x91, 0x42, 0x28, 0xD0, 0x18, 0x48, +0xA1, 0xF6, 0x67, 0x12, 0xA0, 0xFB, 0x02, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0x02, 0x21, 0x08, 0x46, 0x02, 0xB0, +0xBD, 0xE8, 0xF0, 0x41, 0x01, 0xF0, 0xFA, 0xBD, 0x28, 0x46, 0xFF, 0xF7, 0x7B, 0xFF, 0x03, 0x46, 0xD4, 0xE7, 0x01, 0x2A, +0x02, 0xD0, 0x00, 0x22, 0x9A, 0x70, 0xEE, 0xE7, 0xA1, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, +0x4D, 0x7F, 0xF4, 0xD8, 0x07, 0x4A, 0x08, 0x39, 0xA2, 0xFB, 0x01, 0x12, 0xC2, 0xF3, 0x87, 0x02, 0x9A, 0x70, 0xDE, 0xE7, +0x0E, 0x22, 0x9A, 0x70, 0xDB, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, +0x70, 0xB5, 0x0B, 0x4E, 0x0B, 0x4C, 0x33, 0x68, 0x05, 0x46, 0xB3, 0xF8, 0x6C, 0x11, 0x20, 0x46, 0x02, 0xF0, 0x7A, 0xFB, +0x70, 0x60, 0xFF, 0xF7, 0x95, 0xFF, 0x54, 0xF8, 0x0C, 0x2C, 0xB5, 0xF8, 0x6C, 0x11, 0x01, 0x3A, 0x0A, 0x44, 0x00, 0x21, +0x44, 0xE9, 0x02, 0x21, 0x70, 0xBD, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0xE8, 0x61, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, +0xDF, 0xF8, 0xD8, 0x90, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x93, 0x06, 0x46, 0x93, 0xF8, 0xC0, 0x04, 0x93, 0xF8, +0x6C, 0x50, 0x88, 0x46, 0x17, 0x46, 0x00, 0x28, 0x52, 0xD1, 0x1B, 0x6C, 0x18, 0x79, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, +0x1A, 0x21, 0xEE, 0xF7, 0x75, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x4E, 0xD0, 0x28, 0x4A, 0xDF, 0xF8, 0xA8, 0xE0, 0x4F, 0xF4, +0x1E, 0x71, 0x01, 0xFB, 0x05, 0x21, 0xD0, 0xE9, 0x12, 0x3C, 0x0A, 0x46, 0xBE, 0xF8, 0xFC, 0x51, 0x52, 0xF8, 0x26, 0x0F, +0xD8, 0x66, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x06, 0x99, 0x40, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x90, 0x88, 0xA3, 0xF8, +0x70, 0x00, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x90, 0xC3, 0xF8, 0x72, 0x00, 0x01, 0x35, 0x90, 0x88, 0xA3, 0xF8, +0x76, 0x90, 0xAD, 0xB2, 0xD2, 0xF8, 0x00, 0x90, 0xA3, 0xF8, 0x7C, 0x00, 0x00, 0x20, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, +0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0xC3, 0xF8, 0x78, 0x90, 0xAE, 0xF8, 0xFC, 0x51, 0x2D, 0x01, 0x83, 0xF8, 0x80, 0x00, +0x83, 0xF8, 0x81, 0x00, 0xA3, 0xF8, 0x7E, 0x50, 0xCC, 0xF8, 0x20, 0x00, 0x26, 0x77, 0x91, 0xF8, 0x23, 0x30, 0x63, 0x77, +0xC4, 0xE9, 0x15, 0x87, 0x20, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xEE, 0xF7, 0x3A, 0xBE, 0x01, 0x20, 0x1A, 0x21, +0xEE, 0xF7, 0x26, 0xFE, 0x04, 0x46, 0x00, 0x28, 0xB0, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x52, 0x4B, 0x83, 0xB0, 0x1D, 0x68, 0x9B, 0x7A, +0x01, 0x93, 0x95, 0xF8, 0x70, 0x31, 0x95, 0xF8, 0x6E, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x8B, 0x80, 0x4D, 0x4B, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x08, 0x38, 0x08, 0xF1, 0x5C, 0x07, 0x05, 0xF1, 0xFD, 0x09, 0x00, 0x26, 0x98, 0xF8, 0xC0, 0x34, +0x00, 0x2B, 0x7F, 0xD1, 0x01, 0x9B, 0x03, 0xEB, 0x43, 0x03, 0x05, 0xEB, 0x43, 0x03, 0x9B, 0x78, 0x00, 0x2B, 0x77, 0xD1, +0x95, 0xF8, 0x71, 0x01, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x19, 0xF8, 0x01, 0x3C, 0xB5, 0xF8, 0x6C, 0x11, 0x1A, 0x33, +0x19, 0x44, 0xEE, 0xF7, 0xE9, 0xFD, 0x4A, 0x46, 0x01, 0x46, 0x00, 0x28, 0x63, 0xD0, 0xD0, 0xE9, 0x12, 0x3C, 0x40, 0x24, +0x00, 0x20, 0x83, 0xF8, 0x68, 0x40, 0x83, 0xF8, 0x69, 0x00, 0x83, 0xF8, 0x6A, 0x00, 0x83, 0xF8, 0x6B, 0x00, 0x95, 0xF8, +0x60, 0x01, 0xC0, 0x07, 0x58, 0xD4, 0xD5, 0xF8, 0x60, 0x01, 0xB5, 0xF8, 0x64, 0x41, 0xA3, 0xF8, 0x70, 0x40, 0xD8, 0x66, +0x05, 0xF5, 0xB0, 0x7A, 0xDF, 0xF8, 0xC0, 0xE0, 0x38, 0x68, 0xBE, 0xF8, 0xFC, 0x41, 0xB7, 0xF8, 0x04, 0xB0, 0xC3, 0xF8, +0x72, 0x00, 0x01, 0x34, 0xDA, 0xF8, 0x00, 0x00, 0xBA, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x76, 0xB0, 0xA4, 0xB2, 0x4F, 0xF0, +0x00, 0x0B, 0x98, 0x67, 0xA3, 0xF8, 0x7C, 0xA0, 0xAE, 0xF8, 0xFC, 0x41, 0x83, 0xF8, 0x80, 0xB0, 0x19, 0xF8, 0x01, 0x0C, +0x83, 0xF8, 0x81, 0x00, 0x19, 0xF8, 0x01, 0x0C, 0x24, 0x01, 0xA3, 0xF8, 0x7E, 0x40, 0x40, 0xB1, 0x81, 0x33, 0x09, 0xEB, +0x00, 0x04, 0x12, 0xF8, 0x01, 0x0B, 0x03, 0xF8, 0x01, 0x0F, 0xA2, 0x42, 0xF9, 0xD1, 0xB5, 0xF8, 0x6C, 0x21, 0xDC, 0xF8, +0x28, 0x30, 0x16, 0x48, 0xCC, 0xF8, 0x20, 0x00, 0x9B, 0x1A, 0x00, 0x22, 0xCC, 0xF8, 0x28, 0x30, 0xC1, 0xE9, 0x15, 0x22, +0x95, 0xF8, 0x6E, 0x31, 0x0B, 0x77, 0xFF, 0x23, 0x4B, 0x77, 0x08, 0x46, 0x05, 0x21, 0xEE, 0xF7, 0x99, 0xFD, 0x95, 0xF8, +0x70, 0x31, 0x01, 0x36, 0xB3, 0x42, 0x09, 0xF1, 0x21, 0x09, 0x3F, 0xF7, 0x7F, 0xAF, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x01, 0x20, 0x8A, 0xE7, 0x07, 0x48, 0x04, 0x68, 0x80, 0x88, 0xDC, 0x66, 0xA3, 0xF8, 0x70, 0x00, 0x05, 0xF5, 0xB0, 0x7A, +0xA6, 0xE7, 0x00, 0xBF, 0xF4, 0x9F, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xAC, 0xB2, 0x15, 0x00, +0x20, 0x62, 0x17, 0x00, 0x38, 0xB5, 0x02, 0x22, 0x05, 0x46, 0x01, 0x23, 0x40, 0xF6, 0x04, 0x00, 0x01, 0xF0, 0x92, 0xFA, +0x04, 0x46, 0x02, 0x20, 0x01, 0xF0, 0x30, 0xFD, 0x05, 0x4A, 0x06, 0x49, 0x03, 0x46, 0x04, 0x20, 0x03, 0xF0, 0x40, 0xF9, +0x25, 0x70, 0x20, 0x46, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0xF0, 0xB2, 0xBA, 0xBC, 0xA4, 0x15, 0x00, 0x00, 0xA4, 0x15, 0x00, +0x03, 0x4A, 0x93, 0x7A, 0x10, 0x68, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x43, 0x00, 0x70, 0x47, 0xF4, 0x9F, 0x17, 0x00, +0xC3, 0x78, 0x13, 0xF0, 0x05, 0x0F, 0x03, 0xD0, 0x02, 0x4B, 0x1B, 0x68, 0x58, 0x69, 0x70, 0x47, 0xFF, 0xF7, 0xE8, 0xBD, +0xC8, 0x35, 0x17, 0x00, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDA, 0x0C, 0x4B, 0x1B, 0x68, +0x1B, 0x07, 0x0D, 0xD1, 0x0B, 0x48, 0x0C, 0x49, 0x02, 0x68, 0x4B, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x23, 0xF0, +0x04, 0x03, 0x4F, 0xF0, 0x80, 0x60, 0x4B, 0x60, 0x01, 0xF0, 0x3C, 0xBE, 0x06, 0x49, 0x07, 0x48, 0x84, 0x22, 0x03, 0xF0, +0xFB, 0xBA, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x38, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x84, 0x9E, 0x15, 0x00, 0x5A, 0x4A, 0x5B, 0x49, 0x13, 0x68, 0xF0, 0xB4, 0x14, 0x68, 0x5A, 0x4E, +0x5A, 0x4D, 0x24, 0xF0, 0xFF, 0x04, 0x04, 0x43, 0x14, 0x60, 0x14, 0x68, 0x17, 0x68, 0xC4, 0xF3, 0x09, 0x24, 0x27, 0xF4, +0x7F, 0x37, 0xDB, 0xB2, 0x00, 0xFB, 0x04, 0xF4, 0x27, 0xF4, 0x40, 0x77, 0xB4, 0xFB, 0xF3, 0xF4, 0x01, 0xEA, 0x04, 0x24, +0x3C, 0x43, 0x14, 0x60, 0x11, 0x68, 0x14, 0x68, 0xC1, 0xF3, 0x89, 0x41, 0x2C, 0x40, 0x00, 0xFB, 0x01, 0xF1, 0xB1, 0xFB, +0xF3, 0xF1, 0x06, 0xEA, 0x81, 0x41, 0x21, 0x43, 0x11, 0x60, 0x11, 0x68, 0x49, 0x4E, 0x4A, 0x4C, 0x0D, 0x40, 0x45, 0xF0, +0x89, 0x65, 0x15, 0x60, 0x32, 0x68, 0x35, 0x68, 0x47, 0x49, 0xC2, 0xF3, 0x0F, 0x22, 0x25, 0xF4, 0x7F, 0x05, 0x25, 0xF4, +0x7F, 0x45, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x2A, 0x43, 0x32, 0x60, 0x0A, 0x68, +0x0D, 0x68, 0x40, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, +0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x60, 0x0A, 0x68, 0x0C, 0x68, 0xC2, 0xF3, 0x09, 0x02, +0x24, 0xF4, 0x7F, 0x74, 0x00, 0xFB, 0x02, 0xF2, 0x24, 0xF0, 0x03, 0x04, 0xB2, 0xFB, 0xF3, 0xF2, 0xC2, 0xF3, 0x09, 0x02, +0x22, 0x43, 0x1D, 0x28, 0x0A, 0x60, 0x44, 0xD8, 0x4A, 0x68, 0x42, 0xF0, 0x03, 0x02, 0x4A, 0x60, 0x2E, 0x49, 0x2B, 0x4C, +0x0A, 0x68, 0x2E, 0x4E, 0x0F, 0x68, 0x2E, 0x4D, 0xC2, 0xF3, 0x0F, 0x22, 0x37, 0x40, 0x00, 0xFB, 0x02, 0xF2, 0xB2, 0xFB, +0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x3A, 0x43, 0x0A, 0x60, 0x2A, 0x68, 0x2F, 0x68, 0xC2, 0xF3, 0x0F, 0x22, 0x00, 0xFB, +0x02, 0xF2, 0x3E, 0x40, 0xB2, 0xFB, 0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x22, 0x32, 0x43, 0x2A, 0x60, 0x0A, 0x69, 0x0D, 0x69, +0x1D, 0x4C, 0xC2, 0xF3, 0x09, 0x52, 0x25, 0xF0, 0x7F, 0x55, 0x00, 0xFB, 0x02, 0xF2, 0x25, 0xF4, 0x40, 0x15, 0xB2, 0xFB, +0xF3, 0xF2, 0x04, 0xEA, 0x02, 0x52, 0x2A, 0x43, 0x0A, 0x61, 0x0C, 0x69, 0x0A, 0x69, 0xC4, 0xF3, 0x09, 0x04, 0x22, 0xF4, +0x7F, 0x72, 0x00, 0xFB, 0x04, 0xF0, 0x22, 0xF0, 0x03, 0x02, 0xB0, 0xFB, 0xF3, 0xF0, 0xC0, 0xF3, 0x09, 0x00, 0x10, 0x43, +0xF0, 0xBC, 0x08, 0x61, 0x70, 0x47, 0x11, 0x49, 0x0A, 0x68, 0x3B, 0x28, 0x22, 0xF0, 0x03, 0x02, 0x94, 0xBF, 0x42, 0xF0, +0x02, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x0A, 0x60, 0xB2, 0xE7, 0x00, 0xBF, 0xE4, 0x00, 0x32, 0x40, 0x00, 0xFF, 0x03, 0x00, +0x00, 0x00, 0xFC, 0x0F, 0xFF, 0xFF, 0x03, 0xF0, 0xE8, 0x00, 0x32, 0x40, 0x00, 0xFF, 0xFF, 0x00, 0xEC, 0x00, 0x32, 0x40, +0x00, 0x00, 0xF0, 0x3F, 0xF4, 0x00, 0x32, 0x40, 0xFF, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x32, 0x40, 0xF0, 0x00, 0x32, 0x40, +0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x2C, 0xDB, 0xF0, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x18, 0x4B, 0x18, 0x49, 0x1B, 0x68, 0x0E, 0x68, 0x18, 0x4C, +0x18, 0x4A, 0x19, 0x4D, 0x19, 0x4F, 0x03, 0xF5, 0xC3, 0x43, 0x28, 0x33, 0x70, 0x1C, 0x08, 0x60, 0x23, 0x60, 0x17, 0x4C, +0x80, 0x23, 0x13, 0x60, 0x2A, 0x68, 0x63, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x43, 0xF0, 0x04, 0x03, 0x2A, 0x60, 0x63, 0x60, +0x00, 0x23, 0x3B, 0x60, 0x28, 0xB1, 0x09, 0x4B, 0x0E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, +0x70, 0x47, 0x0B, 0x4B, 0x1B, 0x68, 0x1A, 0x07, 0xCE, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0xD9, 0x22, 0x03, 0xF0, 0xE4, 0xB9, +0x38, 0x36, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x20, 0x01, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x44, 0x01, 0x32, 0x40, +0x88, 0x80, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xD4, 0xA4, 0x15, 0x00, 0x03, 0x4A, 0x01, 0x23, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, 0xFB, 0xD1, 0x70, 0x47, +0x50, 0x80, 0x32, 0x40, 0x70, 0xB5, 0x76, 0x4A, 0x01, 0x23, 0x82, 0xB0, 0x13, 0x60, 0x13, 0x68, 0x13, 0xF0, 0xFF, 0x0F, +0xFB, 0xD1, 0x73, 0x4B, 0xD3, 0xF8, 0xF0, 0x40, 0xDE, 0xF7, 0x66, 0xFF, 0xA0, 0x47, 0x71, 0x4B, 0x71, 0x49, 0x72, 0x4A, +0x19, 0x60, 0x13, 0x68, 0x71, 0x49, 0x23, 0xF4, 0x00, 0x63, 0x13, 0x60, 0x0B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xC0, 0xF2, 0x86, 0x80, 0x6D, 0x48, 0x6E, 0x4B, 0x6A, 0x49, 0x6E, 0x4C, 0x6E, 0x4A, 0x04, 0x60, 0x1A, 0x60, 0x0A, 0x68, +0x6D, 0x4C, 0x6E, 0x4D, 0x42, 0xF0, 0x80, 0x62, 0x42, 0xF4, 0xF8, 0x62, 0x0A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x62, +0x0A, 0x60, 0x50, 0xF8, 0x84, 0x2C, 0x69, 0x49, 0xA3, 0xF5, 0x00, 0x43, 0x1C, 0x3B, 0x42, 0xF4, 0x80, 0x32, 0x40, 0xF8, +0x84, 0x2C, 0x25, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x7F, 0x42, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x02, 0x1A, 0x60, +0x1A, 0x68, 0x22, 0xF4, 0xFE, 0x02, 0x42, 0xF4, 0x80, 0x12, 0x1A, 0x60, 0x8A, 0x78, 0x2A, 0xB9, 0x1A, 0x68, 0x12, 0x0C, +0x12, 0x04, 0x42, 0xF0, 0x64, 0x02, 0x1A, 0x60, 0x5A, 0x4B, 0x5B, 0x49, 0x50, 0x4C, 0x5B, 0x4E, 0x5B, 0x4D, 0x00, 0x22, +0x4F, 0xF4, 0x40, 0x50, 0x08, 0x60, 0x1A, 0x60, 0x0D, 0xF1, 0x06, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0xE0, 0xF7, 0x1C, 0xF9, +0x9D, 0xF8, 0x07, 0x20, 0x9D, 0xF8, 0x06, 0x00, 0x54, 0x49, 0x13, 0x02, 0x43, 0xEA, 0x00, 0x43, 0x13, 0x43, 0x0B, 0x60, +0x23, 0x68, 0x52, 0x4A, 0x43, 0xF4, 0x80, 0x53, 0x23, 0x60, 0x23, 0x68, 0x41, 0xF6, 0x25, 0x40, 0x43, 0xF4, 0x00, 0x53, +0x23, 0x60, 0xC1, 0xF8, 0x70, 0x04, 0x13, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x13, 0x60, 0xDF, 0xF7, 0x77, 0xFD, 0x32, 0x68, +0x49, 0x49, 0x43, 0x1C, 0x9B, 0x06, 0x22, 0xF0, 0xE0, 0x52, 0x03, 0xF0, 0xE0, 0x53, 0x13, 0x43, 0x33, 0x60, 0x23, 0x68, +0x45, 0x4A, 0x43, 0xF0, 0x20, 0x03, 0x23, 0x60, 0x0B, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x43, 0xF0, +0x02, 0x03, 0x13, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x2B, 0x68, 0x99, 0x03, 0x13, 0xD4, 0x3D, 0x4A, +0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x2A, 0x4B, 0x1B, 0x68, 0xB3, 0xF1, 0xC8, 0x5F, +0xBF, 0xF4, 0x74, 0xAF, 0x37, 0x49, 0x38, 0x48, 0x40, 0xF2, 0x21, 0x12, 0x03, 0xF0, 0x46, 0xF9, 0x6C, 0xE7, 0xDF, 0xF7, +0x05, 0xFD, 0x00, 0x28, 0xE7, 0xD0, 0xDF, 0xF7, 0x35, 0xFD, 0x33, 0x4E, 0x32, 0x68, 0x00, 0x02, 0x00, 0xF4, 0xE0, 0x63, +0x22, 0xF4, 0xE0, 0x62, 0x13, 0x43, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x60, 0x03, 0x33, 0x60, +0x33, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x33, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x2B, 0x68, 0x1B, 0x04, +0x0D, 0xD4, 0x1E, 0x4B, 0x1B, 0x68, 0x9A, 0x03, 0xC7, 0xD5, 0xDF, 0xF7, 0xE9, 0xFC, 0x00, 0x28, 0xC3, 0xD0, 0x22, 0x4A, +0x13, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x13, 0x60, 0xBD, 0xE7, 0xDF, 0xF7, 0xB1, 0xFC, 0x00, 0x28, 0xED, 0xD0, 0x23, 0x68, +0x43, 0xF4, 0x00, 0x23, 0x23, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x60, 0x63, 0x43, 0xF0, 0x80, 0x63, 0x33, 0x60, 0xE2, 0xE7, +0x50, 0x80, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x74, 0x80, 0x32, 0x40, 0x4C, 0xF1, 0x73, 0x8B, 0x4C, 0x00, 0x32, 0x40, +0x38, 0x36, 0x17, 0x00, 0xD8, 0x00, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x10, 0x19, 0x04, 0x00, 0xC0, 0x07, 0xF9, 0x80, +0x60, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x3C, 0x36, 0x17, 0x00, 0x24, 0x02, 0x32, 0x40, 0x58, 0x01, 0x32, 0x40, +0x9C, 0x00, 0x32, 0x40, 0x04, 0x00, 0x32, 0x40, 0xA0, 0x00, 0x32, 0x40, 0x10, 0x03, 0x32, 0x40, 0x48, 0x80, 0x32, 0x40, +0x6C, 0x00, 0x32, 0x40, 0x00, 0x04, 0x32, 0x40, 0x70, 0x79, 0x15, 0x00, 0x40, 0x88, 0x15, 0x00, 0x50, 0x03, 0x32, 0x40, +0x05, 0x49, 0x06, 0x4A, 0x0B, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, +0x70, 0x47, 0x00, 0xBF, 0x74, 0x80, 0x32, 0x40, 0x80, 0x80, 0x32, 0x40, 0x1D, 0x4A, 0x1E, 0x49, 0x13, 0x68, 0x1E, 0x48, +0x30, 0xB4, 0x23, 0xF0, 0x80, 0x03, 0x00, 0x25, 0x3C, 0x24, 0x13, 0x60, 0x0D, 0x60, 0x0A, 0x46, 0x04, 0x60, 0x13, 0x68, +0x1B, 0x07, 0xFC, 0xD1, 0x17, 0x4A, 0x18, 0x49, 0x13, 0x68, 0x18, 0x4D, 0x18, 0x48, 0x19, 0x4C, 0x43, 0xF4, 0x80, 0x33, +0x13, 0x60, 0x0B, 0x68, 0x02, 0xF5, 0x00, 0x42, 0x23, 0xF0, 0xFF, 0x03, 0x0B, 0x60, 0x20, 0x32, 0x4F, 0xF0, 0xFF, 0x33, +0x2B, 0x60, 0x04, 0x60, 0x13, 0x68, 0x12, 0x4C, 0x12, 0x49, 0x43, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x22, 0x68, 0x4B, 0x68, +0xA0, 0xF5, 0x00, 0x40, 0x24, 0x38, 0x42, 0xF0, 0x00, 0x42, 0x22, 0x60, 0x02, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x42, 0xF0, +0x80, 0x02, 0x02, 0x60, 0x30, 0xBC, 0x4B, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x38, 0x00, 0x32, 0x40, +0x54, 0x00, 0x32, 0x40, 0x8C, 0x80, 0x32, 0x40, 0x7C, 0x80, 0x32, 0x40, 0x70, 0x80, 0x32, 0x40, 0x44, 0xF1, 0x73, 0x0B, +0x80, 0x80, 0x32, 0x40, 0x1C, 0x9E, 0x17, 0x00, 0x0B, 0x49, 0x0C, 0x4A, 0x0C, 0x4B, 0x10, 0xB4, 0x04, 0x68, 0x80, 0x88, +0x0C, 0x60, 0x4F, 0xF0, 0x00, 0x51, 0x10, 0x60, 0x1A, 0x46, 0x19, 0x60, 0x10, 0x68, 0x81, 0x00, 0xFC, 0xD4, 0xC3, 0x00, +0x5D, 0xBF, 0x00, 0x0C, 0x10, 0x38, 0xC0, 0xB2, 0xFF, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xBC, 0x00, 0x32, 0x40, +0xC0, 0x00, 0x32, 0x40, 0xC4, 0x00, 0x32, 0x40, 0x38, 0xB5, 0x11, 0x4B, 0x11, 0x48, 0x19, 0x68, 0x42, 0x68, 0x11, 0x4C, +0x11, 0x4D, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x21, 0xF0, 0x02, 0x01, 0x19, 0x60, 0x23, 0x68, 0x0E, 0x49, +0x43, 0xF4, 0xE0, 0x63, 0x2A, 0x43, 0x23, 0x60, 0x05, 0x60, 0x01, 0x20, 0x0A, 0x60, 0xF3, 0xF7, 0x51, 0xFB, 0x23, 0x68, +0x23, 0xF4, 0xE0, 0x33, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x23, 0x68, 0x43, 0xF4, 0x00, 0x53, 0x23, 0x60, 0x38, 0xBD, +0x74, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0xDE, 0xFF, 0xFF, 0x7F, 0x60, 0x00, 0x32, 0x40, +0x80, 0xEA, 0xE0, 0x72, 0xF0, 0xB4, 0xA2, 0xEB, 0xE0, 0x72, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x16, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x16, 0x4D, 0x16, 0x4B, 0x2E, 0x68, 0x1B, 0x68, 0x16, 0x49, 0x77, 0x1C, 0x00, 0x28, +0x09, 0x68, 0x2F, 0x60, 0x43, 0xF0, 0x80, 0x73, 0x15, 0xDD, 0x8A, 0x42, 0x18, 0xD8, 0x11, 0x49, 0x0F, 0x4C, 0x0A, 0x68, +0x10, 0x1A, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x23, 0x60, 0x08, 0x60, 0x00, 0x20, 0x23, 0x60, 0x2F, 0xB1, 0x08, 0x4B, +0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xF0, 0xBC, 0x70, 0x47, 0xEA, 0xD0, 0xC9, 0x43, 0x20, 0x32, +0x91, 0x42, 0xE6, 0xD2, 0x4F, 0xF0, 0xFF, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x4C, 0x00, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, 0x35, 0x4B, 0x1B, 0x68, 0x70, 0xB5, 0xC3, 0xF3, 0x40, 0x64, 0x9B, 0x01, +0x12, 0xD4, 0x33, 0x49, 0x33, 0x48, 0x0B, 0x69, 0x33, 0x4A, 0x05, 0x68, 0x08, 0x69, 0xB2, 0xF8, 0xB0, 0x10, 0xB2, 0xF8, +0xB2, 0x20, 0xA3, 0xF5, 0xFA, 0x63, 0x03, 0xEB, 0x45, 0x13, 0x1B, 0x1A, 0x5B, 0x1A, 0x9B, 0x1A, 0x00, 0x2B, 0x17, 0xDB, +0x2C, 0x4B, 0x1D, 0x68, 0x9D, 0xB1, 0x28, 0x48, 0x29, 0x4E, 0xEA, 0x68, 0x03, 0x69, 0xB6, 0xF8, 0xB0, 0x40, 0xB6, 0xF8, +0xB2, 0x10, 0xD3, 0x1A, 0xA3, 0xF5, 0xFA, 0x63, 0x1B, 0x1B, 0x5B, 0x1A, 0x00, 0x2B, 0x07, 0xDB, 0x24, 0x4B, 0x1B, 0x68, +0x1C, 0x78, 0x01, 0x2C, 0x0B, 0xD0, 0x01, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x21, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x12, 0xDB, 0x00, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x1D, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x18, 0xDB, 0x15, 0x4B, 0x52, 0x1A, 0x4F, 0xF4, 0x80, 0x20, 0x04, 0x21, 0x98, 0x60, 0x1A, 0x63, 0x20, 0x46, 0x99, 0x60, +0x70, 0xBD, 0x03, 0x69, 0xD2, 0x1A, 0x02, 0xF5, 0x9C, 0x52, 0x08, 0x32, 0x00, 0x2A, 0xE5, 0xDA, 0x12, 0x49, 0x13, 0x48, +0x40, 0xF2, 0x3E, 0x22, 0x02, 0xF0, 0x92, 0xFF, 0x00, 0x24, 0xD5, 0xE7, 0x03, 0x69, 0xD3, 0x1A, 0x5B, 0x1A, 0x00, 0x2B, +0xE1, 0xDA, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF2, 0x43, 0x22, 0x02, 0xF0, 0x85, 0xFF, 0xEA, 0x68, 0xB6, 0xF8, 0xB2, 0x10, +0xD7, 0xE7, 0x00, 0xBF, 0x4C, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x80, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, +0xD0, 0x9C, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0xA4, 0x15, 0x00, +0x80, 0x8D, 0x15, 0x00, 0x70, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0B, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x0B, 0x4B, 0x0B, 0x49, 0x0C, 0x4D, 0x0E, 0x68, 0x1A, 0x68, 0x28, 0x68, 0x09, 0x68, 0x54, 0x1C, 0xB1, 0x42, +0x18, 0xBF, 0x28, 0x68, 0x1C, 0x60, 0x2C, 0xB1, 0x03, 0x4C, 0x1A, 0x60, 0x23, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, +0x70, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xA8, 0x80, 0x32, 0x40, 0xA4, 0x80, 0x32, 0x40, +0x3B, 0x4A, 0x3C, 0x4B, 0x10, 0xB5, 0x14, 0x68, 0x1C, 0x60, 0x61, 0x05, 0x1D, 0xD4, 0xE2, 0x05, 0x16, 0xD4, 0xA3, 0x05, +0x10, 0xD4, 0xE0, 0x06, 0x31, 0xD4, 0x37, 0x4B, 0x1A, 0x78, 0x22, 0xB1, 0x14, 0xF0, 0x2F, 0x0F, 0x1C, 0xBF, 0x01, 0x22, +0x9A, 0x71, 0x34, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0D, 0xDB, 0x10, 0xBD, 0x31, 0x48, 0x02, 0xF0, +0xAD, 0xFC, 0xFE, 0xE7, 0xF2, 0xF7, 0x96, 0xFD, 0xA3, 0x05, 0xE6, 0xD5, 0xF6, 0xE7, 0x2E, 0x48, 0x02, 0xF0, 0xA4, 0xFC, +0xFE, 0xE7, 0xE1, 0x07, 0x1C, 0xD4, 0xA2, 0x07, 0x42, 0xD4, 0x63, 0x07, 0x38, 0xD4, 0x20, 0x07, 0x2E, 0xD4, 0x21, 0x06, +0x24, 0xD4, 0x62, 0x06, 0x1A, 0xD4, 0xA3, 0x06, 0xE3, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x25, 0x49, 0x25, 0x48, 0x40, 0xF2, +0xB5, 0x22, 0x02, 0xF0, 0xD5, 0xBE, 0x04, 0x20, 0xEC, 0xF7, 0xA4, 0xFD, 0x4F, 0xF0, 0x80, 0x41, 0x04, 0x20, 0xEC, 0xF7, +0x3F, 0xFE, 0xC4, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x2B, 0x72, 0x02, 0xF0, 0xC4, 0xBE, +0xBD, 0xE8, 0x10, 0x40, 0x18, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0xB3, 0x22, 0x02, 0xF0, 0xBC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, +0x14, 0x49, 0x18, 0x48, 0x40, 0xF2, 0xB1, 0x22, 0x02, 0xF0, 0xB4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x10, 0x49, 0x15, 0x48, +0x40, 0xF2, 0xAF, 0x22, 0x02, 0xF0, 0xAC, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x0C, 0x49, 0x12, 0x48, 0x40, 0xF2, 0xAE, 0x22, +0x02, 0xF0, 0xA4, 0xBE, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x49, 0x0F, 0x48, 0x40, 0xF2, 0xAD, 0x22, 0x02, 0xF0, 0x9C, 0xBE, +0x84, 0x80, 0x32, 0x40, 0x88, 0x80, 0x32, 0x40, 0x80, 0x35, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x5C, 0xA5, 0x15, 0x00, +0x28, 0xA5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xA6, 0x15, 0x00, 0x90, 0xA5, 0x15, 0x00, 0x58, 0xA6, 0x15, 0x00, +0x30, 0xA6, 0x15, 0x00, 0x08, 0xA6, 0x15, 0x00, 0xE0, 0xA5, 0x15, 0x00, 0xB8, 0xA5, 0x15, 0x00, 0x38, 0xB5, 0x62, 0x4A, +0x62, 0x4B, 0x11, 0x68, 0x1C, 0x68, 0x62, 0x4B, 0x0C, 0x40, 0x23, 0x40, 0x54, 0x60, 0x00, 0x2B, 0x54, 0xD1, 0x60, 0x4B, +0x23, 0x40, 0x00, 0x2B, 0x4B, 0xD1, 0x62, 0x07, 0x03, 0xD5, 0x5E, 0x4B, 0xD3, 0xF8, 0xDC, 0x30, 0x98, 0x47, 0x23, 0x07, +0x03, 0xD5, 0x5B, 0x4B, 0xD3, 0xF8, 0xD4, 0x30, 0x98, 0x47, 0xE5, 0x00, 0x2E, 0xD4, 0xE0, 0x05, 0x28, 0xD4, 0x58, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x00, 0xDB, 0x38, 0xBD, 0x61, 0x02, 0x3C, 0xD4, 0xA2, 0x02, 0x42, 0xD4, +0x63, 0x06, 0x48, 0xD4, 0xE5, 0x04, 0x4E, 0xD4, 0xA0, 0x04, 0x54, 0xD4, 0x61, 0x04, 0x5A, 0xD4, 0x22, 0x04, 0x60, 0xD4, +0xE3, 0x03, 0x66, 0xD4, 0xA5, 0x03, 0x6C, 0xD4, 0xE0, 0x01, 0x72, 0xD4, 0xA1, 0x01, 0x78, 0xD4, 0xE2, 0x02, 0x7E, 0xD4, +0x23, 0x01, 0xE4, 0xD5, 0xBD, 0xE8, 0x38, 0x40, 0x47, 0x49, 0x48, 0x48, 0x40, 0xF2, 0x19, 0x32, 0x02, 0xF0, 0x38, 0xBE, +0x46, 0x48, 0x02, 0xF0, 0xED, 0xFB, 0xD2, 0xE7, 0x45, 0x4B, 0x46, 0x4A, 0x1D, 0x68, 0x93, 0x7F, 0x05, 0xF0, 0x3F, 0x01, +0x0B, 0x43, 0x4F, 0xF4, 0x00, 0x20, 0x93, 0x77, 0x01, 0xF0, 0x64, 0xF9, 0x41, 0x4B, 0x1D, 0x60, 0xC1, 0xE7, 0x4F, 0xF0, +0x80, 0x70, 0x01, 0xF0, 0x5D, 0xF9, 0xAE, 0xE7, 0x4F, 0xF0, 0x00, 0x70, 0x01, 0xF0, 0x58, 0xF9, 0xA5, 0xE7, 0xBD, 0xE8, +0x38, 0x40, 0x35, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x0B, 0x32, 0x02, 0xF0, 0x13, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x31, 0x49, +0x37, 0x48, 0x4F, 0xF4, 0x43, 0x72, 0x02, 0xF0, 0x0B, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x2D, 0x49, 0x34, 0x48, 0x40, 0xF2, +0x0D, 0x32, 0x02, 0xF0, 0x03, 0xBE, 0xBD, 0xE8, 0x38, 0x40, 0x29, 0x49, 0x31, 0x48, 0x4F, 0xF4, 0x44, 0x72, 0x02, 0xF0, +0xFB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x25, 0x49, 0x2E, 0x48, 0x40, 0xF2, 0x11, 0x32, 0x02, 0xF0, 0xF3, 0xBD, 0xBD, 0xE8, +0x38, 0x40, 0x21, 0x49, 0x2B, 0x48, 0x40, 0xF2, 0x12, 0x32, 0x02, 0xF0, 0xEB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x1D, 0x49, +0x28, 0x48, 0x40, 0xF2, 0x13, 0x32, 0x02, 0xF0, 0xE3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x19, 0x49, 0x25, 0x48, 0x4F, 0xF4, +0x45, 0x72, 0x02, 0xF0, 0xDB, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x15, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x15, 0x32, 0x02, 0xF0, +0xD3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x11, 0x49, 0x1F, 0x48, 0x40, 0xF2, 0x16, 0x32, 0x02, 0xF0, 0xCB, 0xBD, 0xBD, 0xE8, +0x38, 0x40, 0x0D, 0x49, 0x1C, 0x48, 0x40, 0xF2, 0x17, 0x32, 0x02, 0xF0, 0xC3, 0xBD, 0xBD, 0xE8, 0x38, 0x40, 0x09, 0x49, +0x19, 0x48, 0x4F, 0xF4, 0x46, 0x72, 0x02, 0xF0, 0xBB, 0xBD, 0x00, 0xBF, 0x6C, 0x80, 0x32, 0x40, 0x74, 0x80, 0x32, 0x40, +0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x08, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x10, 0xA9, 0x15, 0x00, 0xA8, 0xA6, 0x15, 0x00, 0x90, 0x80, 0x32, 0x40, 0x98, 0x9C, 0x17, 0x00, 0x94, 0x80, 0x32, 0x40, +0xD8, 0xA6, 0x15, 0x00, 0x00, 0xA7, 0x15, 0x00, 0x34, 0xA7, 0x15, 0x00, 0x68, 0xA7, 0x15, 0x00, 0x90, 0xA7, 0x15, 0x00, +0xC0, 0xA7, 0x15, 0x00, 0xF0, 0xA7, 0x15, 0x00, 0x20, 0xA8, 0x15, 0x00, 0x50, 0xA8, 0x15, 0x00, 0x80, 0xA8, 0x15, 0x00, +0xB4, 0xA8, 0x15, 0x00, 0xE8, 0xA8, 0x15, 0x00, 0x10, 0xB5, 0x18, 0x4B, 0x84, 0xB0, 0xD3, 0xF8, 0x20, 0x32, 0x8D, 0xF8, +0x07, 0x00, 0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0x0D, 0xF1, 0x07, 0x00, 0x98, 0x47, 0x12, 0x4A, 0x13, 0x49, +0x13, 0x68, 0x9D, 0xF8, 0x0E, 0x40, 0x91, 0xF8, 0xBA, 0x00, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x04, 0x23, 0x13, 0x60, +0x18, 0xB1, 0x0E, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x4B, 0xB1, 0x0A, 0x4A, 0x9D, 0xF8, 0x0F, 0x10, 0x13, 0x68, 0x23, 0xF0, +0xFF, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x13, 0x68, 0x91, 0xF8, 0xBB, 0x10, 0x23, 0xF0, 0xFF, 0x03, +0x0B, 0x43, 0x13, 0x60, 0x04, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x2C, 0x19, 0x17, 0x00, +0xBC, 0x34, 0x17, 0x00, 0x30, 0xB5, 0x90, 0xF9, 0x65, 0x50, 0x7F, 0x2D, 0x83, 0xB0, 0x0E, 0xD0, 0x90, 0xF9, 0x66, 0x30, +0x0B, 0x48, 0x9D, 0x42, 0xA8, 0xBF, 0x1D, 0x46, 0x8D, 0xF8, 0x07, 0x50, 0xD0, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x07, 0x00, +0x98, 0x47, 0x03, 0xB0, 0x30, 0xBD, 0x0C, 0x46, 0x05, 0x49, 0x13, 0x46, 0x0A, 0x68, 0x12, 0x0A, 0x22, 0x70, 0x0A, 0x68, +0x1A, 0x70, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0x00, 0x32, 0x40, 0x91, 0xF9, 0x00, 0x30, +0x7F, 0x2B, 0x40, 0xD0, 0xF0, 0xB5, 0x20, 0x4E, 0x90, 0xF9, 0x65, 0x70, 0xD6, 0xF8, 0x20, 0x32, 0x85, 0xB0, 0x0C, 0x46, +0x05, 0x46, 0x11, 0x46, 0x20, 0x46, 0x0D, 0xF1, 0x0F, 0x02, 0x01, 0x91, 0x98, 0x47, 0x94, 0xF9, 0x00, 0x30, 0x95, 0xF9, +0x66, 0x20, 0x85, 0xF8, 0x65, 0x30, 0x93, 0x42, 0x20, 0xDC, 0x94, 0xF9, 0x00, 0x30, 0xBB, 0x42, 0x1A, 0xD0, 0xD5, 0xF8, +0xE4, 0x30, 0x43, 0xB1, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x10, 0x02, 0x83, 0xF8, 0x56, 0x21, 0x1B, 0x68, 0x00, 0x2B, +0xF6, 0xD1, 0x28, 0x6C, 0x60, 0xB1, 0xD6, 0xF8, 0xB4, 0x30, 0x98, 0x47, 0x28, 0x46, 0xFC, 0xF7, 0x5D, 0xFC, 0x28, 0xB1, +0x2A, 0x6C, 0xD6, 0xF8, 0x3C, 0x33, 0x92, 0xF9, 0x0C, 0x00, 0x98, 0x47, 0x05, 0xB0, 0xF0, 0xBD, 0x22, 0x70, 0x01, 0x99, +0xD6, 0xF8, 0x20, 0x32, 0x0D, 0xF1, 0x0F, 0x02, 0x20, 0x46, 0x98, 0x47, 0xD5, 0xE7, 0x70, 0x47, 0x88, 0x1A, 0x17, 0x00, +0x10, 0xB5, 0x15, 0x4B, 0x82, 0xB0, 0x0C, 0x46, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x07, 0x02, 0x0D, 0xF1, 0x06, 0x01, +0x98, 0x47, 0xE2, 0x6C, 0x10, 0x4B, 0x94, 0x6B, 0x93, 0xF8, 0xBD, 0x30, 0x61, 0x69, 0xC1, 0xF3, 0xC2, 0x20, 0xC9, 0xB2, +0x6B, 0xB9, 0x01, 0xF0, 0x7C, 0x01, 0x50, 0xEA, 0x01, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x06, 0x30, 0x9D, 0xF8, 0x07, 0x30, +0x43, 0xEA, 0x03, 0x23, 0x63, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0xF0, 0x7F, 0x01, 0xDF, 0xF7, 0xB1, 0xFA, 0x40, 0xEA, +0x00, 0x20, 0x60, 0x62, 0x02, 0xB0, 0x10, 0xBD, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x00, 0x29, 0x11, 0xDD, +0x10, 0xB4, 0x01, 0x39, 0x00, 0x23, 0x01, 0x24, 0x10, 0xF0, 0x01, 0x0F, 0x1C, 0xBF, 0x04, 0xFA, 0x01, 0xF2, 0x13, 0x43, +0x01, 0x39, 0x4F, 0xEA, 0x50, 0x00, 0xF5, 0xD2, 0x18, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x23, 0x18, 0x46, +0x70, 0x47, 0x00, 0xBF, 0x0B, 0x1F, 0x03, 0x44, 0x01, 0x44, 0x03, 0xF8, 0x01, 0x2B, 0x8B, 0x42, 0x4F, 0xEA, 0x12, 0x22, +0xF9, 0xD1, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x89, 0xB0, 0x8D, 0x88, 0x0C, 0x7D, 0x00, 0x95, 0x0D, 0x68, 0x01, 0x95, +0x03, 0x93, 0x1C, 0xB1, 0x0B, 0x69, 0xAB, 0x42, 0x00, 0xF0, 0xAC, 0x81, 0x01, 0x9B, 0xD9, 0x4F, 0x9C, 0xB2, 0x4F, 0xEA, +0x13, 0x4C, 0xCC, 0x80, 0xA1, 0xF8, 0x08, 0xC0, 0x53, 0x78, 0x16, 0x78, 0x46, 0xEA, 0x03, 0x26, 0x4E, 0x81, 0xD3, 0x78, +0x95, 0x78, 0x45, 0xEA, 0x03, 0x25, 0x8D, 0x81, 0x92, 0xF8, 0x05, 0xE0, 0x13, 0x79, 0x43, 0xEA, 0x0E, 0x23, 0xCB, 0x81, +0x4F, 0xF0, 0x00, 0x09, 0x09, 0xF0, 0x01, 0x0A, 0x00, 0xEB, 0x4A, 0x02, 0x10, 0xF8, 0x1A, 0x80, 0x92, 0xF8, 0x01, 0xE0, +0x02, 0x92, 0x48, 0xEA, 0x0E, 0x22, 0x5A, 0x40, 0x4F, 0xEA, 0x12, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, +0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x4F, 0xEA, 0x4A, 0x08, 0x14, 0x44, +0x08, 0xF1, 0x04, 0x02, 0xA4, 0xB2, 0x00, 0xEB, 0x02, 0x0E, 0xCC, 0x80, 0x82, 0x5C, 0x9E, 0xF8, 0x01, 0xE0, 0x42, 0xEA, +0x0E, 0x2E, 0x84, 0xEA, 0x0E, 0x0E, 0xCE, 0xF3, 0x0F, 0x22, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x12, 0x20, 0x37, 0xF8, +0x1E, 0xB0, 0x4F, 0xEA, 0x12, 0x2E, 0x4E, 0xEA, 0x02, 0x2E, 0x8E, 0xEA, 0x0B, 0x0B, 0xDC, 0x44, 0x08, 0xF1, 0x08, 0x0E, +0x1F, 0xFA, 0x8C, 0xFC, 0x00, 0xEB, 0x0E, 0x02, 0xA1, 0xF8, 0x08, 0xC0, 0x10, 0xF8, 0x0E, 0xE0, 0x52, 0x78, 0x4E, 0xEA, +0x02, 0x22, 0x8C, 0xEA, 0x02, 0x02, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0xB0, +0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x0B, 0x0B, 0x08, 0xF1, 0x0C, 0x08, 0x5E, 0x44, 0x00, 0xEB, +0x08, 0x02, 0xB6, 0xB2, 0x4E, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, 0x08, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x72, 0x40, +0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, 0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, +0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x15, 0x44, 0xAD, 0xB2, 0x02, 0x9A, 0x8D, 0x81, 0x92, 0xF8, 0x01, 0xE0, 0x10, 0xF8, +0x1A, 0x20, 0x42, 0xEA, 0x0E, 0x22, 0x6A, 0x40, 0xC2, 0xF3, 0x0F, 0x2E, 0xD2, 0xB2, 0x37, 0xF8, 0x1E, 0xE0, 0x37, 0xF8, +0x12, 0x80, 0x4F, 0xEA, 0x1E, 0x22, 0x42, 0xEA, 0x0E, 0x22, 0x82, 0xEA, 0x08, 0x02, 0x19, 0xFA, 0x82, 0xF2, 0x13, 0x44, +0x09, 0xF1, 0x01, 0x09, 0x9B, 0xB2, 0xB9, 0xF1, 0x08, 0x0F, 0xCB, 0x81, 0x7F, 0xF4, 0x6E, 0xAF, 0x01, 0x9A, 0x0A, 0x61, +0x4F, 0xF0, 0x01, 0x0E, 0x81, 0xF8, 0x14, 0xE0, 0x00, 0x9A, 0x90, 0xF8, 0x01, 0x80, 0x90, 0xF8, 0x00, 0xE0, 0x90, 0xF8, +0x03, 0x90, 0x1A, 0x44, 0x4E, 0xEA, 0x08, 0x2E, 0x92, 0xB2, 0x82, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x28, 0x5F, 0xFA, +0x8E, 0xFE, 0x37, 0xF8, 0x18, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, +0x08, 0x0A, 0x90, 0xF8, 0x02, 0x80, 0x90, 0xF8, 0x05, 0xE0, 0x54, 0x44, 0xA4, 0xB2, 0x48, 0xEA, 0x09, 0x28, 0x84, 0xEA, +0x08, 0x08, 0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, +0x1A, 0x28, 0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x04, 0x90, 0x90, 0xF8, 0x07, 0x80, 0xD4, 0x44, +0x1F, 0xFA, 0x8C, 0xFC, 0x49, 0xEA, 0x0E, 0x2E, 0x8C, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, +0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, +0x90, 0xF8, 0x06, 0x90, 0x90, 0xF8, 0x09, 0xE0, 0x56, 0x44, 0xB6, 0xB2, 0x49, 0xEA, 0x08, 0x28, 0x86, 0xEA, 0x08, 0x08, +0x4F, 0xEA, 0x18, 0x2A, 0x5F, 0xFA, 0x88, 0xF8, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x18, 0x90, 0x4F, 0xEA, 0x1A, 0x28, +0x48, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x08, 0x90, 0x90, 0xF8, 0x0B, 0x80, 0x55, 0x44, 0xAD, 0xB2, +0x49, 0xEA, 0x0E, 0x2E, 0x85, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, 0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, +0x37, 0xF8, 0x1E, 0x90, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, 0x0A, 0x2A, 0x8A, 0xEA, 0x09, 0x0A, 0x90, 0xF8, 0x0A, 0xE0, +0x90, 0xF8, 0x0D, 0x90, 0x53, 0x44, 0x9B, 0xB2, 0x4E, 0xEA, 0x08, 0x2E, 0x83, 0xEA, 0x0E, 0x0E, 0x4F, 0xEA, 0x1E, 0x2A, +0x5F, 0xFA, 0x8E, 0xFE, 0x37, 0xF8, 0x1A, 0xA0, 0x37, 0xF8, 0x1E, 0x80, 0x07, 0x7B, 0x4F, 0xEA, 0x1A, 0x2E, 0x4E, 0xEA, +0x0A, 0x2E, 0x8E, 0xEA, 0x08, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x47, 0xEA, 0x09, 0x29, 0x82, 0xEA, 0x09, 0x07, 0xFF, 0x03, +0x82, 0xEA, 0x09, 0x09, 0x90, 0xF8, 0x0F, 0xE0, 0x47, 0xEA, 0x59, 0x09, 0x87, 0x7B, 0x4C, 0x44, 0xA4, 0xB2, 0x47, 0xEA, +0x0E, 0x27, 0x84, 0xEA, 0x07, 0x0E, 0x4F, 0xEA, 0xCE, 0x3E, 0x67, 0x40, 0x4E, 0xEA, 0x57, 0x07, 0x67, 0x44, 0xBF, 0xB2, +0x4F, 0xEA, 0xC7, 0x3C, 0x4C, 0xEA, 0x57, 0x0C, 0x66, 0x44, 0xB6, 0xB2, 0x4F, 0xEA, 0xC6, 0x3C, 0x4C, 0xEA, 0x56, 0x0C, +0x65, 0x44, 0xAD, 0xB2, 0x4F, 0xEA, 0xC5, 0x3C, 0x4C, 0xEA, 0x55, 0x0C, 0x63, 0x44, 0x1F, 0xFA, 0x83, 0xF9, 0x00, 0x9B, +0xAD, 0xF8, 0x18, 0x60, 0x4F, 0xEA, 0x13, 0x2E, 0x0E, 0xF0, 0x7F, 0x0C, 0xAD, 0xF8, 0x16, 0x70, 0xAD, 0xF8, 0x1A, 0x50, +0x03, 0x9E, 0x00, 0x9D, 0xB5, 0x70, 0x4C, 0xF0, 0x20, 0x0C, 0x86, 0xF8, 0x00, 0xE0, 0x86, 0xF8, 0x01, 0xC0, 0x4F, 0xEA, +0xC9, 0x38, 0x45, 0x78, 0x03, 0x78, 0xAD, 0xF8, 0x1C, 0x90, 0x48, 0xEA, 0x59, 0x08, 0x42, 0x44, 0x92, 0xB2, 0x43, 0xEA, +0x05, 0x23, 0xAD, 0xF8, 0x1E, 0x20, 0x5A, 0x40, 0x52, 0x08, 0xF2, 0x70, 0x33, 0x46, 0x06, 0xF1, 0x0C, 0x00, 0x05, 0xAA, +0x01, 0xE0, 0x32, 0xF8, 0x02, 0x4F, 0x1C, 0x71, 0x25, 0x0A, 0x5D, 0x71, 0x02, 0x33, 0x98, 0x42, 0xF7, 0xD1, 0x00, 0x23, +0x0B, 0x75, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xCC, 0x88, 0xB1, 0xF8, 0x08, 0xC0, 0x4E, 0x89, 0x8D, 0x89, 0xCB, 0x89, +0x00, 0x4F, 0xFD, 0xE6, 0x50, 0xA9, 0x15, 0x00, 0xF0, 0xB4, 0x13, 0x4F, 0x01, 0x22, 0x3C, 0x1F, 0x00, 0x23, 0xC7, 0xF8, +0x00, 0x24, 0xC7, 0xF8, 0x04, 0x34, 0x22, 0x46, 0x42, 0xF8, 0x04, 0x3F, 0x01, 0x33, 0xB3, 0xF5, 0x80, 0x7F, 0xF9, 0xD1, +0x00, 0x23, 0xDF, 0xF8, 0x30, 0xC0, 0x1D, 0x46, 0xC2, 0x5C, 0x54, 0xF8, 0x04, 0x6F, 0x2A, 0x44, 0x32, 0x44, 0xD5, 0xB2, +0x01, 0x33, 0x57, 0xF8, 0x25, 0x20, 0x22, 0x60, 0x8B, 0x42, 0xA8, 0xBF, 0x00, 0x23, 0xA4, 0x45, 0x47, 0xF8, 0x25, 0x60, +0xEE, 0xD1, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x18, 0x2C, 0x17, 0x00, 0x14, 0x30, 0x17, 0x00, 0x71, 0xB3, 0x18, 0x4B, +0xF0, 0xB5, 0xD3, 0xF8, 0x00, 0x54, 0xD3, 0xF8, 0x04, 0x24, 0x53, 0xF8, 0x25, 0x60, 0x32, 0x44, 0x01, 0x39, 0xD2, 0xB2, +0x89, 0xB2, 0x01, 0x31, 0x53, 0xF8, 0x22, 0x40, 0x01, 0x44, 0x6F, 0x1C, 0x43, 0xF8, 0x22, 0x60, 0x43, 0xF8, 0x25, 0x40, +0xFD, 0xB2, 0x34, 0x44, 0xE4, 0xB2, 0x53, 0xF8, 0x25, 0x60, 0x53, 0xF8, 0x24, 0x70, 0x10, 0xF8, 0x01, 0x4B, 0x02, 0xEB, +0x06, 0x0C, 0x96, 0x46, 0x5F, 0xFA, 0x8C, 0xF2, 0x67, 0x40, 0x88, 0x42, 0x53, 0xF8, 0x22, 0x40, 0x00, 0xF8, 0x01, 0x7C, +0xE5, 0xD1, 0xC3, 0xF8, 0x00, 0x54, 0xC3, 0xF8, 0x04, 0xE4, 0xF0, 0xBD, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x2C, 0x17, 0x00, +0xFF, 0xF7, 0xCA, 0xBF, 0x83, 0x68, 0x8A, 0x68, 0x03, 0x48, 0x9B, 0x1A, 0x83, 0x42, 0x94, 0xBF, 0x00, 0x20, 0x01, 0x20, +0x70, 0x47, 0x00, 0xBF, 0x00, 0xA3, 0xE1, 0x11, 0x83, 0x88, 0xB3, 0xEB, 0x11, 0x4F, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, +0xC0, 0x88, 0x89, 0xB2, 0x40, 0x1A, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, +0xDF, 0xF8, 0x4C, 0xB1, 0xDB, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x07, 0x46, 0x89, 0x46, 0x15, 0x46, +0x5E, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x3F, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDF, 0xF8, +0x2C, 0x81, 0xDF, 0xF8, 0x2C, 0xA1, 0xD8, 0xF8, 0x00, 0x30, 0xDA, 0xF8, 0x14, 0x60, 0x01, 0x33, 0xC8, 0xF8, 0x00, 0x30, +0x1E, 0xB1, 0xB3, 0x88, 0xBB, 0x42, 0x40, 0xD0, 0x00, 0x26, 0x37, 0x49, 0x37, 0x48, 0x49, 0xEA, 0x07, 0x42, 0x00, 0xF0, +0xF5, 0xF9, 0x04, 0x46, 0x00, 0x28, 0x47, 0xD0, 0x34, 0x4B, 0x35, 0x4A, 0x1B, 0x69, 0x32, 0x48, 0x1D, 0x44, 0xA5, 0x60, +0x21, 0x46, 0x00, 0xF0, 0x87, 0xFE, 0x9E, 0xB9, 0xDA, 0xF8, 0x14, 0x30, 0xA3, 0x42, 0x13, 0xD0, 0xD8, 0xF8, 0x00, 0x30, +0x2B, 0xB1, 0x29, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xC8, 0xF8, 0x00, 0x30, 0x8B, 0xB1, 0x29, 0x4B, 0x1A, 0x69, 0xAD, 0x1A, +0x00, 0x2D, 0x14, 0xDB, 0xBD, 0xE8, 0xF8, 0x8F, 0xDA, 0xF8, 0x14, 0x40, 0x00, 0x2C, 0xEB, 0xD0, 0x25, 0x4B, 0xA1, 0x68, +0xD3, 0xF8, 0xE0, 0x31, 0x24, 0x48, 0x98, 0x47, 0xE4, 0xE7, 0x00, 0x2A, 0xEB, 0xD0, 0x62, 0xB6, 0x1E, 0x4B, 0x1A, 0x69, +0xAD, 0x1A, 0x00, 0x2D, 0xEA, 0xDA, 0xBD, 0xE8, 0xF8, 0x4F, 0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x29, 0xBD, 0xF6, 0x88, +0xA6, 0xEB, 0x09, 0x06, 0xB6, 0xFA, 0x86, 0xF6, 0x76, 0x09, 0xB8, 0xE7, 0xB2, 0xB1, 0x19, 0x4B, 0x9A, 0x42, 0x9C, 0xD9, +0x18, 0x49, 0x19, 0x48, 0x94, 0x22, 0x02, 0xF0, 0x0F, 0xFA, 0x96, 0xE7, 0x0C, 0x20, 0x00, 0xF0, 0xFB, 0xF9, 0xDB, 0xF8, +0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x09, 0xDB, 0xA7, 0x80, 0xA4, 0xF8, 0x06, 0x90, 0xA9, 0xE7, +0x0E, 0x49, 0x10, 0x48, 0x93, 0x22, 0x02, 0xF0, 0xFB, 0xF9, 0x82, 0xE7, 0x00, 0x28, 0xF3, 0xD1, 0x0A, 0x49, 0x0D, 0x48, +0xA5, 0x22, 0x02, 0xF0, 0xF3, 0xF9, 0xED, 0xE7, 0x38, 0x61, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x41, 0x26, 0x14, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, 0xFF, 0xA2, 0xE1, 0x11, +0x70, 0x79, 0x15, 0x00, 0x5C, 0xAB, 0x15, 0x00, 0x50, 0xAB, 0x15, 0x00, 0x78, 0xAB, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x25, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x25, 0x4D, 0x25, 0x4E, 0x2B, 0x68, 0x74, 0x69, 0x01, 0x33, 0x2B, 0x60, 0x74, 0xB1, +0xA3, 0x88, 0x83, 0x42, 0x02, 0xD1, 0xE3, 0x88, 0x8B, 0x42, 0x11, 0xD0, 0x41, 0xEA, 0x00, 0x42, 0x1F, 0x49, 0x20, 0x48, +0x00, 0xF0, 0x54, 0xF9, 0x04, 0x46, 0x38, 0xBB, 0x2B, 0x68, 0x33, 0xB1, 0x18, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, +0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x06, 0xF1, 0x14, 0x00, 0x00, 0xF0, 0x98, 0xFD, 0x77, 0x69, 0x17, 0x4B, +0xDF, 0xB1, 0xD3, 0xF8, 0xE0, 0x31, 0xB9, 0x68, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x0A, 0xDA, 0x12, 0x4A, 0xBB, 0x68, 0x12, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x04, 0xDA, 0x10, 0x49, +0x10, 0x48, 0xE7, 0x22, 0x02, 0xF0, 0x8E, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xED, 0xF9, 0x2B, 0x68, 0xD3, 0xE7, 0xD3, 0xF8, +0xD8, 0x31, 0x06, 0xF1, 0x20, 0x00, 0x98, 0x47, 0xF4, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x80, 0xB6, 0x17, 0x00, 0x59, 0x26, 0x14, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x80, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x28, 0x4D, 0x29, 0x4F, +0xDF, 0xF8, 0xB0, 0x80, 0x28, 0x4E, 0xDF, 0xF8, 0xB0, 0x90, 0x21, 0xE0, 0xA1, 0x68, 0x33, 0x69, 0xCB, 0x1A, 0x32, 0x2B, +0x07, 0xD4, 0xD9, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xA3, 0x68, 0x32, 0x69, 0x9B, 0x1A, 0x00, 0x2B, 0x30, 0xDA, 0x21, 0x48, +0x00, 0xF0, 0x44, 0xFD, 0x2B, 0x68, 0x04, 0x46, 0x5A, 0x1E, 0x2B, 0xB1, 0xD8, 0xF8, 0x00, 0x30, 0x2A, 0x60, 0x0A, 0xB9, +0x03, 0xB1, 0x62, 0xB6, 0xA0, 0x88, 0xE1, 0x88, 0xFF, 0x22, 0x00, 0xF0, 0xCB, 0xF8, 0x20, 0x46, 0x00, 0xF0, 0xA4, 0xF9, +0x4F, 0xF0, 0x00, 0x50, 0x00, 0xF0, 0x6C, 0xFC, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x01, 0x23, +0xC8, 0xF8, 0x00, 0x30, 0x2A, 0x68, 0x7C, 0x69, 0x10, 0x48, 0x53, 0x1C, 0x2B, 0x60, 0x00, 0x2C, 0xCA, 0xD1, 0x2B, 0xB1, +0x0E, 0x4B, 0x2A, 0x60, 0x1B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0x2B, 0x68, 0x00, 0x2B, +0xFA, 0xD0, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0xF4, 0xD1, 0x00, 0x2A, 0xF2, 0xD0, 0xF0, 0xE7, +0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x94, 0xB6, 0x17, 0x00, 0xA0, 0xB6, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x0E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0E, 0x4D, 0x0E, 0x4C, 0x2B, 0x68, 0x4F, 0xF0, 0x00, 0x50, 0x01, 0x33, 0x2B, 0x60, +0x00, 0xF0, 0x28, 0xFC, 0x01, 0xE0, 0x00, 0xF0, 0x59, 0xF9, 0x20, 0x46, 0x00, 0xF0, 0xE4, 0xFC, 0x00, 0x28, 0xF8, 0xD1, +0x2B, 0x68, 0x33, 0xB1, 0x03, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x38, 0xBD, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x94, 0xB6, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0x03, 0xF1, +0x0C, 0x00, 0x1D, 0x46, 0x0F, 0x46, 0x16, 0x46, 0x00, 0xF0, 0xC8, 0xF8, 0x0F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x04, 0x46, 0x0F, 0xDB, 0x00, 0x21, 0xA4, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x08, 0xE7, 0x80, 0x26, 0x81, +0x65, 0x81, 0x2A, 0x46, 0x21, 0x60, 0x40, 0x46, 0xDD, 0xF7, 0xDC, 0xFB, 0x40, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x28, +0xED, 0xD1, 0x04, 0x49, 0x04, 0x48, 0x52, 0x22, 0x02, 0xF0, 0xBA, 0xF8, 0xE7, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0xF8, 0x06, 0x3C, 0xB2, 0xF9, 0x00, 0x10, +0x00, 0x29, 0x10, 0xB5, 0xDA, 0xB2, 0x04, 0x46, 0x0C, 0xDB, 0x0B, 0x2A, 0x13, 0xD8, 0x11, 0x48, 0xA4, 0xF1, 0x0C, 0x01, +0x00, 0xF0, 0x4C, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xA4, 0xBB, 0x0D, 0x2A, 0xF0, 0xD9, +0x0B, 0x49, 0x0C, 0x48, 0xBB, 0x22, 0x02, 0xF0, 0x93, 0xF8, 0x34, 0xF8, 0x06, 0x3C, 0x34, 0xF8, 0x04, 0x2C, 0x34, 0xF8, +0x08, 0x1C, 0x08, 0x48, 0x01, 0xF0, 0x10, 0xFE, 0xA4, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0xF0, 0xDE, 0xB8, +0x38, 0x36, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0xB4, 0xAB, 0x15, 0x00, +0x08, 0xB5, 0x00, 0x23, 0xFF, 0xF7, 0x94, 0xFF, 0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0xC0, 0xBF, 0x10, 0xB4, 0x5D, 0xF8, +0x04, 0x4B, 0x20, 0xF8, 0x08, 0x1C, 0x20, 0xF8, 0x06, 0x2C, 0x20, 0xF8, 0x04, 0x3C, 0xFF, 0xF7, 0xB5, 0xBF, 0x00, 0xBF, +0x00, 0xF0, 0xC6, 0xB8, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x68, 0xD4, 0xB1, 0x07, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x4F, 0xF0, +0x00, 0x08, 0x02, 0xE0, 0xA0, 0x46, 0x93, 0xB1, 0x1C, 0x46, 0x31, 0x46, 0x20, 0x46, 0xA8, 0x47, 0x23, 0x68, 0x00, 0x28, +0xF6, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0x0C, 0xD0, 0xC8, 0xF8, 0x00, 0x30, 0x23, 0x68, 0x5B, 0xB1, 0x00, 0x23, 0x23, 0x60, +0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x24, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x3B, 0x60, 0x00, 0x2B, 0xF3, 0xD1, +0xC7, 0xF8, 0x04, 0x80, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0xBF, 0x0F, 0x48, 0x30, 0xB4, 0x20, 0xF0, 0x03, 0x00, +0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x0C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0B, 0x4A, 0x0C, 0x4B, +0x11, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x4C, 0x1C, 0x1B, 0x1A, 0x00, 0x25, 0x14, 0x60, 0xC0, 0xE9, 0x00, 0x53, 0x2C, 0xB1, +0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x03, 0xA0, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, 0xF8, 0xB5, 0x31, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x03, 0x30, 0x20, 0xF0, 0x03, 0x04, 0x00, 0x2B, 0x04, 0xF1, 0x04, 0x06, 0x48, 0xDB, 0x2C, 0x4B, 0xDB, 0x69, +0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x2A, 0x4A, 0x01, 0x21, 0x11, 0x60, 0x29, 0x4D, 0x2A, 0x68, +0x02, 0xF1, 0x01, 0x0C, 0xC5, 0xF8, 0x00, 0xC0, 0x00, 0x2B, 0x3E, 0xD0, 0x04, 0xF1, 0x0C, 0x00, 0x00, 0x21, 0x05, 0xE0, +0x4C, 0x68, 0xA2, 0x42, 0x38, 0xBF, 0x19, 0x46, 0x1B, 0x68, 0x43, 0xB1, 0x5A, 0x68, 0x82, 0x42, 0xFA, 0xD3, 0x00, 0x29, +0xF4, 0xD1, 0x19, 0x46, 0x1B, 0x68, 0x00, 0x2B, 0xF6, 0xD1, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x12, 0xDB, +0x0A, 0x46, 0x4B, 0x68, 0x9B, 0x1B, 0x98, 0x18, 0x4B, 0x60, 0x04, 0x30, 0x9E, 0x50, 0xBC, 0xF1, 0x00, 0x0F, 0x07, 0xD0, +0x13, 0x4A, 0x0C, 0xF1, 0xFF, 0x33, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xF8, 0xBD, 0x00, 0x29, +0xEA, 0xD1, 0x10, 0x49, 0x10, 0x48, 0x97, 0x22, 0x01, 0xF0, 0xC0, 0xFF, 0x00, 0x22, 0xD5, 0xF8, 0x00, 0xC0, 0x11, 0x46, +0xE1, 0xE7, 0x07, 0x2E, 0xB4, 0xD8, 0x0A, 0x49, 0x0B, 0x48, 0x7B, 0x22, 0x01, 0xF0, 0xB4, 0xFF, 0xAE, 0xE7, 0x3A, 0x68, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xE8, 0xDB, 0x5B, 0x68, 0xFF, 0xDE, 0x38, 0x36, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x08, 0xAC, 0x15, 0x00, 0xE0, 0xAB, 0x15, 0x00, +0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xF4, 0x90, 0x36, 0x4A, 0xD9, 0xF8, 0x00, 0x30, 0xD4, 0x69, 0xB3, 0xF9, 0x00, 0x30, +0x50, 0xF8, 0x04, 0x8C, 0x00, 0x2B, 0x06, 0x46, 0xA0, 0xF1, 0x04, 0x05, 0x2F, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x2E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2E, 0x48, 0xD0, 0xF8, 0x00, 0xC0, 0x0C, 0xF1, 0x01, 0x07, +0x07, 0x60, 0x00, 0x2C, 0x47, 0xD0, 0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x23, 0xD0, 0xAC, 0x42, 0x06, 0xD9, 0x37, 0xE0, +0x63, 0x68, 0x1A, 0x19, 0xAA, 0x42, 0x1C, 0xD0, 0xAC, 0x42, 0x26, 0xD8, 0x21, 0x46, 0x24, 0x68, 0x00, 0x2C, 0xF5, 0xD1, +0x0D, 0x60, 0x46, 0xE9, 0x01, 0x48, 0x47, 0xB1, 0x1E, 0x4B, 0xC0, 0xF8, 0x00, 0xC0, 0x1B, 0x68, 0xBC, 0xF1, 0x00, 0x0F, +0x01, 0xD1, 0x03, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, 0xF8, 0x83, 0xA0, 0x42, 0xCD, 0xD8, 0x1A, 0x49, 0x1A, 0x48, 0xC7, 0x22, +0x01, 0xF0, 0x56, 0xFF, 0xC7, 0xE7, 0x43, 0x44, 0x22, 0x68, 0x63, 0x60, 0xE1, 0x18, 0x8A, 0x42, 0xE5, 0xD1, 0xD2, 0xE9, +0x00, 0x21, 0x0B, 0x44, 0x22, 0x60, 0x63, 0x60, 0xDF, 0xE7, 0x05, 0xEB, 0x08, 0x03, 0x9C, 0x42, 0x0D, 0x60, 0xD8, 0xD1, +0x23, 0x68, 0x46, 0xF8, 0x04, 0x3C, 0x52, 0x1B, 0x32, 0x60, 0xD4, 0xE7, 0xD9, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x04, 0xDB, 0x00, 0x23, 0x1D, 0x60, 0xFF, 0xDE, 0x25, 0x60, 0xFF, 0xDE, 0x06, 0x49, 0x07, 0x48, 0xE2, 0x22, +0x01, 0xF0, 0x2E, 0xFF, 0xF4, 0xE7, 0x00, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x18, 0xAC, 0x15, 0x00, 0x3C, 0xAC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xC0, 0x88, 0x40, 0x1A, +0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x2A, 0xB3, 0xF8, 0xB5, 0x53, 0x1E, 0x0F, 0x46, 0x0A, 0x68, 0x01, 0xE0, +0x59, 0x1C, 0x11, 0xD0, 0x32, 0xF8, 0x33, 0x40, 0x84, 0x42, 0x4F, 0xEA, 0xC3, 0x06, 0x02, 0xEB, 0xC3, 0x05, 0x03, 0xF1, +0xFF, 0x33, 0xF3, 0xD1, 0x0B, 0x4B, 0x68, 0x68, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x02, 0xDB, 0xF8, 0xBD, +0x00, 0x20, 0xF8, 0xBD, 0x00, 0x28, 0xFA, 0xD1, 0x06, 0x49, 0x07, 0x48, 0xF4, 0x22, 0x01, 0xF0, 0xF5, 0xFE, 0x3B, 0x68, +0x1E, 0x44, 0x70, 0x68, 0xF8, 0xBD, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x50, 0xAC, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x44, 0x4F, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, +0x0D, 0x46, 0x4F, 0xEA, 0x10, 0x29, 0xC6, 0xB2, 0x3B, 0xDB, 0x40, 0x4B, 0x03, 0xEB, 0x06, 0x16, 0xB3, 0x68, 0x03, 0xEB, +0x49, 0x09, 0x3E, 0x48, 0x2A, 0x46, 0x21, 0x46, 0x01, 0xF0, 0x56, 0xFC, 0xB9, 0xF8, 0x00, 0x30, 0xAB, 0x42, 0x01, 0xD1, +0xBD, 0xE8, 0xF8, 0x83, 0xDF, 0xF8, 0x0C, 0x81, 0x38, 0x4F, 0x39, 0x4E, 0xA9, 0xF8, 0x00, 0x50, 0x19, 0xE0, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x02, 0xD4, 0x72, 0xB6, 0x01, 0x23, 0x33, 0x60, 0x34, 0x4D, 0x35, 0x48, 0x2B, 0x68, 0x01, 0x33, +0x2B, 0x60, 0x00, 0xF0, 0x61, 0xFA, 0x2A, 0x68, 0x53, 0x1E, 0x22, 0xB1, 0x32, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0xB3, 0xF9, 0x41, 0x46, 0x22, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0x40, 0xFE, +0x01, 0x46, 0x00, 0x28, 0xDD, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x0C, 0x2E, 0x23, 0xD8, 0x33, 0xD0, 0x20, 0x4B, 0x03, 0xEB, +0x06, 0x16, 0xF3, 0x89, 0x4B, 0x45, 0x0B, 0xD9, 0xB3, 0x68, 0x03, 0xEB, 0x49, 0x09, 0xB9, 0xF1, 0x00, 0x0F, 0xBA, 0xD1, +0x20, 0x49, 0x21, 0x48, 0xB9, 0x22, 0x01, 0xF0, 0x8B, 0xFE, 0xB4, 0xE7, 0xB4, 0x22, 0x1D, 0x49, 0x1E, 0x48, 0x01, 0xF0, +0x85, 0xFE, 0x3A, 0x68, 0xB3, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xEB, 0x49, 0x09, 0xA7, 0xDA, 0xB9, 0xF1, +0x00, 0x0F, 0xA4, 0xD1, 0xE8, 0xE7, 0x15, 0x49, 0x17, 0x48, 0xB2, 0x22, 0x01, 0xF0, 0x74, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x93, 0xDA, 0x0D, 0x2E, 0x04, 0xD0, 0x0F, 0x49, 0x12, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x68, 0xFE, +0x0C, 0x49, 0x11, 0x48, 0xB3, 0x22, 0x01, 0xF0, 0x63, 0xFE, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC1, 0xDB, +0x81, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, 0xC8, 0xAC, 0x15, 0x00, 0x8C, 0xB6, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x84, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB8, 0xAC, 0x15, 0x00, +0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, 0x41, 0x2D, 0x14, 0x00, +0x70, 0xB5, 0x20, 0x4D, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x10, 0x26, 0xC4, 0xB2, 0x06, 0xDB, +0x1C, 0x4D, 0x24, 0x01, 0x25, 0x44, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x0C, 0x2C, 0x11, 0xD8, 0x21, 0xD0, +0x17, 0x4D, 0x05, 0xEB, 0x04, 0x13, 0x24, 0x01, 0xDB, 0x89, 0xB3, 0x42, 0xF0, 0xD8, 0x25, 0x44, 0x14, 0x49, 0x15, 0x48, +0xD9, 0x22, 0x01, 0xF0, 0x1F, 0xFE, 0xAB, 0x68, 0x33, 0xF8, 0x16, 0x00, 0x70, 0xBD, 0x10, 0x49, 0x11, 0x48, 0xD7, 0x22, +0x01, 0xF0, 0x16, 0xFE, 0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x0D, 0x2C, 0x04, 0xD0, 0x0A, 0x49, +0x0C, 0x48, 0xBB, 0x22, 0x01, 0xF0, 0x0A, 0xFE, 0x07, 0x49, 0x0B, 0x48, 0xD8, 0x22, 0x01, 0xF0, 0x05, 0xFE, 0x2B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD3, 0xDB, 0xC8, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x14, 0xAD, 0x15, 0x00, +0x70, 0x79, 0x15, 0x00, 0x98, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x68, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0x67, 0x4D, 0x68, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0xF0, 0xCF, 0xF9, 0x2B, 0x68, 0x04, 0x46, 0x2B, 0xB1, +0x61, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x00, 0x2B, 0x54, 0xD0, 0x00, 0x2C, 0x39, 0xD0, 0x60, 0x4F, 0xB4, 0xF8, +0x06, 0xA0, 0x3B, 0x68, 0xB4, 0xF8, 0x04, 0x80, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x5F, 0xFA, 0x8A, 0xF6, 0x4F, 0xEA, +0x1A, 0x2A, 0x48, 0xDB, 0xDF, 0xF8, 0x90, 0x91, 0x36, 0x01, 0x59, 0xF8, 0x06, 0x10, 0xB1, 0x44, 0x00, 0x29, 0x52, 0xD0, +0xD9, 0xF8, 0x08, 0x30, 0x33, 0xF8, 0x1A, 0x30, 0x01, 0xEB, 0xC3, 0x01, 0x40, 0x46, 0x8A, 0x88, 0xFF, 0xF7, 0x9C, 0xFE, +0x06, 0x46, 0x00, 0x28, 0x45, 0xD0, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x4E, 0x48, 0x01, 0xF0, 0x31, 0xFB, 0x23, 0x89, +0xE2, 0x88, 0xA0, 0x88, 0x04, 0xF1, 0x0C, 0x01, 0xB0, 0x47, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x7B, 0xD0, 0x00, 0x28, +0x50, 0xD0, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x79, 0xDB, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x3E, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x41, 0x4A, 0x2B, 0x68, 0x52, 0x68, 0x01, 0x33, 0x2B, 0x60, 0x00, 0x2A, +0x40, 0xD0, 0x33, 0xB1, 0x38, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xBD, 0xE8, +0xF0, 0x87, 0x00, 0x2A, 0xA8, 0xD0, 0x62, 0xB6, 0xA6, 0xE7, 0x0C, 0x2E, 0x36, 0xD8, 0x48, 0xD0, 0xDF, 0xF8, 0xF8, 0x90, +0x09, 0xEB, 0x06, 0x13, 0x36, 0x01, 0xDB, 0x89, 0x53, 0x45, 0xAE, 0xD8, 0x32, 0x49, 0x33, 0x48, 0x4F, 0xF4, 0x89, 0x72, +0x01, 0xF0, 0x6C, 0xFD, 0xA7, 0xE7, 0xD9, 0xF8, 0x04, 0x10, 0x69, 0xB1, 0x8A, 0x88, 0x40, 0x46, 0xFF, 0xF7, 0x4C, 0xFE, +0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x06, 0x46, 0x27, 0x48, 0x01, 0xF0, 0xE3, 0xFA, 0x00, 0x2E, 0xAF, 0xD1, 0x05, 0xE0, +0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x23, 0x48, 0x01, 0xF0, 0xDA, 0xFA, 0xE3, 0x88, 0x22, 0x89, 0xA1, 0x88, 0x24, 0x48, +0x01, 0xF0, 0xD4, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFC, 0xAF, 0xE7, 0x4F, 0xF0, 0x00, 0x60, 0x00, 0xF0, 0x74, 0xF8, +0x2B, 0x68, 0xB8, 0xE7, 0x1B, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0x88, 0x72, 0x01, 0xF0, 0x3E, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0x72, 0xAF, 0x0D, 0x2E, 0x04, 0xD0, 0x14, 0x49, 0x18, 0x48, 0xBB, 0x22, 0x01, 0xF0, +0x31, 0xFD, 0x12, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x01, 0xF0, 0x2B, 0xFD, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xAB, 0xDB, 0x5E, 0xE7, 0x12, 0x48, 0x21, 0x46, 0x00, 0xF0, 0xCD, 0xF8, 0x85, 0xE7, 0x09, 0x49, 0x10, 0x48, +0x40, 0xF2, 0x6D, 0x12, 0x01, 0xF0, 0x1A, 0xFD, 0x7E, 0xE7, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x84, 0xB6, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xB4, 0xAB, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x98, 0xAC, 0x15, 0x00, 0xDC, 0xAC, 0x15, 0x00, 0x74, 0xAC, 0x15, 0x00, 0x10, 0x7D, 0x15, 0x00, 0x84, 0xAC, 0x15, 0x00, +0x8C, 0xB6, 0x17, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x14, 0xAD, 0x15, 0x00, 0x00, 0x20, 0x70, 0x47, 0x02, 0x20, 0x70, 0x47, +0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x09, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x09, 0x4A, +0x09, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, 0x18, 0x43, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x03, 0x4B, 0x11, 0x60, +0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x80, 0xB6, 0x17, 0x00, 0x4F, 0xF0, 0x00, 0x50, 0xFF, 0xF7, 0xDC, 0xBF, 0x30, 0xB4, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0A, 0x4A, 0x0A, 0x4D, 0x11, 0x68, 0x2B, 0x68, 0x4C, 0x1C, +0x23, 0xEA, 0x00, 0x00, 0x14, 0x60, 0x28, 0x60, 0x2C, 0xB1, 0x04, 0x4B, 0x11, 0x60, 0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, +0x62, 0xB6, 0x30, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x80, 0xB6, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x18, 0x4E, 0x34, 0x68, 0xDC, 0xB1, 0xDF, 0xF8, 0x68, 0x80, 0x17, 0x4D, 0x17, 0x4F, 0xDF, 0xF8, +0x64, 0xA0, 0xDF, 0xF8, 0x64, 0x90, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB4, 0xFA, 0x84, 0xF4, +0x12, 0xDB, 0x55, 0xF8, 0x34, 0x30, 0x05, 0xEB, 0xC4, 0x04, 0x60, 0x68, 0x98, 0x47, 0x3B, 0x68, 0x34, 0x68, 0xDB, 0x78, +0x1B, 0xB9, 0x00, 0x2C, 0xEB, 0xD1, 0xBD, 0xE8, 0xF0, 0x87, 0xE9, 0xF7, 0x09, 0xFA, 0x00, 0x2C, 0xE5, 0xD1, 0xF8, 0xE7, +0x1D, 0x2C, 0x03, 0xDC, 0x55, 0xF8, 0x34, 0x30, 0x00, 0x2B, 0xE8, 0xD1, 0xDC, 0x22, 0x51, 0x46, 0x48, 0x46, 0x01, 0xF0, +0x7D, 0xFC, 0xE0, 0xE7, 0x80, 0xB6, 0x17, 0x00, 0x70, 0x21, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xE4, 0xAD, 0x15, 0x00, 0x08, 0xB5, 0xFF, 0xF7, 0x35, 0xFC, 0x08, 0x4B, 0x08, 0x49, 0xD8, 0x61, +0x00, 0x22, 0xC3, 0xE9, 0x03, 0x22, 0xC3, 0xE9, 0x01, 0x22, 0xC3, 0xE9, 0x05, 0x22, 0x59, 0x62, 0x4F, 0xF0, 0xFF, 0x30, +0xBD, 0xE8, 0x08, 0x40, 0xFF, 0xF7, 0x8A, 0xBF, 0x80, 0xB6, 0x17, 0x00, 0xD1, 0x31, 0x14, 0x00, 0x00, 0x23, 0xC0, 0xE9, +0x00, 0x33, 0x70, 0x47, 0x38, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, +0x07, 0xDB, 0x2B, 0x68, 0x6B, 0xB1, 0x6B, 0x68, 0x1C, 0x60, 0x00, 0x23, 0x6C, 0x60, 0x23, 0x60, 0x38, 0xBD, 0x00, 0x29, +0xF5, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x48, 0x22, 0x01, 0xF0, 0x3C, 0xFC, 0xEF, 0xE7, 0x00, 0x23, 0x2C, 0x60, 0x6C, 0x60, +0x23, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, 0x04, 0xDB, 0x2B, 0x68, 0x53, 0xB1, 0x23, 0x60, +0x2C, 0x60, 0x38, 0xBD, 0x00, 0x29, 0xF8, 0xD1, 0x05, 0x49, 0x06, 0x48, 0x5F, 0x22, 0x01, 0xF0, 0x1B, 0xFC, 0xF2, 0xE7, +0x6C, 0x60, 0x23, 0x60, 0x2C, 0x60, 0x38, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x14, 0xAE, 0x15, 0x00, +0x03, 0x68, 0x33, 0xB1, 0x42, 0x68, 0x19, 0x68, 0x01, 0x60, 0x9A, 0x42, 0x04, 0xBF, 0x00, 0x22, 0x42, 0x60, 0x18, 0x46, +0x70, 0x47, 0x00, 0xBF, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x0C, 0x46, +0x0B, 0xDB, 0x2B, 0x68, 0x43, 0xB1, 0xA3, 0x42, 0x02, 0xD1, 0x14, 0xE0, 0xA3, 0x42, 0x0C, 0xD0, 0x1A, 0x46, 0x1B, 0x68, +0x00, 0x2B, 0xF9, 0xD1, 0x38, 0xBD, 0x00, 0x28, 0xF1, 0xD1, 0x0C, 0x49, 0x0C, 0x48, 0x84, 0x22, 0x01, 0xF0, 0xE8, 0xFB, +0xEB, 0xE7, 0x6B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x23, 0x68, 0x13, 0x60, 0x38, 0xBD, 0x6B, 0x68, 0x22, 0x68, 0x2A, 0x60, +0xA3, 0x42, 0xEB, 0xD1, 0x00, 0x23, 0x6B, 0x60, 0x38, 0xBD, 0x6A, 0x60, 0xF2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x28, 0xAE, 0x15, 0x00, 0x03, 0x68, 0x2B, 0xB1, 0x00, 0x20, 0x1B, 0x68, 0x01, 0x30, 0x00, 0x2B, +0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x41, 0xD0, 0xE9, 0x00, 0x47, 0x80, 0x46, 0x0D, 0x46, +0x16, 0x46, 0x1F, 0xB1, 0x39, 0x46, 0x28, 0x46, 0x90, 0x47, 0x88, 0xB1, 0x00, 0x27, 0x24, 0xB9, 0x1A, 0xE0, 0x23, 0x68, +0x27, 0x46, 0x8B, 0xB1, 0x1C, 0x46, 0x21, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0xF6, 0xD0, 0x2C, 0x60, 0x67, 0xB9, +0xC8, 0xF8, 0x00, 0x50, 0xBD, 0xE8, 0xF0, 0x81, 0x3D, 0x60, 0xC8, 0xF8, 0x04, 0x50, 0x28, 0x60, 0xBD, 0xE8, 0xF0, 0x81, +0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, 0x3D, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x23, 0xC8, 0xF8, 0x04, 0x50, 0x2B, 0x60, +0xEA, 0xE7, 0x00, 0xBF, 0x03, 0x68, 0xB9, 0xB1, 0xCB, 0xB1, 0x8B, 0x42, 0x10, 0xB4, 0x04, 0x46, 0x02, 0xD1, 0x07, 0xE0, +0x99, 0x42, 0x05, 0xD0, 0x1B, 0x68, 0x00, 0x2B, 0xFA, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x63, 0x68, 0x08, 0x68, +0x10, 0x60, 0x8B, 0x42, 0x0A, 0x60, 0xF6, 0xD1, 0x62, 0x60, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, +0x49, 0xBF, 0x70, 0x47, 0x81, 0xB1, 0x03, 0x68, 0x8B, 0x42, 0x0A, 0xD0, 0x2B, 0xB1, 0x18, 0x68, 0x88, 0x42, 0x03, 0xD0, +0x03, 0x46, 0x00, 0x2B, 0xF9, 0xD1, 0x70, 0x47, 0x11, 0x60, 0x1A, 0x60, 0x70, 0x47, 0x11, 0x46, 0xFF, 0xF7, 0x36, 0xBF, +0x11, 0x46, 0xFF, 0xF7, 0x0F, 0xBF, 0x00, 0xBF, 0x0B, 0x46, 0x09, 0x68, 0x99, 0xB1, 0x02, 0x46, 0x00, 0x68, 0x48, 0xB1, +0x10, 0xB4, 0x54, 0x68, 0x58, 0x68, 0x21, 0x60, 0x50, 0x60, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, 0x1A, 0x60, 0x70, 0x47, +0x93, 0xE8, 0x03, 0x00, 0x82, 0xE8, 0x03, 0x00, 0x00, 0x22, 0x1A, 0x60, 0x70, 0x47, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x4F, +0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x0D, 0x46, 0x14, 0x46, 0x0A, 0xDB, 0x25, 0xB3, 0x23, 0x68, +0x2B, 0x60, 0x73, 0x68, 0xA3, 0x42, 0x4F, 0xF0, 0x00, 0x03, 0x08, 0xBF, 0x75, 0x60, 0x23, 0x60, 0xF8, 0xBD, 0xE0, 0xB1, +0xB5, 0xB1, 0x2B, 0x68, 0xA3, 0x42, 0x0A, 0xD0, 0x13, 0x49, 0x14, 0x48, 0x40, 0xF2, 0x75, 0x12, 0x01, 0xF0, 0x2A, 0xFB, +0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x00, 0x2C, 0xE3, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, +0xBB, 0x72, 0x01, 0xF0, 0x1D, 0xFB, 0xDB, 0xE7, 0x00, 0x2C, 0xF6, 0xD0, 0x23, 0x68, 0x33, 0x60, 0xD9, 0xE7, 0x07, 0x49, +0x09, 0x48, 0x4F, 0xF4, 0xBA, 0x72, 0x01, 0xF0, 0x11, 0xFB, 0x3B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xD7, 0xDB, +0xCA, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x38, 0xAE, 0x15, 0x00, 0x74, 0xAE, 0x15, 0x00, +0x28, 0xAE, 0x15, 0x00, 0x81, 0xB1, 0x10, 0xB4, 0x08, 0x4C, 0x01, 0x44, 0x10, 0xF8, 0x01, 0x3B, 0x83, 0xEA, 0x12, 0x63, +0x81, 0x42, 0x54, 0xF8, 0x23, 0x30, 0x83, 0xEA, 0x02, 0x22, 0xF5, 0xD1, 0x10, 0x46, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x10, 0x46, 0x70, 0x47, 0x84, 0xAE, 0x15, 0x00, 0xF8, 0xB5, 0x0F, 0x18, 0xB8, 0x42, 0xBC, 0x46, 0x06, 0xD3, 0x1D, 0xE0, +0x44, 0x78, 0x2E, 0x78, 0x02, 0x34, 0xFF, 0x2E, 0x20, 0x44, 0x06, 0xD0, 0x46, 0x1C, 0xB7, 0x42, 0x05, 0x46, 0xF5, 0xD8, +0x00, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x87, 0x42, 0xFA, 0xD3, 0x1C, 0x80, 0x00, 0x2D, 0xF7, 0xD0, 0xEE, 0x1C, 0x66, 0x45, +0xF4, 0xD8, 0xAE, 0x78, 0x96, 0x42, 0xF2, 0xD0, 0x0C, 0x1B, 0x84, 0x45, 0xA1, 0xB2, 0x01, 0xD9, 0x0F, 0x18, 0xE7, 0xE7, +0x06, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE5, 0xDA, 0x84, 0x45, 0xE3, 0xD0, 0x03, 0x49, 0x04, 0x48, +0x7F, 0x22, 0x01, 0xF0, 0xB9, 0xFA, 0xDD, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, +0x2D, 0xE9, 0xF8, 0x43, 0x01, 0xEB, 0x00, 0x08, 0x40, 0x45, 0xC6, 0x46, 0x2D, 0xD2, 0x02, 0xF1, 0x05, 0x0C, 0xC2, 0xF1, +0x02, 0x07, 0x05, 0xE0, 0x44, 0x78, 0x35, 0x78, 0x02, 0x34, 0xDD, 0x2D, 0x20, 0x44, 0x07, 0xD0, 0x45, 0x1C, 0xA8, 0x45, +0x06, 0x46, 0xF5, 0xD8, 0x00, 0x26, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x45, 0xF9, 0xD3, 0x1C, 0x80, 0x00, 0x2E, +0xF6, 0xD0, 0xF5, 0x1D, 0xAE, 0x45, 0xF3, 0xD3, 0x15, 0x46, 0x01, 0xE0, 0x65, 0x45, 0xF0, 0xD0, 0x05, 0xEB, 0x06, 0x08, +0x15, 0xF8, 0x01, 0x9B, 0x18, 0xF8, 0x07, 0x80, 0xC1, 0x45, 0xF5, 0xD0, 0x0C, 0x1B, 0x86, 0x45, 0xA1, 0xB2, 0x02, 0xD9, +0x01, 0xEB, 0x00, 0x08, 0xDC, 0xE7, 0x07, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xDA, 0xDA, 0x86, 0x45, +0xD8, 0xD0, 0x04, 0x49, 0x04, 0x48, 0xB4, 0x22, 0x01, 0xF0, 0x70, 0xFA, 0xD2, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x84, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x70, 0xB4, 0x03, 0xE0, +0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x10, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x01, 0x2E, 0x03, 0xEB, 0x00, 0x05, +0xF4, 0xD1, 0xA9, 0x42, 0x07, 0xD3, 0x38, 0xB1, 0x0A, 0x2B, 0x04, 0xD8, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, +0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x17, 0xD9, +0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, 0xA3, 0x1C, 0x32, 0x2E, +0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x70, 0x70, 0xBC, +0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, +0x70, 0xB4, 0x03, 0xE0, 0x73, 0x1C, 0x99, 0x42, 0x30, 0x46, 0x10, 0xD9, 0x45, 0x78, 0x04, 0x78, 0xAB, 0x1C, 0x1E, 0x18, +0x00, 0x2C, 0xF5, 0xD1, 0xB1, 0x42, 0x05, 0xD3, 0x10, 0xB1, 0x22, 0x2B, 0x02, 0xD8, 0x15, 0x70, 0x70, 0xBC, 0x70, 0x47, +0x20, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, +0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, +0xA3, 0x1C, 0x07, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x07, 0x2B, 0x02, 0xD9, +0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, +0x99, 0x42, 0x17, 0xD9, 0x70, 0xB4, 0x03, 0xE0, 0x6B, 0x1C, 0x99, 0x42, 0x28, 0x46, 0x0E, 0xD9, 0x44, 0x78, 0x06, 0x78, +0xA3, 0x1C, 0x30, 0x2E, 0x03, 0xEB, 0x00, 0x05, 0xF4, 0xD1, 0xA9, 0x42, 0x05, 0xD3, 0x28, 0xB1, 0x13, 0x2B, 0x02, 0xD9, +0x14, 0x70, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, +0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, +0x02, 0x33, 0x25, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, +0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, +0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, +0x06, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1A, 0xD9, 0x30, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, +0x20, 0x46, 0x11, 0xD9, 0x43, 0x78, 0x05, 0x78, 0x02, 0x33, 0x3E, 0x2D, 0x03, 0xEB, 0x00, 0x04, 0xF4, 0xD1, 0xA1, 0x42, +0x08, 0xD3, 0x40, 0xB1, 0xA3, 0xF1, 0x03, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, +0x00, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x2B, 0xD9, +0x30, 0xB4, 0x03, 0xE0, 0x18, 0x46, 0x01, 0x33, 0x99, 0x42, 0x16, 0xD9, 0x44, 0x78, 0x05, 0x78, 0xA3, 0x1C, 0xC4, 0x2D, +0x03, 0x44, 0xF5, 0xD1, 0x99, 0x42, 0x0E, 0xD3, 0x70, 0xB1, 0x02, 0x30, 0x04, 0x44, 0x07, 0xE0, 0x43, 0x78, 0x05, 0x78, +0x02, 0x33, 0xC2, 0x2D, 0x03, 0xEB, 0x00, 0x01, 0x06, 0xD0, 0x08, 0x46, 0x43, 0x1C, 0x9C, 0x42, 0xF4, 0xD8, 0x00, 0x20, +0x30, 0xBC, 0x70, 0x47, 0x8C, 0x42, 0xFA, 0xD3, 0x00, 0x28, 0xF9, 0xD0, 0xA3, 0xF1, 0x05, 0x03, 0xB3, 0xFA, 0x83, 0xF3, +0x5B, 0x09, 0x30, 0xBC, 0x13, 0x70, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, +0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x03, 0x2C, +0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, +0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, +0x02, 0x33, 0x4C, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x12, 0x2B, 0x18, 0xBF, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, +0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, +0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2A, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, +0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, +0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC7, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, +0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, +0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x20, 0x2C, 0x03, 0xEB, 0x00, 0x02, +0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x03, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, +0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x36, 0x2C, +0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x05, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xB5, 0x83, 0xB0, +0x06, 0x4A, 0x0D, 0xF1, 0x06, 0x03, 0xFF, 0xF7, 0xC1, 0xFD, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x1A, 0x2B, 0x18, 0xBF, +0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x98, 0xB2, 0x15, 0x00, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, +0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x2D, 0x2C, +0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x1C, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, +0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, +0x02, 0x33, 0x47, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x06, 0x2B, 0x38, 0xBF, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, +0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x1D, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x63, 0x1C, 0x99, 0x42, 0x20, 0x46, 0x13, 0xD9, +0x43, 0x78, 0x02, 0x78, 0x02, 0x33, 0x1C, 0x18, 0x00, 0x2A, 0xF5, 0xD1, 0xA1, 0x42, 0x03, 0xD2, 0x10, 0x46, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x28, 0xFA, 0xD0, 0x06, 0x2B, 0x38, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, +0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x53, 0x2C, +0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, +0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, +0x02, 0x33, 0x55, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x02, 0x2B, 0x08, 0xBF, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, +0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, +0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xBF, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, +0x0E, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, 0x06, 0x03, 0x23, 0x22, 0xFF, 0xF7, 0xB2, 0xFC, +0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x18, 0x02, 0x21, 0x2A, 0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, +0x02, 0xB0, 0x10, 0xBD, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, 0x53, 0x1C, 0x99, 0x42, +0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0x3D, 0x2C, 0x03, 0xEB, 0x00, 0x02, 0xF4, 0xD1, 0x91, 0x42, +0x06, 0xD3, 0x30, 0xB1, 0x18, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x44, 0x43, 0x1C, 0x99, 0x42, 0x19, 0xD9, 0x10, 0xB4, 0x03, 0xE0, +0x53, 0x1C, 0x99, 0x42, 0x10, 0x46, 0x0F, 0xD9, 0x43, 0x78, 0x04, 0x78, 0x02, 0x33, 0xC0, 0x2C, 0x03, 0xEB, 0x00, 0x02, +0xF4, 0xD1, 0x91, 0x42, 0x06, 0xD3, 0x30, 0xB1, 0x07, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, +0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, +0x06, 0x03, 0x24, 0x22, 0xFF, 0xF7, 0x5E, 0xFC, 0x40, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0xA3, 0xF1, 0x09, 0x02, 0x09, 0x2A, +0x9A, 0xBF, 0x03, 0x3B, 0x23, 0x70, 0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, +0x26, 0x22, 0xFF, 0xF7, 0x4B, 0xFC, 0x20, 0xB1, 0xBD, 0xF8, 0x06, 0x30, 0x10, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, +0x5D, 0xF8, 0x04, 0xFB, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x06, 0x03, 0x25, 0x22, 0xFF, 0xF7, 0x3B, 0xFC, 0x20, 0xB1, +0xBD, 0xF8, 0x06, 0x30, 0x04, 0x2B, 0x18, 0xBF, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x43, 0x79, 0x02, 0x79, +0x58, 0x00, 0x40, 0xEA, 0xD2, 0x10, 0x80, 0x05, 0x70, 0x47, 0x00, 0xBF, 0x43, 0x79, 0x07, 0x48, 0x83, 0xEA, 0x13, 0x13, +0x5B, 0x01, 0xC1, 0xF3, 0x08, 0x01, 0x03, 0xF4, 0xF0, 0x73, 0x0B, 0x44, 0x00, 0xEA, 0x83, 0x50, 0x40, 0xF4, 0x7C, 0x10, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x28, 0x08, 0xDA, 0x10, 0xF1, 0x6D, 0x0F, 0x01, 0xDA, 0x00, 0x20, +0x70, 0x47, 0x6E, 0x30, 0x40, 0x00, 0xC0, 0xB2, 0x70, 0x47, 0xDC, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, +0x1D, 0x46, 0x95, 0xB0, 0x90, 0x46, 0xDD, 0xF8, 0x78, 0xB0, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0x91, 0x07, 0x46, 0x00, 0x28, +0x00, 0xF0, 0x7F, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x91, 0x83, 0x00, 0x24, 0xCD, 0xE9, 0x00, 0x44, 0x03, 0x9E, 0x02, 0x94, +0xA1, 0x46, 0xA2, 0x46, 0xA2, 0xF1, 0x20, 0x03, 0x58, 0x2B, 0x5A, 0xD8, 0xDF, 0xE8, 0x13, 0xF0, 0x35, 0x01, 0x59, 0x00, +0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x34, 0x03, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x17, 0x03, 0x35, 0x01, +0x59, 0x00, 0x35, 0x01, 0x36, 0x03, 0x59, 0x00, 0x12, 0x01, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, +0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, +0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, +0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, +0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, +0x59, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x59, 0x00, +0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x10, 0x01, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, +0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x6E, 0x00, 0x59, 0x00, 0x59, 0x00, 0x6E, 0x00, 0xA2, 0xF1, 0x31, 0x01, 0x08, 0x29, +0x40, 0xF2, 0xE2, 0x80, 0x00, 0x21, 0x9E, 0x48, 0x00, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x01, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, +0x00, 0xF2, 0xD8, 0x83, 0xDF, 0xE8, 0x0A, 0xF0, 0x75, 0x5B, 0x45, 0x9A, 0x70, 0x8E, 0x80, 0x06, 0x07, 0x21, 0xEE, 0xE7, +0xA2, 0xF1, 0x41, 0x03, 0x37, 0x2B, 0x00, 0xF2, 0x05, 0x82, 0xDF, 0xE8, 0x13, 0xF0, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, +0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x54, 0x02, +0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, +0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x05, 0x02, +0x29, 0x01, 0x5E, 0x01, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0xA3, 0x01, 0x03, 0x02, 0x03, 0x02, +0x03, 0x02, 0x54, 0x02, 0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x03, 0x02, 0x03, 0x02, 0xF8, 0x01, 0x03, 0x02, 0x29, 0x01, +0x03, 0x02, 0x03, 0x02, 0x29, 0x01, 0x10, 0x2B, 0x00, 0xF2, 0xCA, 0x80, 0xDF, 0xE8, 0x13, 0xF0, 0xD2, 0x00, 0xC8, 0x00, +0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xD9, 0x00, +0xC8, 0x00, 0xE0, 0x00, 0xC8, 0x00, 0xC8, 0x00, 0xC1, 0x00, 0x00, 0x23, 0x00, 0x93, 0x02, 0x93, 0x4F, 0xF0, 0xFF, 0x33, +0x01, 0x93, 0x4F, 0xF0, 0x01, 0x0A, 0x15, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x7F, 0xF4, 0x28, 0xAF, 0x00, 0x2E, 0x62, 0xD0, +0x00, 0x23, 0x3B, 0x70, 0x20, 0x46, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x01, 0x93, 0x4F, 0xF0, 0x04, 0x0A, +0xED, 0xE7, 0x2E, 0xB1, 0xA0, 0x45, 0x9C, 0xBF, 0x07, 0xF8, 0x01, 0x2B, 0x06, 0xF1, 0xFF, 0x36, 0x01, 0x34, 0x4F, 0xF0, +0x00, 0x0A, 0xE2, 0xE7, 0x68, 0x2A, 0x7B, 0xD0, 0x6C, 0x2A, 0x3F, 0xD0, 0x57, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xC0, 0xF2, 0x92, 0x82, 0x4F, 0xF0, 0x06, 0x0A, 0xD4, 0xE7, 0x2A, 0x2A, 0x61, 0xD0, 0x01, 0x9B, 0x30, 0x3A, +0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x01, 0x93, 0x4F, 0xF0, 0x05, 0x0A, 0xC8, 0xE7, 0x2A, 0x2A, 0x5B, 0xD0, +0x02, 0x9B, 0x30, 0x3A, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x43, 0x03, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0xBC, 0xE7, +0x06, 0x21, 0x4C, 0xE7, 0x44, 0x4B, 0x03, 0xEB, 0xCA, 0x0A, 0x9A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, +0x25, 0x83, 0x01, 0xA3, 0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xBB, 0x40, 0x14, 0x00, +0xD9, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, +0x00, 0x9B, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x97, 0xE7, 0x05, 0x21, 0x27, 0xE7, 0x03, 0x9B, +0x00, 0x2B, 0x9B, 0xD0, 0x20, 0x46, 0x07, 0xF8, 0x01, 0x6C, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2D, 0x49, 0x01, 0xEB, +0xCA, 0x0A, 0x9A, 0xF8, 0x04, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0xF7, 0x82, 0x01, 0xA1, 0x51, 0xF8, 0x2A, 0xF0, +0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0x2F, 0x3F, 0x14, 0x00, 0xDD, 0x3F, 0x14, 0x00, 0x85, 0x3F, 0x14, 0x00, +0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x5B, 0xF8, 0x04, 0x3B, 0x01, 0x93, 0x4F, 0xF0, +0x05, 0x0A, 0x6A, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x93, 0x4F, 0xF0, 0x03, 0x0A, 0x64, 0xE7, 0x00, 0x9B, 0x43, 0xF0, +0x01, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x06, 0x0A, 0x5D, 0xE7, 0x14, 0x46, 0x00, 0x2A, 0x3F, 0xF4, 0x63, 0xAF, 0x03, 0x90, +0x7D, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x50, 0xE7, 0x10, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x82, 0x4F, 0xF0, 0x02, 0x0A, 0x46, 0xE7, 0x00, 0x9B, 0x43, 0xF0, +0x10, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x3F, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x08, 0x03, 0x00, 0x93, 0x4F, 0xF0, +0x02, 0x0A, 0x38, 0xE7, 0x00, 0x9B, 0x43, 0xF0, 0x20, 0x03, 0x00, 0x93, 0x4F, 0xF0, 0x02, 0x0A, 0x31, 0xE7, 0x00, 0xBF, +0x24, 0xB3, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x9B, 0x9B, 0x07, 0x00, 0xF1, 0x94, 0x81, 0x00, 0x9B, 0xD8, 0x07, +0x40, 0xF1, 0x90, 0x81, 0x64, 0x2A, 0x00, 0xF0, 0x32, 0x82, 0x5B, 0xF8, 0x04, 0x1B, 0x58, 0x3A, 0x89, 0xB2, 0x20, 0x2A, +0x00, 0xF2, 0x24, 0x82, 0xDF, 0xE8, 0x12, 0xF0, 0x5A, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, +0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x4E, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, +0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x36, 0x02, 0x22, 0x02, +0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x72, 0x00, 0x22, 0x02, 0x22, 0x02, 0x69, 0x02, 0x02, 0x9B, 0x59, 0x1E, 0x5B, 0xF8, +0x04, 0x3B, 0x8D, 0xF8, 0x10, 0x30, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x01, 0x23, 0x00, 0x28, 0x70, 0xD1, +0x00, 0x98, 0x80, 0x06, 0x40, 0xF1, 0x15, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0xEA, 0x81, 0x10, 0x46, 0x02, 0xEB, 0x03, 0x09, +0xA4, 0xEB, 0x02, 0x0E, 0x09, 0xE0, 0xE0, 0x45, 0x04, 0xD8, 0x07, 0x78, 0x02, 0xF8, 0x01, 0x7B, 0x01, 0x3E, 0x17, 0x46, +0x01, 0x30, 0x48, 0x45, 0x07, 0xD0, 0x00, 0xEB, 0x0E, 0x0C, 0x3A, 0x46, 0x00, 0x2E, 0xF0, 0xD1, 0x01, 0x30, 0x48, 0x45, +0xF4, 0xD1, 0x23, 0x44, 0x00, 0x29, 0x40, 0xF3, 0xCA, 0x81, 0xCC, 0x18, 0x20, 0x21, 0x08, 0xE0, 0x98, 0x45, 0x03, 0xD8, +0x02, 0xF8, 0x01, 0x1B, 0x01, 0x3E, 0x17, 0x46, 0x01, 0x33, 0xA3, 0x42, 0x05, 0xD0, 0x3A, 0x46, 0x00, 0x2E, 0xF3, 0xD1, +0x01, 0x33, 0xA3, 0x42, 0xF6, 0xD1, 0x4F, 0xF0, 0x07, 0x0A, 0xB2, 0xE6, 0x00, 0x9B, 0x99, 0x07, 0x03, 0xD4, 0x00, 0x9B, +0xDA, 0x07, 0x00, 0xF1, 0xBC, 0x81, 0x5B, 0xF8, 0x04, 0x1B, 0x00, 0x29, 0xC0, 0xF2, 0xBE, 0x81, 0xDF, 0xF8, 0x5C, 0xA4, +0x00, 0x23, 0x0D, 0xF1, 0x50, 0x0E, 0xAA, 0xFB, 0x01, 0x2C, 0x4F, 0xEA, 0xDC, 0x0C, 0x0C, 0xEB, 0x8C, 0x00, 0xA1, 0xEB, +0x40, 0x00, 0x89, 0x46, 0x30, 0x30, 0xB9, 0xF1, 0x09, 0x0F, 0x72, 0x46, 0x61, 0x46, 0x0E, 0xF8, 0x01, 0x0D, 0x18, 0x46, +0x03, 0xF1, 0x01, 0x03, 0xEB, 0xD8, 0x00, 0x99, 0x09, 0x06, 0x00, 0xF1, 0x9E, 0x81, 0x00, 0x99, 0x09, 0x07, 0x40, 0xF1, +0xE7, 0x81, 0x83, 0x1C, 0x2B, 0x20, 0x0E, 0xF8, 0x01, 0x0C, 0x00, 0x98, 0x02, 0x99, 0x00, 0xF0, 0x40, 0x00, 0x02, 0x3A, +0xC9, 0x1A, 0x00, 0x28, 0x8E, 0xD0, 0x00, 0x29, 0x14, 0xDD, 0x0C, 0x44, 0x4F, 0xF0, 0x30, 0x0E, 0x08, 0xE0, 0xE0, 0x45, +0x03, 0xD8, 0x00, 0xF8, 0x01, 0xEB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x39, 0x00, 0xF0, 0xB0, 0x80, 0xA4, 0xEB, 0x01, 0x0C, +0x38, 0x46, 0x00, 0x2E, 0xF1, 0xD1, 0x01, 0x39, 0xF5, 0xD1, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0x7C, 0xAF, 0x91, 0x46, +0xA7, 0xE7, 0x5B, 0xF8, 0x04, 0x2B, 0x00, 0x2A, 0x40, 0xF0, 0x2C, 0x81, 0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, +0x00, 0x23, 0x65, 0xE7, 0x4A, 0x46, 0xF7, 0xE7, 0x5B, 0xF8, 0x04, 0x3B, 0x02, 0x9A, 0xDF, 0xF8, 0xB0, 0xE3, 0x9C, 0x46, +0x1C, 0xF8, 0x01, 0x3B, 0x00, 0x2A, 0x00, 0xF0, 0x09, 0x81, 0x19, 0x11, 0x15, 0x2A, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, +0x01, 0x10, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x10, 0x28, 0xBF, 0x15, 0x22, 0x02, 0xEB, 0x42, 0x01, 0x01, 0x3A, +0x8D, 0xF8, 0x11, 0x30, 0x01, 0xF1, 0xFF, 0x33, 0xC1, 0xF1, 0x01, 0x01, 0x1D, 0xD0, 0x0C, 0xEB, 0x02, 0x0A, 0x0D, 0xF1, +0x13, 0x02, 0x1C, 0xF0, 0x03, 0x0F, 0x1C, 0xF8, 0x01, 0x0B, 0x4F, 0xEA, 0x20, 0x19, 0x00, 0xF0, 0x0F, 0x00, 0x1E, 0xF8, +0x09, 0x90, 0x82, 0xF8, 0x00, 0x90, 0x1E, 0xF8, 0x00, 0x00, 0x50, 0x70, 0x0C, 0xBF, 0x4F, 0xF0, 0x3A, 0x09, 0x4F, 0xF0, +0x2E, 0x09, 0xE2, 0x45, 0x02, 0xF8, 0x01, 0x9C, 0x02, 0xF1, 0x03, 0x02, 0xE5, 0xD1, 0x00, 0x9A, 0x02, 0xF0, 0x40, 0x02, +0x00, 0x2A, 0x40, 0xF0, 0x69, 0x81, 0x00, 0x98, 0x02, 0x92, 0x80, 0x06, 0x04, 0xAA, 0x3F, 0xF5, 0x1F, 0xAF, 0x00, 0x2B, +0x7F, 0xF4, 0x1F, 0xAF, 0xA1, 0xE7, 0x5B, 0xF8, 0x04, 0x1B, 0xDF, 0xF8, 0x14, 0xE3, 0x8C, 0x46, 0x4F, 0xF0, 0x3A, 0x09, +0x1C, 0xF8, 0x06, 0x3B, 0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, +0x11, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x01, 0x31, 0x04, 0xAB, 0x11, 0xF8, 0x01, 0x2B, 0x83, 0xF8, 0x02, 0x90, 0x10, 0x11, +0x02, 0xF0, 0x0F, 0x02, 0x1E, 0xF8, 0x00, 0x00, 0x1E, 0xF8, 0x02, 0x20, 0xD8, 0x70, 0x8C, 0x45, 0x1A, 0x71, 0x03, 0xF1, +0x03, 0x03, 0xEE, 0xD1, 0x02, 0x9B, 0xA3, 0xF1, 0x11, 0x01, 0x00, 0x9B, 0x04, 0xAA, 0x03, 0xF0, 0x40, 0x00, 0x11, 0x23, +0xE4, 0xE6, 0x00, 0x29, 0x7F, 0xF7, 0x6C, 0xAF, 0x21, 0x44, 0x4F, 0xF0, 0x20, 0x0C, 0x08, 0xE0, 0xA0, 0x45, 0x03, 0xD8, +0x00, 0xF8, 0x01, 0xCB, 0x01, 0x3E, 0x07, 0x46, 0x01, 0x34, 0xA1, 0x42, 0x05, 0xD0, 0x38, 0x46, 0x00, 0x2E, 0xF3, 0xD1, +0x01, 0x34, 0xA1, 0x42, 0xF6, 0xD1, 0x0C, 0x46, 0x00, 0x21, 0x00, 0x2B, 0x7F, 0xF4, 0xD3, 0xAE, 0x55, 0xE7, 0x04, 0x23, +0x9A, 0x49, 0x01, 0xEB, 0xCA, 0x0A, 0x1A, 0xF8, 0x03, 0xA0, 0xBA, 0xF1, 0x07, 0x0F, 0x00, 0xF2, 0x1F, 0x81, 0x01, 0xA3, +0x53, 0xF8, 0x2A, 0xF0, 0x8F, 0x3F, 0x14, 0x00, 0x5B, 0x3F, 0x14, 0x00, 0xC9, 0x40, 0x14, 0x00, 0xD9, 0x3F, 0x14, 0x00, +0x85, 0x3F, 0x14, 0x00, 0xC1, 0x3F, 0x14, 0x00, 0xA5, 0x3F, 0x14, 0x00, 0xB1, 0x3E, 0x14, 0x00, 0x01, 0x23, 0xE1, 0xE7, +0x02, 0x21, 0x26, 0xE5, 0x58, 0x3A, 0x5B, 0xF8, 0x04, 0x1B, 0x20, 0x2A, 0x00, 0xF2, 0x98, 0x80, 0x01, 0xA3, 0x53, 0xF8, +0x22, 0xF0, 0x00, 0xBF, 0xED, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, +0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, +0x7D, 0x45, 0x14, 0x00, 0xD5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x17, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, +0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, +0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, +0xA5, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, +0x1D, 0x42, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x7D, 0x45, 0x14, 0x00, 0x0B, 0x46, 0x14, 0x00, 0x03, 0x9E, 0x14, 0x46, +0x4A, 0xE5, 0x64, 0x49, 0x64, 0x48, 0x4F, 0xF4, 0xA2, 0x72, 0x00, 0xF0, 0x49, 0xFB, 0x4F, 0xF0, 0x06, 0x0A, 0x3C, 0xE5, +0x1A, 0x11, 0x03, 0xF0, 0x0F, 0x03, 0x1E, 0xF8, 0x02, 0x20, 0x1E, 0xF8, 0x03, 0x30, 0x8D, 0xF8, 0x10, 0x20, 0x8D, 0xF8, +0x11, 0x30, 0x6F, 0xF0, 0x2E, 0x01, 0x2F, 0x23, 0x0F, 0x22, 0xFC, 0xE6, 0x13, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x97, 0x80, +0x01, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0xCC, 0xAE, 0x01, 0x9B, 0x11, 0x46, 0xC2, 0xF1, 0x01, 0x00, 0x00, 0x2B, 0x00, 0xEB, +0x01, 0x0C, 0x0F, 0xDD, 0x11, 0xF8, 0x01, 0xEF, 0x01, 0x3B, 0xBE, 0xF1, 0x00, 0x0F, 0x10, 0xD0, 0x00, 0x2B, 0xF3, 0xD1, +0x02, 0x99, 0x00, 0x98, 0x01, 0x93, 0x63, 0x46, 0xC9, 0x1A, 0x00, 0xF0, 0x40, 0x00, 0x1F, 0xE6, 0x00, 0xEB, 0x01, 0x0C, +0x11, 0xF8, 0x01, 0xEF, 0xBE, 0xF1, 0x00, 0x0F, 0xE4, 0xD1, 0x01, 0x93, 0x63, 0x46, 0x02, 0x99, 0x00, 0x98, 0xC9, 0x1A, +0x00, 0xF0, 0x40, 0x00, 0x10, 0xE6, 0x1C, 0x46, 0x4F, 0xF0, 0x07, 0x0A, 0xF9, 0xE4, 0x23, 0x46, 0x91, 0x46, 0x2B, 0xE6, +0x00, 0x9B, 0x02, 0x99, 0x03, 0xF0, 0x40, 0x00, 0x14, 0xAA, 0x00, 0x23, 0x02, 0xE6, 0x5B, 0xF8, 0x04, 0x1B, 0x09, 0xB2, +0x41, 0xE6, 0x83, 0x1C, 0x2D, 0x20, 0x64, 0xE6, 0x00, 0x9B, 0x43, 0xF0, 0x80, 0x03, 0x49, 0x42, 0x00, 0x93, 0x3B, 0xE6, +0x00, 0x9B, 0x43, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x08, 0x23, 0x40, 0x20, 0x02, 0x93, 0xDF, 0xF8, 0xD0, 0xC0, 0x14, 0xAA, +0x01, 0xF0, 0x0F, 0x03, 0x09, 0x09, 0x1C, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, +0xF4, 0xD1, 0x02, 0x99, 0xC9, 0x1A, 0xDD, 0xE5, 0x14, 0xAA, 0x01, 0xF0, 0x01, 0x03, 0x30, 0x33, 0x02, 0xF8, 0x01, 0x3D, +0x49, 0x08, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF5, 0xD1, 0xBA, 0xE7, 0xDF, 0xF8, 0x90, 0xE0, 0x14, 0xAA, 0x01, 0xF0, +0x0F, 0x03, 0x09, 0x09, 0x1E, 0xF8, 0x03, 0x30, 0x02, 0xF8, 0x01, 0x3D, 0x14, 0xAB, 0xA3, 0xEB, 0x02, 0x03, 0xF4, 0xD1, +0xAB, 0xE7, 0x00, 0x9B, 0x03, 0xF0, 0x40, 0x00, 0xCF, 0xE7, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0x11, 0x12, 0x00, 0xF0, +0xAF, 0xFA, 0x4F, 0xF0, 0x02, 0x0A, 0xA2, 0xE4, 0x00, 0x22, 0x02, 0x92, 0x04, 0xAA, 0xBA, 0xE5, 0x00, 0x99, 0xC9, 0x06, +0x06, 0xD4, 0x02, 0x98, 0xC1, 0x1A, 0x00, 0x98, 0x72, 0x46, 0x00, 0xF0, 0x40, 0x00, 0xA7, 0xE5, 0x83, 0x1C, 0x20, 0x20, +0x0D, 0xE6, 0x00, 0x99, 0x01, 0xF0, 0x40, 0x00, 0x02, 0x99, 0x9F, 0xE5, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xBF, 0xF6, 0x86, 0xAC, 0x04, 0x49, 0x04, 0x48, 0x4F, 0xF4, 0x12, 0x72, 0x00, 0xF0, 0x89, 0xFA, 0x7E, 0xE4, +0x24, 0xB3, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0xCD, 0xCC, 0xCC, 0xCC, +0x10, 0xB3, 0x15, 0x00, 0xFC, 0xB2, 0x15, 0x00, 0x0F, 0xB4, 0x2D, 0xE9, 0xF0, 0x47, 0x21, 0x4E, 0xD6, 0xF8, 0x04, 0x31, +0x82, 0xB0, 0xFB, 0xB1, 0x0A, 0x9C, 0xDF, 0xF8, 0x80, 0x80, 0xDF, 0xF8, 0x80, 0xA0, 0xDF, 0xF8, 0x80, 0x90, 0xA7, 0x1C, +0x20, 0x46, 0x14, 0xF8, 0x01, 0x5B, 0x29, 0x06, 0xA5, 0xF1, 0x80, 0x02, 0x0A, 0xD5, 0x88, 0x2D, 0x13, 0xD8, 0xD6, 0xF8, +0x00, 0x31, 0xDB, 0x43, 0xD3, 0x40, 0xDB, 0x07, 0x08, 0xD4, 0xA7, 0x42, 0x20, 0x46, 0xED, 0xD1, 0x12, 0x4B, 0x0B, 0xA9, +0xD3, 0xF8, 0x30, 0x34, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x47, 0x04, 0xB0, 0x70, 0x47, 0xD8, 0xF8, +0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, 0x05, 0xF1, 0x66, 0x03, 0x00, 0x2A, 0xDB, 0xB2, 0x05, 0xDB, 0xD6, 0xF8, 0x04, 0x31, +0x9A, 0x3D, 0xAB, 0x42, 0xE3, 0xD8, 0xEB, 0xE7, 0x05, 0x2B, 0xF7, 0xD9, 0x40, 0xF2, 0xA9, 0x22, 0x51, 0x46, 0x48, 0x46, +0x00, 0xF0, 0x36, 0xFA, 0xF0, 0xE7, 0x00, 0xBF, 0xB0, 0xB6, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xCC, 0xB2, 0x15, 0x00, 0x0E, 0xB4, 0x09, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0x1B, 0x88, 0x18, 0x42, +0x82, 0xB0, 0x06, 0xD0, 0x06, 0x4B, 0x03, 0x98, 0xD3, 0xF8, 0x30, 0x34, 0x04, 0xA9, 0x01, 0x91, 0x98, 0x47, 0x02, 0xB0, +0x5D, 0xF8, 0x04, 0xEB, 0x03, 0xB0, 0x70, 0x47, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x08, 0xB5, 0x05, 0x48, +0xFF, 0xF7, 0x94, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFE, 0xF7, 0x35, 0xF8, 0xE0, 0xF7, 0x0F, 0xFC, 0xFE, 0xE7, +0x64, 0xB3, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x48, 0xFF, 0xF7, 0x86, 0xFF, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFE, 0xF7, +0x27, 0xF8, 0xE0, 0xF7, 0x01, 0xFC, 0xFE, 0xE7, 0x7C, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x17, 0x48, 0x00, 0x68, 0x00, 0x78, +0x02, 0x28, 0x83, 0xB0, 0x1D, 0x46, 0x06, 0xD1, 0x48, 0x78, 0x83, 0x1E, 0x01, 0x2B, 0x0C, 0x46, 0x0E, 0xD9, 0x05, 0x28, +0x0C, 0xD0, 0x11, 0x48, 0x01, 0x92, 0xFF, 0xF7, 0x69, 0xFF, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x1C, 0x40, 0xFE, 0xF7, +0x63, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x23, 0x78, 0x53, 0xB9, 0xA3, 0x78, 0x01, 0x92, 0x1B, 0xB1, 0xE1, 0xF7, +0x17, 0xFE, 0x01, 0x9A, 0xEE, 0xE7, 0xE1, 0xF7, 0x1D, 0xFE, 0x01, 0x9A, 0xEA, 0xE7, 0x01, 0x21, 0x01, 0x92, 0xE1, 0xF7, +0xE1, 0xFD, 0x60, 0x78, 0x01, 0x9A, 0xED, 0xE7, 0x78, 0x36, 0x17, 0x00, 0x88, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x83, 0xB0, +0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, 0x1D, 0x46, 0xFF, 0xF7, 0x3F, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, +0x04, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, 0x07, 0x40, 0xFE, 0xF7, 0x35, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, +0xA0, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x0C, 0x46, 0x09, 0x48, 0x09, 0x68, 0x01, 0x92, +0x1D, 0x46, 0xFF, 0xF7, 0x25, 0xFF, 0x07, 0x4B, 0x21, 0x68, 0xC3, 0xF8, 0x00, 0x11, 0x01, 0x9A, 0x29, 0x46, 0x40, 0xF2, +0x05, 0x40, 0xFE, 0xF7, 0x1B, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xC8, 0xB3, 0x15, 0x00, 0xB0, 0xB6, 0x17, 0x00, +0x18, 0x46, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x23, 0x01, 0x46, 0x4F, 0xF4, 0x82, 0x60, 0xFE, 0xF7, 0xA3, 0xF8, 0x22, 0x4B, +0xA9, 0x88, 0x93, 0xF8, 0xA9, 0x30, 0x04, 0x46, 0xEB, 0xB1, 0x4B, 0x1E, 0x01, 0x2B, 0x0D, 0xD9, 0x02, 0x29, 0x2A, 0xD0, +0x03, 0x29, 0x2F, 0xD0, 0x04, 0x29, 0x1C, 0xD1, 0x1B, 0x4B, 0x2A, 0x68, 0xDA, 0x65, 0x4F, 0xF0, 0x80, 0x72, 0xC3, 0xF8, +0x34, 0x21, 0x14, 0xE0, 0x18, 0x48, 0x17, 0x4A, 0x03, 0x68, 0x43, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x53, 0x6F, 0x16, 0x48, +0x43, 0xF0, 0x10, 0x03, 0x53, 0x67, 0x01, 0x23, 0x03, 0x70, 0x01, 0x29, 0xE2, 0xD1, 0x10, 0x4B, 0x2A, 0x68, 0xDA, 0x63, +0x40, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0x00, 0x25, 0x0F, 0x48, 0x25, 0x60, 0xFF, 0xF7, 0xDA, 0xFE, 0x20, 0x46, 0xFE, 0xF7, +0x9F, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x08, 0x4B, 0x2A, 0x68, 0x9A, 0x65, 0x20, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xEE, 0xE7, +0x04, 0x4B, 0x2A, 0x68, 0x1A, 0x64, 0x80, 0x22, 0xC3, 0xF8, 0x24, 0x21, 0xE7, 0xE7, 0x00, 0xBF, 0x2C, 0x19, 0x17, 0x00, +0x00, 0x00, 0x50, 0x40, 0xE0, 0x50, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0xF0, 0xB3, 0x15, 0x00, 0x30, 0xB5, 0x18, 0x46, +0x0C, 0x46, 0x08, 0x23, 0x01, 0x46, 0x85, 0xB0, 0x40, 0xF2, 0x12, 0x40, 0xFE, 0xF7, 0x4A, 0xF8, 0x18, 0x4B, 0x22, 0x68, +0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x19, 0xD9, 0x11, 0x68, 0xA3, 0x68, 0x60, 0x68, 0x4B, 0x40, +0x03, 0x40, 0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0x2A, 0x60, 0x11, 0x68, 0xA3, 0x68, 0x69, 0x60, 0xCD, 0xE9, 0x01, 0x11, +0x00, 0x92, 0x61, 0x68, 0x0D, 0x48, 0x1A, 0x46, 0xFF, 0xF7, 0x96, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x5B, 0xF8, 0x00, 0x20, +0x05, 0xB0, 0x30, 0xBD, 0x09, 0x4B, 0x9A, 0x42, 0x07, 0xD1, 0xD4, 0xE9, 0x01, 0x03, 0x11, 0x68, 0x4B, 0x40, 0x03, 0x40, +0x4B, 0x40, 0x13, 0x60, 0x22, 0x68, 0xA3, 0x68, 0xC5, 0xE9, 0x00, 0x23, 0x19, 0x46, 0xE1, 0xE7, 0x78, 0x36, 0x17, 0x00, +0x04, 0xB4, 0x15, 0x00, 0x58, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x19, 0x46, 0x40, 0xF2, 0x0A, 0x40, 0x0C, 0x23, 0xFE, 0xF7, +0x0B, 0xF8, 0x00, 0x24, 0xC0, 0xE9, 0x00, 0x44, 0x84, 0x60, 0xFE, 0xF7, 0x35, 0xF8, 0x20, 0x46, 0x10, 0xBD, 0x00, 0xBF, +0x30, 0xB5, 0x18, 0x46, 0x83, 0xB0, 0x08, 0x23, 0x0C, 0x46, 0x01, 0x46, 0x40, 0xF2, 0x03, 0x40, 0xFD, 0xF7, 0xF8, 0xFF, +0x10, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x3B, 0x01, 0x2B, 0x05, 0x46, 0x13, 0xD9, 0xD4, 0xE9, 0x00, 0x32, 0x1A, 0x60, +0x23, 0x68, 0x03, 0x60, 0x19, 0x68, 0x62, 0x68, 0x41, 0x60, 0xCD, 0xE9, 0x00, 0x11, 0x09, 0x48, 0x11, 0x46, 0xFF, 0xF7, +0x4B, 0xFE, 0x28, 0x46, 0xFE, 0xF7, 0x10, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0xD4, 0xE9, 0x00, 0x32, 0xC0, 0xE9, +0x00, 0x32, 0x11, 0x46, 0xED, 0xE7, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, 0x58, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0D, 0x46, +0x40, 0xF2, 0x01, 0x40, 0x19, 0x46, 0x08, 0x23, 0xFD, 0xF7, 0xCA, 0xFF, 0x29, 0x68, 0x0B, 0x68, 0x04, 0x46, 0xC4, 0xE9, +0x00, 0x13, 0x1A, 0x46, 0x03, 0x48, 0xFF, 0xF7, 0x29, 0xFE, 0x20, 0x46, 0xFD, 0xF7, 0xEE, 0xFF, 0x00, 0x20, 0x38, 0xBD, +0x98, 0xB4, 0x15, 0x00, 0x38, 0xB5, 0x0C, 0x46, 0x40, 0xF2, 0x0E, 0x40, 0x19, 0x46, 0x04, 0x23, 0xFD, 0xF7, 0xB2, 0xFF, +0x61, 0x68, 0x02, 0x29, 0x05, 0x46, 0x20, 0xD9, 0x03, 0x29, 0x11, 0xD0, 0x13, 0x48, 0xFF, 0xF7, 0x11, 0xFE, 0x4F, 0xF4, +0xD2, 0x73, 0x0F, 0x20, 0x1B, 0x68, 0x98, 0x47, 0xC0, 0xB2, 0x28, 0x60, 0x0F, 0x48, 0xFF, 0xF7, 0x07, 0xFE, 0x28, 0x46, +0xFD, 0xF7, 0xCC, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x24, 0x68, 0x0C, 0x48, 0x21, 0x46, 0xFF, 0xF7, 0xFD, 0xFD, 0x5C, 0xB1, +0xA2, 0x02, 0x01, 0x21, 0x40, 0xF2, 0x1E, 0x40, 0xFD, 0xF7, 0xEC, 0xFD, 0xE3, 0xE7, 0x22, 0x68, 0x06, 0x48, 0xFF, 0xF7, +0xF1, 0xFD, 0xDE, 0xE7, 0xE0, 0xF7, 0x70, 0xFA, 0xFE, 0xE7, 0x00, 0xBF, 0xF4, 0xB4, 0x15, 0x00, 0x08, 0xB5, 0x15, 0x00, +0xE8, 0xB4, 0x15, 0x00, 0xC8, 0xB4, 0x15, 0x00, 0x30, 0xB5, 0x40, 0xF2, 0x0C, 0x40, 0x83, 0xB0, 0x0C, 0x46, 0x19, 0x46, +0x04, 0x23, 0xFD, 0xF7, 0x73, 0xFF, 0x05, 0x46, 0x20, 0x68, 0x00, 0x23, 0x82, 0x07, 0x62, 0x68, 0x2B, 0x60, 0x1C, 0xBF, +0xFF, 0x23, 0x2B, 0x60, 0x93, 0x07, 0x1C, 0xBF, 0x01, 0x23, 0x2B, 0x60, 0x04, 0xF1, 0x08, 0x01, 0x12, 0xF0, 0xEA, 0xFA, +0xD4, 0xE9, 0x00, 0x12, 0x28, 0x68, 0xA3, 0x68, 0x00, 0x90, 0x0A, 0x44, 0x04, 0x48, 0xFF, 0xF7, 0xC1, 0xFD, 0x28, 0x46, +0xFD, 0xF7, 0x86, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x1C, 0xB5, 0x15, 0x00, 0x70, 0xB5, 0x06, 0x46, +0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x11, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x10, 0x4C, 0x11, 0x48, +0x25, 0x68, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x35, 0x0A, 0x46, 0x31, 0x46, 0x25, 0x60, 0xFF, 0xF7, 0xA3, 0xFD, 0x0D, 0x4B, +0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDB, 0xFC, 0xF7, 0x41, 0xFF, 0x4F, 0xF0, 0x00, 0x40, 0xFE, 0xF7, 0x1D, 0xFB, 0x23, 0x68, +0x33, 0xB1, 0x04, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0xBF, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x78, 0xB5, 0x15, 0x00, 0x80, 0xB6, 0x17, 0x00, 0x70, 0xB5, 0x04, 0x46, +0x72, 0xB6, 0x07, 0x4D, 0x07, 0x48, 0x00, 0x26, 0x22, 0xF0, 0x7F, 0x43, 0x2E, 0x60, 0x0A, 0x46, 0x21, 0x46, 0xFF, 0xF7, +0x79, 0xFD, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xFD, 0xD1, 0x70, 0xBD, 0x38, 0x00, 0x32, 0x40, 0x78, 0xB5, 0x15, 0x00, +0xD0, 0x22, 0x17, 0x00, 0x10, 0xB4, 0x0C, 0x46, 0x22, 0xF0, 0x7F, 0x43, 0x01, 0x46, 0x22, 0x46, 0x02, 0x48, 0x5D, 0xF8, +0x04, 0x4B, 0xFF, 0xF7, 0x63, 0xBD, 0x00, 0xBF, 0x90, 0xB5, 0x15, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x07, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x06, 0x4B, 0x1A, 0x68, 0x51, 0x1C, 0x19, 0x60, 0x29, 0xB1, 0x03, 0x49, +0x1A, 0x60, 0x0B, 0x68, 0x0A, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x70, 0x47, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, +0x10, 0xB5, 0x06, 0x4C, 0x4F, 0xF4, 0x84, 0x72, 0x20, 0x46, 0x00, 0x21, 0xDB, 0xF7, 0xD2, 0xFA, 0x4F, 0xF0, 0xFF, 0x32, +0x02, 0x23, 0xC4, 0xE9, 0x40, 0x23, 0x10, 0xBD, 0xB0, 0xB6, 0x17, 0x00, 0x08, 0xB5, 0x08, 0x22, 0x00, 0x21, 0x02, 0x48, +0xDB, 0xF7, 0xC4, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0xB8, 0xB7, 0x17, 0x00, 0xE0, 0xF7, 0xB4, 0xBC, 0x01, 0x4B, 0xD3, 0xF8, +0x24, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x02, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0xCC, 0xBB, 0x04, 0x4B, 0x1B, 0x68, +0x1B, 0x78, 0x03, 0x2B, 0x01, 0xD0, 0x01, 0x20, 0x70, 0x47, 0xE0, 0xF7, 0x5F, 0xBB, 0x00, 0xBF, 0x78, 0x36, 0x17, 0x00, +0xE0, 0xF7, 0x6E, 0xBB, 0x70, 0xB5, 0x04, 0x68, 0x9C, 0xB1, 0x0A, 0x4E, 0x05, 0x46, 0x03, 0xE0, 0xFE, 0xF7, 0x32, 0xFB, +0x2C, 0x68, 0x64, 0xB1, 0x28, 0x46, 0xFE, 0xF7, 0x71, 0xFB, 0xE3, 0x68, 0x21, 0x46, 0x30, 0x46, 0x00, 0x2B, 0xF3, 0xD1, +0xA2, 0x68, 0x2C, 0x68, 0x13, 0x81, 0x00, 0x2C, 0xF2, 0xD1, 0x70, 0xBD, 0x24, 0x65, 0x17, 0x00, 0x38, 0xB5, 0x14, 0x4B, +0x1B, 0x68, 0x1B, 0x78, 0x03, 0x2B, 0x00, 0xD0, 0x38, 0xBD, 0x04, 0x46, 0xE0, 0xF7, 0x80, 0xFB, 0x05, 0x46, 0xB8, 0xB1, +0x4C, 0xF2, 0xDE, 0x03, 0xA3, 0x61, 0x21, 0x46, 0x1C, 0x22, 0x12, 0xF0, 0x07, 0xFA, 0x0C, 0x4C, 0x23, 0x68, 0x00, 0x2B, +0xFC, 0xD0, 0x0B, 0x4B, 0x18, 0x68, 0x29, 0x1F, 0x00, 0xF5, 0x07, 0x70, 0xFE, 0xF7, 0x02, 0xFB, 0x01, 0x23, 0x23, 0x60, +0xBD, 0xE8, 0x38, 0x40, 0xE0, 0xF7, 0x90, 0xBB, 0xBD, 0xE8, 0x38, 0x40, 0x04, 0x48, 0xFF, 0xF7, 0xD1, 0xBC, 0x00, 0xBF, +0x78, 0x36, 0x17, 0x00, 0x58, 0x40, 0x04, 0x40, 0x00, 0x38, 0x18, 0x00, 0xA8, 0xB5, 0x15, 0x00, 0x01, 0x4B, 0xD3, 0xF8, +0x28, 0x31, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x04, 0x46, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, +0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0F, 0x4D, 0x10, 0x48, 0x2B, 0x68, 0x01, 0x33, 0x2B, 0x60, 0xFE, 0xF7, +0xD7, 0xFA, 0x05, 0x2C, 0x03, 0xD8, 0x0D, 0x4A, 0x13, 0x5D, 0x01, 0x3B, 0x13, 0x55, 0x2B, 0x68, 0x33, 0xB1, 0x07, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x07, 0x4A, 0xD2, 0xF8, 0xF8, 0x31, 0x01, 0x3B, +0xC2, 0xF8, 0xF8, 0x31, 0x38, 0xBD, 0x00, 0xBF, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x20, 0x58, 0x17, 0x00, +0x74, 0x28, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x0C, 0x4C, 0xDF, 0xF8, 0x3C, 0x80, 0x0C, 0x4F, +0x0C, 0x4E, 0x04, 0xF5, 0x7C, 0x75, 0x62, 0x69, 0x30, 0x46, 0x13, 0x46, 0x3A, 0xB1, 0x12, 0x78, 0x21, 0x69, 0x20, 0x2A, +0x0C, 0xBF, 0x42, 0x46, 0x3A, 0x46, 0xE1, 0xF7, 0xB1, 0xFA, 0x10, 0x34, 0xAC, 0x42, 0xF0, 0xD1, 0x00, 0x20, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0xBF, 0x24, 0x30, 0x17, 0x00, 0xC4, 0xB5, 0x15, 0x00, 0xC8, 0xB5, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, +0xF8, 0xB5, 0x10, 0xF8, 0x01, 0x3C, 0x09, 0x2B, 0x00, 0xF1, 0xFF, 0x36, 0x30, 0xD1, 0x1C, 0x4C, 0x23, 0x68, 0x99, 0x42, +0x0D, 0x46, 0x08, 0xDA, 0x1A, 0x4F, 0x38, 0x46, 0x00, 0xF0, 0x64, 0xFD, 0x23, 0x68, 0x01, 0x3B, 0xAB, 0x42, 0x23, 0x60, +0xF7, 0xDC, 0x17, 0x4D, 0xAE, 0x42, 0x19, 0xD9, 0x16, 0x4F, 0x06, 0xE0, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0x00, 0xF0, +0x53, 0xFD, 0xAE, 0x42, 0x10, 0xD0, 0x15, 0xF8, 0x01, 0x0B, 0x09, 0x28, 0xF4, 0xD1, 0x20, 0x68, 0x00, 0xF0, 0x07, 0x00, +0x38, 0x44, 0x00, 0xF0, 0x49, 0xFD, 0x23, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0xAE, 0x42, 0x23, 0x60, 0xEE, 0xD1, +0x0A, 0x4A, 0x13, 0x68, 0x01, 0x3B, 0x30, 0x46, 0x13, 0x60, 0xF8, 0xBD, 0x04, 0x48, 0x00, 0xF0, 0x39, 0xFD, 0x02, 0x4A, +0x13, 0x68, 0x01, 0x3B, 0x13, 0x60, 0xF1, 0xE7, 0x24, 0x34, 0x17, 0x00, 0x1C, 0xB8, 0x15, 0x00, 0x28, 0x34, 0x17, 0x00, +0x20, 0xB8, 0x15, 0x00, 0x68, 0x34, 0x17, 0x00, 0x61, 0xB3, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0x64, 0x90, 0x16, 0x4F, +0xDF, 0xF8, 0x58, 0x80, 0x0E, 0x46, 0x45, 0x1E, 0x00, 0x24, 0x08, 0xE0, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, +0x11, 0xFC, 0x23, 0x07, 0x10, 0xD0, 0xB4, 0x42, 0x13, 0xD0, 0x14, 0xF0, 0x07, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF1, 0xD1, +0x48, 0x46, 0xFF, 0xF7, 0x05, 0xFC, 0x15, 0xF8, 0x01, 0x1F, 0x38, 0x46, 0xFF, 0xF7, 0x00, 0xFC, 0x23, 0x07, 0xEE, 0xD1, +0x40, 0x46, 0xFF, 0xF7, 0xFB, 0xFB, 0xB4, 0x42, 0xEB, 0xD1, 0xBD, 0xE8, 0xF8, 0x43, 0x04, 0x48, 0xFF, 0xF7, 0xF4, 0xBB, +0x02, 0x48, 0xFF, 0xF7, 0xF1, 0xBB, 0x00, 0xBF, 0xD8, 0xB5, 0x15, 0x00, 0xB4, 0x79, 0x15, 0x00, 0xD4, 0xB5, 0x15, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0x87, 0xB0, 0x04, 0x93, 0x00, 0x29, 0x7E, 0xD0, 0x04, 0x2A, 0x14, 0x46, 0x02, 0xD0, 0x53, 0x1E, +0x01, 0x2B, 0x78, 0xD8, 0x65, 0x42, 0x04, 0xFB, 0x01, 0xF3, 0xDF, 0xF8, 0x8C, 0x91, 0x03, 0x93, 0x05, 0x40, 0x5C, 0x48, +0x29, 0x46, 0xE1, 0xF7, 0x09, 0xFA, 0x03, 0x9A, 0x2B, 0x0E, 0x10, 0x2A, 0x17, 0x46, 0x28, 0xBF, 0x10, 0x27, 0x01, 0x2B, +0x68, 0xD0, 0x2B, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0x64, 0xD0, 0x00, 0x2A, 0x00, 0xF0, 0x9C, 0x80, 0xDF, 0xF8, 0x60, 0x81, +0xDF, 0xF8, 0x60, 0xA1, 0x2E, 0x46, 0x4F, 0xF0, 0x00, 0x0B, 0x0A, 0xE0, 0x02, 0x2C, 0x0A, 0xBF, 0x31, 0x88, 0x31, 0x78, +0x50, 0x46, 0xA3, 0x44, 0xE1, 0xF7, 0xEA, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0x0A, 0xD9, 0x04, 0x2C, 0x40, 0x46, 0xF1, 0xD1, +0x31, 0x68, 0x48, 0x48, 0xA3, 0x44, 0xE1, 0xF7, 0xDF, 0xF9, 0x5F, 0x45, 0x26, 0x44, 0xF4, 0xD8, 0x04, 0x9B, 0xB3, 0xB3, +0x03, 0x9B, 0x0F, 0x2B, 0x7D, 0xD8, 0x4F, 0xF0, 0x00, 0x08, 0xC7, 0xF1, 0x10, 0x03, 0x04, 0xF1, 0xFF, 0x3A, 0x05, 0x94, +0xDF, 0xF8, 0x14, 0xB1, 0x44, 0x46, 0x98, 0x46, 0x04, 0xE0, 0x58, 0x46, 0x00, 0xF0, 0x9A, 0xFC, 0xA0, 0x45, 0x0C, 0xD0, +0x1A, 0xEA, 0x04, 0x0F, 0x04, 0xF1, 0x01, 0x04, 0xF5, 0xD1, 0x20, 0x20, 0x00, 0xF0, 0x8E, 0xFC, 0x58, 0x46, 0x00, 0xF0, +0x8D, 0xFC, 0xA0, 0x45, 0xF2, 0xD1, 0x34, 0x48, 0x05, 0x9C, 0x00, 0xF0, 0x87, 0xFC, 0x03, 0x9B, 0x00, 0x2B, 0x4D, 0xD0, +0x4F, 0xF0, 0x00, 0x08, 0x15, 0xF8, 0x08, 0x00, 0xA0, 0xF1, 0x1F, 0x03, 0x5F, 0x2B, 0x88, 0xBF, 0x2E, 0x20, 0x08, 0xF1, +0x01, 0x08, 0x00, 0xF0, 0x75, 0xFC, 0x47, 0x45, 0xF2, 0xD8, 0x35, 0x46, 0x29, 0x48, 0x00, 0xF0, 0x71, 0xFC, 0x03, 0x9B, +0xDB, 0x1B, 0x03, 0x93, 0x8D, 0xD1, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x03, 0x9B, 0x8B, 0xB3, 0xDF, 0xF8, 0x84, 0xA0, +0x4F, 0xF0, 0x00, 0x08, 0x09, 0xE0, 0xCD, 0xF8, 0x00, 0xC0, 0xE1, 0xF7, 0x8D, 0xF9, 0x08, 0xF1, 0x04, 0x08, 0x47, 0x45, +0x05, 0xF1, 0x04, 0x05, 0x1A, 0xD9, 0x28, 0x46, 0xDD, 0xF7, 0xEE, 0xF9, 0x04, 0x2C, 0x06, 0x46, 0x4F, 0xEA, 0x10, 0x6C, +0xC0, 0xF3, 0x07, 0x43, 0xC0, 0xF3, 0x07, 0x22, 0xC1, 0xB2, 0x48, 0x46, 0x0F, 0xD0, 0x02, 0x2C, 0xE5, 0xD1, 0x15, 0x48, +0x32, 0x0C, 0xB1, 0xB2, 0x08, 0xF1, 0x04, 0x08, 0xE1, 0xF7, 0x70, 0xF9, 0x47, 0x45, 0x05, 0xF1, 0x04, 0x05, 0xE4, 0xD8, +0x00, 0x23, 0x04, 0x93, 0xC6, 0xE7, 0x31, 0x46, 0x50, 0x46, 0xE1, 0xF7, 0x65, 0xF9, 0xD6, 0xE7, 0x0A, 0x48, 0x07, 0xB0, +0xBD, 0xE8, 0xF0, 0x4F, 0x00, 0xF0, 0x30, 0xBC, 0x04, 0x9B, 0x00, 0x2B, 0xB8, 0xD0, 0x2E, 0x46, 0x81, 0xE7, 0x04, 0x48, +0x00, 0xF0, 0x28, 0xFC, 0xA2, 0xE7, 0x00, 0xBF, 0xE0, 0xB5, 0x15, 0x00, 0xB8, 0x89, 0x15, 0x00, 0x1C, 0xB6, 0x15, 0x00, +0xD0, 0x79, 0x15, 0x00, 0xE8, 0xB5, 0x15, 0x00, 0xF4, 0xB5, 0x15, 0x00, 0x14, 0xB6, 0x15, 0x00, 0x0C, 0xB6, 0x15, 0x00, +0xD4, 0xB5, 0x15, 0x00, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x22, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x22, 0x4C, 0x22, 0x48, 0x23, 0x68, 0x01, 0x33, 0x23, 0x60, 0xFE, 0xF7, 0x1E, 0xF9, 0x20, 0x48, 0xFE, 0xF7, +0x1B, 0xF9, 0x20, 0x49, 0x1D, 0x48, 0xFE, 0xF7, 0x1B, 0xF9, 0x1F, 0x49, 0x1B, 0x48, 0xFE, 0xF7, 0x17, 0xF9, 0x1E, 0x49, +0x19, 0x48, 0xFE, 0xF7, 0x13, 0xF9, 0x1D, 0x49, 0x17, 0x48, 0xFE, 0xF7, 0x0F, 0xF9, 0x23, 0x68, 0x33, 0xB1, 0x13, 0x4A, +0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x01, 0x22, +0x00, 0xF0, 0xFC, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xF6, 0xFB, 0x17, 0x4B, 0x18, 0x49, +0x18, 0x48, 0x03, 0x22, 0x00, 0xF0, 0xF0, 0xFB, 0x17, 0x4B, 0x18, 0x49, 0x18, 0x48, 0x04, 0x22, 0x00, 0xF0, 0xEA, 0xFB, +0xBD, 0xE8, 0x10, 0x40, 0x16, 0x4B, 0x17, 0x49, 0x17, 0x48, 0x02, 0x22, 0x00, 0xF0, 0xE2, 0xBB, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, 0xC8, 0xB7, 0x17, 0x00, 0x0C, 0xB8, 0x17, 0x00, +0x50, 0xB8, 0x17, 0x00, 0x94, 0xB8, 0x17, 0x00, 0x69, 0x4D, 0x14, 0x00, 0x24, 0xB6, 0x15, 0x00, 0x30, 0xB6, 0x15, 0x00, +0x61, 0x56, 0x14, 0x00, 0x38, 0xB6, 0x15, 0x00, 0x7C, 0xAB, 0x15, 0x00, 0x2D, 0x57, 0x14, 0x00, 0x4C, 0xB6, 0x15, 0x00, +0x58, 0xB6, 0x15, 0x00, 0xED, 0x55, 0x14, 0x00, 0x5C, 0xB6, 0x15, 0x00, 0x68, 0xB6, 0x15, 0x00, 0x99, 0x57, 0x14, 0x00, +0x6C, 0xB6, 0x15, 0x00, 0x7C, 0xB6, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x54, 0x4D, 0x55, 0x4E, 0x29, 0x68, 0x31, 0x60, +0x17, 0x28, 0x04, 0x46, 0x10, 0xD8, 0x17, 0x28, 0x00, 0xF2, 0x8E, 0x80, 0xDF, 0xE8, 0x00, 0xF0, 0x15, 0x8C, 0x8C, 0x71, +0x8C, 0x8C, 0x8C, 0x8C, 0x48, 0x8C, 0x1A, 0x8C, 0x8C, 0x1A, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x55, 0x8C, 0x60, +0x7F, 0x28, 0x39, 0xD0, 0x49, 0x4F, 0x3B, 0x68, 0x3D, 0x2B, 0x65, 0xDD, 0x07, 0x20, 0x00, 0xF0, 0x75, 0xFB, 0x4F, 0xF0, +0xFF, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x44, 0x4E, 0x45, 0x48, 0x33, 0x68, 0xDF, 0xF8, 0x20, 0x81, 0x00, 0x22, +0x1A, 0x70, 0x00, 0xF0, 0x69, 0xFB, 0x34, 0x68, 0xA4, 0xEB, 0x08, 0x04, 0x00, 0x2C, 0xEE, 0xDB, 0x0F, 0xD1, 0x3F, 0x48, +0x00, 0xF0, 0x60, 0xFB, 0x00, 0x24, 0x3D, 0x48, 0x12, 0xF0, 0x70, 0xF9, 0x38, 0x4B, 0x28, 0x60, 0x00, 0x22, 0xC6, 0xF8, +0x00, 0x80, 0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x48, 0xFE, 0xF7, 0xB2, 0xF8, 0x07, 0x46, 0x00, 0x28, +0x48, 0xD0, 0x41, 0x46, 0x04, 0x30, 0x12, 0xF0, 0xED, 0xF8, 0x34, 0x48, 0x39, 0x46, 0xFE, 0xF7, 0x63, 0xF8, 0xE4, 0xE7, +0x2C, 0x4B, 0x2D, 0x4E, 0x1B, 0x68, 0x30, 0x68, 0x0B, 0xB1, 0xFF, 0xF7, 0xC9, 0xFD, 0x4F, 0xF0, 0xFF, 0x34, 0x30, 0x60, +0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x27, 0x4A, 0x25, 0x4B, 0x2B, 0x49, 0x11, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x00, 0x22, +0x1A, 0x60, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x20, 0x4F, 0x21, 0x4E, 0x3B, 0x68, 0x30, 0x68, 0x0B, 0xB9, 0xAE, 0xE7, +0x29, 0x68, 0xFF, 0xF7, 0xAF, 0xFD, 0x3B, 0x68, 0x30, 0x60, 0x00, 0x2B, 0xA7, 0xDD, 0x03, 0x78, 0x20, 0x2B, 0xF5, 0xD1, +0xA3, 0xE7, 0xDF, 0xF8, 0x78, 0x80, 0x18, 0x4E, 0x00, 0x23, 0x88, 0xF8, 0x00, 0x30, 0xB0, 0xE7, 0x01, 0x31, 0x20, 0x46, +0x31, 0x60, 0x00, 0xF0, 0x0D, 0xFB, 0x13, 0x49, 0x0B, 0x68, 0x1C, 0x70, 0x3A, 0x68, 0x01, 0x33, 0x01, 0x32, 0x0B, 0x60, +0x3A, 0x60, 0x4F, 0xF0, 0xFF, 0x34, 0x8E, 0xE7, 0x13, 0x48, 0x00, 0xF0, 0x01, 0xFB, 0xA0, 0xE7, 0x0A, 0x4F, 0x3B, 0x68, +0x3D, 0x2B, 0x81, 0xDC, 0x09, 0x28, 0xE5, 0xD1, 0x0F, 0x48, 0x01, 0xF0, 0x07, 0x01, 0x08, 0x44, 0x00, 0xF0, 0xF4, 0xFA, +0x33, 0x68, 0x23, 0xF0, 0x07, 0x03, 0x08, 0x33, 0x33, 0x60, 0xDE, 0xE7, 0x6C, 0x34, 0x17, 0x00, 0x24, 0x34, 0x17, 0x00, +0x68, 0x34, 0x17, 0x00, 0xD4, 0x22, 0x17, 0x00, 0xD0, 0x79, 0x15, 0x00, 0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, +0xC0, 0xB7, 0x17, 0x00, 0x28, 0x34, 0x17, 0x00, 0x84, 0xB6, 0x15, 0x00, 0x20, 0xB8, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x4D, +0x2C, 0x68, 0x3F, 0x2C, 0x0D, 0xD8, 0x0B, 0x4F, 0x4F, 0xEA, 0x04, 0x1C, 0x07, 0xEB, 0x04, 0x16, 0x01, 0x34, 0x47, 0xF8, +0x0C, 0x00, 0xC6, 0xE9, 0x01, 0x12, 0xF3, 0x60, 0x2C, 0x60, 0x00, 0x20, 0xF8, 0xBD, 0x05, 0x48, 0xE0, 0xF7, 0xF0, 0xFF, +0x4F, 0xF0, 0xFF, 0x30, 0xF8, 0xBD, 0x00, 0xBF, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xA8, 0xB6, 0x15, 0x00, +0x2D, 0xE9, 0xF0, 0x4F, 0x95, 0xB0, 0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x76, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0xDF, 0xF8, 0xFC, 0xB1, 0x75, 0x48, 0xDB, 0xF8, 0x00, 0x30, 0x01, 0x33, 0xCB, 0xF8, 0x00, 0x30, 0xFE, 0xF7, +0x05, 0xF8, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x3B, 0xB1, 0x6E, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0xCB, 0xF8, 0x00, 0x30, +0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x00, 0x2E, 0x00, 0xF0, 0x94, 0x80, 0x33, 0x1D, 0x03, 0xAC, 0x01, 0x22, 0x4F, 0xF0, +0x00, 0x0C, 0x57, 0x1E, 0x3D, 0x46, 0x19, 0x46, 0x13, 0xF8, 0x01, 0x0B, 0x20, 0x28, 0xFA, 0xD0, 0x09, 0x28, 0xF8, 0xD0, +0x00, 0x28, 0x00, 0xF0, 0xA0, 0x80, 0x22, 0x28, 0x00, 0xF0, 0x83, 0x80, 0x21, 0x60, 0x08, 0x78, 0x15, 0x46, 0x00, 0x28, +0x00, 0xF0, 0xAC, 0x80, 0x0B, 0x46, 0x06, 0xE0, 0x09, 0x28, 0x06, 0xD0, 0x13, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0x00, 0xF0, +0xA3, 0x80, 0x20, 0x28, 0xF6, 0xD1, 0x19, 0x78, 0x00, 0x29, 0x00, 0xF0, 0x9D, 0x80, 0x01, 0x32, 0x11, 0x2A, 0x03, 0xF8, +0x01, 0xCB, 0x04, 0xF1, 0x04, 0x04, 0xD4, 0xD1, 0x52, 0x48, 0x10, 0x21, 0xE0, 0xF7, 0x8E, 0xFF, 0x10, 0x25, 0xDD, 0xF8, +0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x95, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x83, 0x80, 0xA0, 0xEB, 0x09, 0x04, +0x4B, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x28, 0xDD, 0x4A, 0x4F, 0x01, 0x95, 0x4F, 0xF0, 0x00, 0x08, 0xC2, 0x46, 0x3D, 0x46, +0x05, 0xE0, 0x46, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x07, 0xF1, 0x10, 0x07, 0x16, 0xDA, 0x39, 0x68, 0x22, 0x46, 0x48, 0x46, +0x0A, 0xF1, 0x01, 0x0A, 0x12, 0xF0, 0xBE, 0xF8, 0x00, 0x28, 0xF0, 0xD1, 0x38, 0x68, 0x12, 0xF0, 0x4B, 0xF8, 0x84, 0x42, +0x43, 0xD0, 0x3C, 0x4B, 0x1A, 0x68, 0x92, 0x45, 0x3D, 0x46, 0x08, 0xF1, 0x01, 0x08, 0x07, 0xF1, 0x10, 0x07, 0xE8, 0xDB, +0xB8, 0xF1, 0x01, 0x0F, 0x2B, 0x46, 0x01, 0x9D, 0x37, 0xD0, 0x03, 0x99, 0x36, 0x48, 0xE0, 0xF7, 0x51, 0xFF, 0x36, 0x48, +0x00, 0xF0, 0x20, 0xFA, 0x35, 0x48, 0x00, 0xF0, 0x1D, 0xFA, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x2A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xDB, 0xF8, 0x00, 0x30, 0x30, 0x48, 0x01, 0x33, 0x31, 0x46, 0xCB, 0xF8, 0x00, 0x30, +0xFD, 0xF7, 0x2A, 0xFF, 0x25, 0x48, 0xFD, 0xF7, 0x6B, 0xFF, 0xDB, 0xF8, 0x00, 0x30, 0x06, 0x46, 0x00, 0x2B, 0x7F, 0xF4, +0x64, 0xAF, 0x00, 0x2E, 0x7F, 0xF4, 0x6C, 0xAF, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4B, 0x1C, 0x23, 0x60, 0x49, 0x78, +0x15, 0x46, 0x19, 0xB9, 0x28, 0xE0, 0x13, 0xF8, 0x01, 0x1F, 0x29, 0xB3, 0x22, 0x29, 0xFA, 0xD1, 0x81, 0xE7, 0x01, 0x9D, +0x3B, 0x46, 0x9A, 0x68, 0xAA, 0x42, 0x24, 0xDB, 0xDB, 0x68, 0x00, 0x2B, 0xC8, 0xD0, 0x28, 0x46, 0x03, 0xA9, 0x98, 0x47, +0x00, 0x28, 0xC3, 0xD0, 0xBF, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x87, 0x03, 0x43, 0xF8, 0x44, 0x0C, 0x00, 0x2F, 0xB8, 0xD0, +0xDD, 0xF8, 0x0C, 0x90, 0x2E, 0x21, 0x48, 0x46, 0x11, 0xF0, 0x12, 0xFF, 0x00, 0x28, 0x7F, 0xF4, 0x7D, 0xAF, 0x48, 0x46, +0x11, 0xF0, 0xE4, 0xFF, 0x04, 0x46, 0x79, 0xE7, 0x14, 0xAB, 0x03, 0xEB, 0x82, 0x02, 0x00, 0x23, 0x42, 0xF8, 0x44, 0x3C, +0x67, 0xE7, 0x59, 0x68, 0x0A, 0x48, 0xE0, 0xF7, 0xF1, 0xFE, 0x9E, 0xE7, 0x38, 0x61, 0x17, 0x00, 0xC0, 0xB7, 0x17, 0x00, +0xC4, 0xB6, 0x15, 0x00, 0x20, 0x30, 0x17, 0x00, 0x24, 0x30, 0x17, 0x00, 0xE4, 0xB6, 0x15, 0x00, 0x08, 0xB7, 0x15, 0x00, +0xA0, 0xB6, 0x15, 0x00, 0xD8, 0xB8, 0x17, 0x00, 0xFC, 0xB6, 0x15, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xF0, 0xB4, 0x05, 0x78, +0x30, 0x2D, 0x2B, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x0A, 0x22, 0x2D, 0x2D, 0x32, 0xD0, 0x00, 0x27, 0x00, 0x26, 0xA5, 0xF1, +0x30, 0x03, 0x5F, 0xFA, 0x83, 0xFC, 0x25, 0xF0, 0x20, 0x04, 0xBC, 0xF1, 0x09, 0x0F, 0xA4, 0xF1, 0x41, 0x04, 0x12, 0xD9, +0x05, 0x2C, 0x06, 0xD9, 0x07, 0xB1, 0x76, 0x42, 0x01, 0xB1, 0x08, 0x60, 0x30, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0xA5, 0xF1, +0x61, 0x04, 0xA5, 0xF1, 0x20, 0x03, 0x19, 0x2C, 0xDB, 0xB2, 0x94, 0xBF, 0x37, 0x3B, 0xA5, 0xF1, 0x37, 0x03, 0x93, 0x42, +0xEC, 0xD2, 0x10, 0xF8, 0x01, 0x5F, 0x02, 0xFB, 0x06, 0x36, 0xDA, 0xE7, 0x45, 0x78, 0x78, 0x2D, 0x00, 0xF1, 0x01, 0x03, +0x0A, 0xD0, 0x18, 0x46, 0x00, 0x2A, 0xCE, 0xD1, 0x2D, 0x2D, 0x4F, 0xF0, 0x08, 0x02, 0xCC, 0xD1, 0x01, 0x27, 0x45, 0x78, +0x38, 0x44, 0xC9, 0xE7, 0x84, 0x78, 0xA4, 0xF1, 0x30, 0x06, 0x09, 0x2E, 0x09, 0xD9, 0x24, 0xF0, 0x20, 0x06, 0x41, 0x3E, +0x05, 0x2E, 0x04, 0xD9, 0x3A, 0xB9, 0x17, 0x46, 0x18, 0x46, 0x08, 0x22, 0xBA, 0xE7, 0x02, 0x30, 0x25, 0x46, 0x10, 0x22, +0xB3, 0xE7, 0x18, 0x46, 0xB3, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x22, 0x0C, 0x46, 0x05, 0x46, 0x48, 0x68, 0x00, 0x21, +0xFF, 0xF7, 0xA2, 0xFF, 0xC0, 0xB1, 0x01, 0x28, 0x10, 0xD1, 0x02, 0x2D, 0x1C, 0xDD, 0x10, 0x22, 0xA0, 0x68, 0x00, 0x21, +0xFF, 0xF7, 0x98, 0xFF, 0x0E, 0x4B, 0x1B, 0x68, 0x01, 0x46, 0x19, 0x80, 0x0D, 0x48, 0x89, 0xB2, 0xFF, 0xF7, 0x34, 0xF8, +0x00, 0x20, 0x38, 0xBD, 0x01, 0x46, 0x0B, 0x48, 0xFF, 0xF7, 0x2E, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x4B, 0x09, 0x48, +0x1B, 0x68, 0x19, 0x88, 0xFF, 0xF7, 0x26, 0xF8, 0x00, 0x20, 0x38, 0xBD, 0x06, 0x48, 0xFF, 0xF7, 0x21, 0xF8, 0x00, 0x20, +0x38, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x2C, 0xB7, 0x15, 0x00, 0x50, 0xB7, 0x15, 0x00, 0x18, 0xB7, 0x15, 0x00, +0x40, 0xB7, 0x15, 0x00, 0x01, 0x28, 0xF8, 0xB5, 0x2A, 0xDD, 0x0D, 0x46, 0x04, 0x46, 0x10, 0x22, 0x68, 0x68, 0x00, 0x21, +0xFF, 0xF7, 0x66, 0xFF, 0x02, 0x2C, 0x06, 0x46, 0x0D, 0xD1, 0x03, 0x0E, 0x01, 0x2B, 0x22, 0xD0, 0x03, 0x0D, 0xB3, 0xF5, +0xA0, 0x6F, 0x1E, 0xD0, 0x32, 0x68, 0x24, 0x48, 0x31, 0x46, 0xFE, 0xF7, 0xFB, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, +0xA8, 0x68, 0x11, 0x46, 0x00, 0xF0, 0x18, 0xF9, 0x03, 0x2C, 0x07, 0x46, 0x19, 0xD1, 0x04, 0x20, 0x01, 0x2F, 0x1C, 0xD0, +0xC2, 0xB2, 0x39, 0x46, 0x30, 0x46, 0x00, 0x23, 0xFF, 0xF7, 0xFE, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x18, 0x48, 0xFE, 0xF7, +0xE3, 0xFF, 0x01, 0x20, 0xF8, 0xBD, 0x30, 0x46, 0xDC, 0xF7, 0x7E, 0xFE, 0x31, 0x46, 0x02, 0x46, 0x12, 0x48, 0xFE, 0xF7, +0xD9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0x22, 0xE8, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0x2E, 0xFF, 0xE0, 0xE7, 0x33, 0x0E, +0x01, 0x2B, 0xEC, 0xD0, 0x33, 0x0D, 0xB3, 0xF5, 0xA0, 0x6F, 0xE8, 0xD0, 0x01, 0x28, 0x06, 0xD1, 0x32, 0x78, 0x0A, 0x48, +0x31, 0x46, 0xFE, 0xF7, 0xC3, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0x28, 0xBE, 0xD1, 0x32, 0x88, 0x06, 0x48, 0x92, 0xB2, +0x31, 0x46, 0xFE, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x7C, 0xB7, 0x15, 0x00, 0x64, 0xB7, 0x15, 0x00, +0x90, 0xB7, 0x15, 0x00, 0xA4, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, 0x21, 0xDD, 0x0D, 0x46, 0x10, 0x22, 0x68, 0x68, +0x00, 0x21, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x22, 0x04, 0x46, 0x00, 0x21, 0xA8, 0x68, 0xFF, 0xF7, 0xFB, 0xFE, 0x21, 0x46, +0x02, 0x46, 0x05, 0x46, 0x0F, 0x48, 0xFE, 0xF7, 0x99, 0xFF, 0x23, 0x0E, 0x01, 0x2B, 0x06, 0xD0, 0x23, 0x0D, 0xB3, 0xF5, +0xA0, 0x6F, 0x0D, 0xD0, 0x25, 0x60, 0x00, 0x20, 0x38, 0xBD, 0x20, 0x46, 0x29, 0x46, 0xDC, 0xF7, 0x53, 0xFE, 0x00, 0x20, +0x38, 0xBD, 0x07, 0x48, 0xFE, 0xF7, 0x86, 0xFF, 0x01, 0x20, 0x38, 0xBD, 0xB4, 0xF1, 0xA0, 0x4F, 0xF1, 0xD1, 0x28, 0x46, +0xDC, 0xF7, 0xF6, 0xFD, 0x00, 0x20, 0x38, 0xBD, 0x7C, 0xB7, 0x15, 0x00, 0xB8, 0xB7, 0x15, 0x00, 0x02, 0x28, 0x38, 0xB5, +0x46, 0xDC, 0x01, 0x28, 0x32, 0xD0, 0x00, 0x22, 0x48, 0x68, 0x11, 0x46, 0xFF, 0xF7, 0xCA, 0xFE, 0x25, 0x4A, 0x26, 0x4B, +0x02, 0xFB, 0x00, 0xF2, 0x9A, 0x42, 0x04, 0x46, 0x3E, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, +0x21, 0x4B, 0x01, 0x21, 0x19, 0x60, 0x21, 0x4D, 0x21, 0x49, 0x2B, 0x68, 0x0A, 0x60, 0x01, 0x33, 0x2B, 0x60, 0x82, 0xB1, +0x1F, 0x49, 0x09, 0x78, 0xF9, 0xB9, 0x33, 0xB1, 0x1A, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x1B, 0x48, 0x21, 0x46, 0xFE, 0xF7, 0x49, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, +0xFC, 0xF7, 0xE8, 0xFF, 0x2B, 0x68, 0xEA, 0xE7, 0x12, 0x4A, 0x15, 0x4B, 0x11, 0x68, 0x15, 0x48, 0xA3, 0xFB, 0x01, 0x31, +0x89, 0x0C, 0xFE, 0xF7, 0x37, 0xFF, 0x00, 0x20, 0x38, 0xBD, 0x01, 0x21, 0x40, 0xF2, 0x1F, 0x40, 0xFC, 0xF7, 0x26, 0xFF, +0x2B, 0x68, 0xD8, 0xE7, 0x0E, 0x48, 0xFE, 0xF7, 0x2B, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x0C, 0x48, 0xFE, 0xF7, +0x25, 0xFF, 0x4F, 0xF0, 0xFF, 0x30, 0x38, 0xBD, 0x40, 0x42, 0x0F, 0x00, 0xFF, 0xA2, 0xE1, 0x11, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x6C, 0x60, 0x17, 0x00, 0x64, 0x28, 0x17, 0x00, 0xF8, 0xB7, 0x15, 0x00, 0x83, 0xDE, 0x1B, 0x43, +0xE8, 0xB7, 0x15, 0x00, 0xD0, 0xB7, 0x15, 0x00, 0x08, 0xB8, 0x15, 0x00, 0x10, 0xB5, 0x07, 0x4C, 0x01, 0xE0, 0x04, 0x2A, +0x05, 0xD0, 0x23, 0x68, 0x03, 0xF0, 0x0F, 0x02, 0xDB, 0x07, 0xF8, 0xD5, 0x10, 0xBD, 0xE0, 0xF7, 0x1D, 0xFC, 0xFF, 0xF7, +0x6B, 0xFC, 0xF4, 0xE7, 0x08, 0x10, 0x04, 0x40, 0xE0, 0xF7, 0x0A, 0xBC, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x78, 0x28, 0xB1, +0xE0, 0xF7, 0x04, 0xFC, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0x28, 0xF9, 0xD1, 0x10, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x4C, +0xD4, 0xF8, 0xB8, 0x30, 0x98, 0x47, 0xD4, 0xF8, 0x28, 0x33, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, +0xFF, 0xF7, 0x2E, 0xBD, 0xFF, 0xF7, 0x0C, 0xBD, 0xFF, 0xF7, 0x36, 0xBE, 0x70, 0xB4, 0x02, 0x68, 0x1C, 0x4C, 0x2D, 0x21, +0xA3, 0x89, 0x11, 0x70, 0x02, 0x68, 0x1A, 0x21, 0x51, 0x70, 0x23, 0xF0, 0x1C, 0x03, 0x02, 0x68, 0x9B, 0xB2, 0x43, 0xF0, +0x0C, 0x03, 0x53, 0x80, 0xA3, 0x7B, 0x13, 0x71, 0x06, 0x68, 0x04, 0xF1, 0x0F, 0x03, 0x04, 0xF1, 0x1F, 0x05, 0x13, 0xF8, +0x01, 0x1B, 0x1A, 0x1B, 0x32, 0x44, 0xAB, 0x42, 0x02, 0xF8, 0x0B, 0x1C, 0xF7, 0xD1, 0x01, 0x68, 0x0E, 0x4A, 0x00, 0x23, +0xCB, 0x73, 0x01, 0x68, 0x0B, 0x74, 0x05, 0x68, 0x23, 0x8C, 0xA5, 0xF8, 0x15, 0x30, 0x05, 0xF1, 0x17, 0x03, 0x1B, 0x35, +0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0xAB, 0x42, 0xF9, 0xD1, 0x03, 0x68, 0x94, 0xF8, 0x28, 0x20, 0xDA, 0x76, +0x03, 0x68, 0x1C, 0x33, 0x03, 0x60, 0x70, 0xBC, 0x1C, 0x20, 0x70, 0x47, 0xE4, 0xB8, 0x17, 0x00, 0x08, 0xB9, 0x17, 0x00, +0x03, 0x68, 0x28, 0x4A, 0xFF, 0x21, 0x70, 0xB4, 0x19, 0x70, 0x03, 0x68, 0x23, 0x21, 0x99, 0x70, 0x05, 0x68, 0xEB, 0x1C, +0x05, 0xF1, 0x09, 0x04, 0x12, 0xF8, 0x01, 0x1F, 0x03, 0xF8, 0x01, 0x1B, 0xA3, 0x42, 0xF9, 0xD1, 0x20, 0x4A, 0xA2, 0xF1, +0x41, 0x01, 0x02, 0xF1, 0x0B, 0x06, 0xA2, 0xF1, 0x38, 0x03, 0x12, 0xF8, 0x01, 0x4F, 0x5B, 0x1A, 0xB2, 0x42, 0x5C, 0x55, +0xF7, 0xD1, 0x91, 0xF8, 0x42, 0x30, 0xB1, 0xF8, 0x50, 0x40, 0xB1, 0xF8, 0x4E, 0x20, 0xEC, 0x82, 0x1C, 0x07, 0xAA, 0x82, +0x05, 0xF1, 0x18, 0x06, 0x4F, 0xEA, 0x63, 0x02, 0x07, 0xD5, 0xB1, 0xF8, 0x52, 0x40, 0xB1, 0xF8, 0x54, 0x30, 0x6B, 0x83, +0x2C, 0x83, 0x05, 0xF1, 0x1C, 0x06, 0x13, 0x07, 0x04, 0xD5, 0xB1, 0xF8, 0x56, 0x30, 0x33, 0x80, 0x73, 0x80, 0x04, 0x36, +0x0C, 0x4C, 0x32, 0x46, 0x14, 0xF8, 0x01, 0x5F, 0x15, 0x70, 0x91, 0xF8, 0x75, 0x51, 0x93, 0x1B, 0x9D, 0x42, 0x02, 0xF1, +0x01, 0x02, 0xF5, 0xDA, 0x03, 0x68, 0xD2, 0x1A, 0x91, 0x1E, 0x59, 0x70, 0x03, 0x68, 0x13, 0x44, 0x03, 0x60, 0x70, 0xBC, +0x10, 0x46, 0x70, 0x47, 0x1F, 0xB9, 0x17, 0x00, 0x25, 0xB9, 0x17, 0x00, 0x3D, 0xB9, 0x17, 0x00, 0x70, 0xB4, 0x0F, 0x4C, +0x03, 0x46, 0x22, 0x6B, 0x09, 0xB1, 0x22, 0xF4, 0xC0, 0x52, 0x19, 0x68, 0xBF, 0x20, 0x08, 0x70, 0x19, 0x68, 0x0C, 0x20, +0x48, 0x70, 0x18, 0x68, 0xA1, 0x8E, 0xC0, 0xF8, 0x02, 0x20, 0x1A, 0x68, 0x60, 0x8F, 0xE6, 0x8E, 0x25, 0x8F, 0xD1, 0x80, +0x02, 0xF1, 0x0E, 0x01, 0x16, 0x81, 0x55, 0x81, 0x90, 0x81, 0x70, 0xBC, 0x0E, 0x20, 0x19, 0x60, 0x70, 0x47, 0x00, 0xBF, +0xE4, 0xB8, 0x17, 0x00, 0x03, 0x68, 0x10, 0xB4, 0xC7, 0x24, 0x1C, 0x70, 0x03, 0x68, 0x01, 0x24, 0x5C, 0x70, 0x03, 0x68, +0x42, 0xEA, 0x01, 0x11, 0x99, 0x70, 0x03, 0x68, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0x33, 0x03, 0x60, 0x03, 0x20, 0x70, 0x47, +0x03, 0x68, 0x46, 0x22, 0x1A, 0x70, 0x03, 0x68, 0x05, 0x22, 0x5A, 0x70, 0x03, 0x68, 0x70, 0x22, 0x9A, 0x70, 0x02, 0x68, +0x00, 0x23, 0xD3, 0x70, 0x02, 0x68, 0x13, 0x71, 0x02, 0x68, 0x53, 0x71, 0x02, 0x68, 0x93, 0x71, 0x03, 0x68, 0x07, 0x33, +0x03, 0x60, 0x07, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x30, 0xB4, 0x02, 0x9C, 0x01, 0x80, 0x42, 0x80, 0x83, 0x80, 0x84, 0xB1, +0x10, 0x22, 0x80, 0x23, 0x82, 0x71, 0xC3, 0x71, 0xE5, 0x18, 0x22, 0x46, 0x13, 0x46, 0x08, 0x33, 0x12, 0xF8, 0x01, 0x1B, +0x1B, 0x1B, 0xAA, 0x42, 0x19, 0x54, 0xF7, 0xD1, 0x88, 0x20, 0x30, 0xBC, 0x70, 0x47, 0x06, 0x20, 0x30, 0xBC, 0x70, 0x47, +0x01, 0x80, 0x02, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x8F, 0xB0, 0x1F, 0x46, 0x1A, 0x9E, 0x03, 0x93, +0x34, 0x8F, 0xB6, 0xF8, 0x36, 0x80, 0x0D, 0x46, 0x03, 0x46, 0x01, 0x2C, 0x38, 0x46, 0x38, 0xBF, 0x01, 0x24, 0x07, 0x93, +0x17, 0x46, 0x01, 0xF0, 0xC1, 0xFE, 0xB5, 0xF8, 0xAE, 0x90, 0x07, 0x9B, 0x09, 0xF0, 0x10, 0x09, 0x40, 0xEA, 0x09, 0x00, +0x06, 0xF1, 0x40, 0x02, 0x5C, 0x80, 0x02, 0x92, 0x18, 0x80, 0x1F, 0xFA, 0x80, 0xF9, 0x14, 0x46, 0x00, 0x2F, 0x00, 0xF0, +0xDE, 0x81, 0x3A, 0x88, 0x9A, 0x80, 0x7A, 0x88, 0xDA, 0x80, 0xBA, 0x88, 0x1A, 0x81, 0x0A, 0x22, 0x17, 0x46, 0x18, 0x99, +0x98, 0x18, 0x08, 0x60, 0x00, 0x21, 0x07, 0x90, 0x95, 0xF8, 0x7E, 0x00, 0x99, 0x54, 0x07, 0x9B, 0x00, 0xF1, 0x02, 0x0E, +0x58, 0x70, 0x00, 0x28, 0x40, 0xF0, 0xC7, 0x80, 0x07, 0x9B, 0x95, 0xF8, 0xB0, 0x10, 0x0E, 0xEB, 0x03, 0x00, 0x01, 0x22, +0x07, 0x90, 0x0E, 0xF8, 0x03, 0x20, 0x07, 0x9B, 0x08, 0x29, 0x8C, 0x46, 0x28, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x83, 0xF8, +0x01, 0xC0, 0x07, 0x9B, 0x1F, 0xFA, 0x8E, 0xFE, 0x0C, 0xF1, 0x02, 0x0A, 0x05, 0xF1, 0xB1, 0x02, 0x51, 0xB1, 0x0C, 0xF1, +0xB1, 0x0C, 0xAC, 0x44, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, 0xB0, 0x0C, 0xF7, 0xD1, +0x95, 0xF8, 0xB0, 0x20, 0xD6, 0x44, 0x0A, 0xEB, 0x03, 0x01, 0x08, 0x2A, 0x77, 0x44, 0x07, 0x91, 0x1A, 0xD9, 0x32, 0x21, +0x0A, 0xF8, 0x03, 0x10, 0x07, 0x9B, 0xA2, 0xF1, 0x08, 0x01, 0x59, 0x70, 0x02, 0xF1, 0xB1, 0x0C, 0x07, 0x9B, 0xA2, 0xF1, +0x06, 0x0E, 0xAC, 0x44, 0x05, 0xF1, 0xB9, 0x02, 0x12, 0xF8, 0x01, 0x0B, 0xD1, 0x18, 0x49, 0x1B, 0x94, 0x45, 0x01, 0xF8, +0xB8, 0x0C, 0xF7, 0xD1, 0x73, 0x44, 0x77, 0x44, 0x07, 0x93, 0xBF, 0xB2, 0x19, 0xF4, 0x80, 0x7F, 0x40, 0xF0, 0xB5, 0x80, +0x07, 0xA8, 0xFF, 0xF7, 0x3F, 0xFF, 0x47, 0x44, 0x07, 0x9B, 0x80, 0xB2, 0xBF, 0xB2, 0xB8, 0xF1, 0x00, 0x0F, 0x0A, 0xD0, +0x02, 0x9A, 0x42, 0x44, 0x94, 0x46, 0x14, 0xF8, 0x01, 0x1B, 0xE2, 0x18, 0x92, 0x1B, 0x64, 0x45, 0x02, 0xF8, 0x41, 0x1C, +0xF7, 0xD1, 0xD5, 0xF8, 0xE0, 0x40, 0x07, 0x44, 0x43, 0x44, 0xE2, 0x07, 0xBF, 0xB2, 0x07, 0x93, 0x1A, 0xD5, 0xB4, 0x4A, +0x07, 0xCA, 0x0A, 0xAE, 0x03, 0xC6, 0x00, 0x20, 0x0A, 0xA9, 0x32, 0x80, 0xAD, 0xF8, 0x36, 0x00, 0xCD, 0xF8, 0x32, 0x00, +0x8D, 0xF8, 0x30, 0x00, 0x5B, 0x1A, 0x0C, 0xA8, 0xDD, 0x22, 0x01, 0xE0, 0x11, 0xF8, 0x01, 0x2F, 0x5A, 0x54, 0x88, 0x42, +0xFA, 0xD1, 0x07, 0x9B, 0x09, 0x37, 0x09, 0x33, 0xBF, 0xB2, 0x07, 0x93, 0xA6, 0x07, 0x04, 0xD5, 0xA6, 0x4B, 0x93, 0xF8, +0x76, 0x31, 0xDC, 0x07, 0x53, 0xD4, 0xA5, 0x4B, 0x9B, 0x7D, 0x01, 0x2B, 0x5A, 0xD0, 0xD5, 0xF8, 0xE0, 0x30, 0x18, 0x07, +0x04, 0xD5, 0xA0, 0x4A, 0x92, 0xF8, 0x76, 0x21, 0x51, 0x07, 0x3C, 0xD4, 0x5A, 0x07, 0x22, 0xD5, 0x9C, 0x4D, 0x95, 0xF8, +0x76, 0x31, 0x9B, 0x07, 0x1D, 0xD5, 0x03, 0x99, 0x9B, 0x4B, 0x9C, 0x4C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, +0x07, 0xA8, 0x93, 0xF8, 0xC0, 0x14, 0xD4, 0xF8, 0x50, 0x21, 0x90, 0x47, 0x07, 0x44, 0x28, 0x8F, 0xD4, 0xF8, 0x4C, 0x61, +0x01, 0xF0, 0x9A, 0xFC, 0x95, 0xF8, 0x75, 0x21, 0x04, 0x2A, 0x01, 0x46, 0x08, 0xBF, 0x03, 0x22, 0x07, 0xA8, 0xB0, 0x47, +0xBF, 0xB2, 0x38, 0x44, 0x87, 0xB2, 0x18, 0x9B, 0x1A, 0x68, 0x07, 0x9B, 0x9B, 0x1A, 0x19, 0x9A, 0x38, 0x46, 0x13, 0x80, +0x0F, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x7F, 0x30, 0x07, 0x9B, 0x28, 0x44, 0x05, 0xF1, 0x7F, 0x02, 0x12, 0xF8, 0x01, 0xCB, +0xD1, 0x18, 0x49, 0x1B, 0x90, 0x42, 0x01, 0xF8, 0x7E, 0xCC, 0xF7, 0xD1, 0x2B, 0xE7, 0x82, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, +0x44, 0x31, 0x98, 0x47, 0x38, 0x44, 0xD5, 0xF8, 0xE0, 0x30, 0x87, 0xB2, 0xB8, 0xE7, 0x7D, 0x4B, 0x07, 0xA8, 0xD3, 0xF8, +0x48, 0x31, 0x98, 0x47, 0x78, 0x4B, 0x9B, 0x7D, 0x38, 0x44, 0x01, 0x2B, 0x87, 0xB2, 0xA4, 0xD1, 0xB5, 0xF8, 0xE4, 0x30, +0x00, 0x2B, 0xA0, 0xD0, 0x07, 0x9B, 0x36, 0x22, 0x1A, 0x70, 0x07, 0x9B, 0x03, 0x22, 0x5A, 0x70, 0x07, 0x9B, 0xB5, 0xF8, +0xE4, 0x20, 0x5A, 0x80, 0x95, 0xF8, 0xE6, 0x20, 0x1A, 0x71, 0x07, 0x9B, 0x05, 0x37, 0x05, 0x33, 0xBF, 0xB2, 0x07, 0x93, +0x8D, 0xE7, 0x07, 0x9B, 0x21, 0x22, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x02, 0x22, 0x59, 0x1C, 0x07, 0x91, +0x0A, 0xA8, 0x1A, 0x70, 0x0D, 0xF1, 0x27, 0x01, 0xDB, 0xF7, 0x8E, 0xFE, 0xD5, 0xF8, 0xA4, 0x30, 0x9D, 0xF9, 0x28, 0x20, +0x93, 0xF9, 0x04, 0x30, 0x9A, 0x42, 0xC8, 0xBF, 0x8D, 0xF8, 0x28, 0x30, 0x07, 0x9B, 0x9D, 0xF8, 0x27, 0x20, 0x59, 0x1C, +0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x9D, 0xF8, 0x28, 0x20, 0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x24, 0x22, +0x59, 0x1C, 0x07, 0x91, 0x1A, 0x70, 0x07, 0x9B, 0x04, 0x93, 0x1A, 0x46, 0x02, 0xF1, 0x01, 0x0B, 0xD5, 0xF8, 0xA4, 0x30, +0xCD, 0xF8, 0x1C, 0xB0, 0x9B, 0x78, 0x4F, 0x4A, 0x00, 0x2B, 0x52, 0xD1, 0x01, 0x23, 0x92, 0xF8, 0x72, 0xA1, 0x05, 0x93, +0x76, 0x32, 0xBA, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x8C, 0x80, 0x00, 0x21, 0x06, 0x95, 0x01, 0x91, 0x08, 0x46, 0x8E, 0x46, +0xA1, 0x46, 0x0D, 0x46, 0x1A, 0x96, 0xD3, 0x78, 0x13, 0xF0, 0x02, 0x03, 0x1F, 0xD1, 0x94, 0x78, 0xB2, 0xF8, 0x00, 0xC0, +0x00, 0x2C, 0x43, 0xD1, 0xAC, 0xF6, 0x6C, 0x14, 0x48, 0x2C, 0x3A, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x9C, 0x45, 0x6F, 0xD0, +0x40, 0x4C, 0xAC, 0xF6, 0x67, 0x13, 0xA4, 0xFB, 0x03, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0x45, 0xD0, +0xA4, 0xEB, 0x0E, 0x0E, 0x05, 0x9C, 0xA6, 0x45, 0x44, 0xD1, 0x01, 0x30, 0xC0, 0xB2, 0x9E, 0x46, 0x06, 0x32, 0x01, 0x31, +0xCB, 0xB2, 0x9A, 0x45, 0xD7, 0xD8, 0x01, 0x9B, 0x1A, 0x9E, 0x03, 0xF1, 0x02, 0x0E, 0x29, 0x46, 0x5F, 0xFA, 0x8E, 0xF3, +0x06, 0x9D, 0x4C, 0x46, 0x9E, 0x46, 0x0B, 0xF1, 0x01, 0x02, 0x07, 0x92, 0x8B, 0xF8, 0x00, 0x10, 0x07, 0x9A, 0x51, 0x1C, +0x07, 0x91, 0x06, 0x37, 0x10, 0x70, 0x04, 0x9A, 0x1E, 0xFA, 0x87, 0xF7, 0xBF, 0xB2, 0x13, 0x70, 0xC0, 0xE6, 0x04, 0x23, +0x92, 0xF8, 0x73, 0xA1, 0x05, 0x93, 0xCA, 0x32, 0xAB, 0xE7, 0xD8, 0xB9, 0x86, 0x46, 0x05, 0x46, 0x01, 0x20, 0xD5, 0xE7, +0x01, 0x2C, 0xF8, 0xD1, 0xAC, 0xF5, 0x9C, 0x5C, 0xAC, 0xF1, 0x0D, 0x04, 0xA4, 0xB2, 0xB4, 0xF5, 0x4D, 0x7F, 0xF0, 0xD8, +0x1D, 0x4B, 0xAC, 0xF1, 0x08, 0x0C, 0xA3, 0xFB, 0x0C, 0x43, 0x9C, 0x08, 0xC3, 0xF3, 0x87, 0x03, 0x00, 0x28, 0xB9, 0xD1, +0x9E, 0x46, 0x1D, 0x46, 0x01, 0x20, 0xBD, 0xE7, 0x0B, 0xF1, 0x01, 0x04, 0x07, 0x94, 0x8B, 0xF8, 0x00, 0x50, 0x07, 0x9C, +0x01, 0x9E, 0x04, 0xF1, 0x01, 0x0C, 0x06, 0xF1, 0x02, 0x0E, 0xCD, 0xF8, 0x1C, 0xC0, 0x00, 0xF1, 0x02, 0x0C, 0x20, 0x70, +0x5F, 0xFA, 0x8E, 0xF0, 0x01, 0x90, 0xDD, 0xF8, 0x1C, 0xB0, 0x9E, 0x46, 0x5F, 0xFA, 0x8C, 0xF0, 0xA4, 0xE7, 0x04, 0x22, +0x17, 0x46, 0x26, 0xE6, 0x0E, 0x23, 0x1C, 0x46, 0x94, 0xE7, 0x02, 0x23, 0x50, 0x46, 0x51, 0x46, 0x9E, 0x46, 0xA8, 0xE7, +0x2C, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xCD, 0xCC, 0xCC, 0xCC, 0x03, 0x22, 0x00, 0x23, 0x30, 0xB4, 0x02, 0x70, 0x43, 0x70, 0x4B, 0x7C, 0x83, 0x70, 0x0B, 0x7C, +0x8C, 0x7B, 0xCA, 0x7B, 0x4D, 0x89, 0xA0, 0xF8, 0x05, 0x50, 0x9B, 0x00, 0x43, 0xEA, 0x44, 0x03, 0x43, 0xEA, 0x82, 0x13, +0xA0, 0xF8, 0x03, 0x30, 0x0B, 0x89, 0x1B, 0x01, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, +0x30, 0xB4, 0x22, 0xF0, 0x01, 0x02, 0xBD, 0xF8, 0x08, 0x40, 0xA0, 0xF8, 0x05, 0x20, 0x03, 0x25, 0x01, 0x22, 0xA0, 0xF8, +0x03, 0x40, 0x83, 0x70, 0x05, 0x70, 0x42, 0x70, 0x2C, 0xB1, 0x00, 0x23, 0xC3, 0x71, 0x03, 0x72, 0x30, 0xBC, 0x09, 0x20, +0x70, 0x47, 0x4B, 0x89, 0xA0, 0xF8, 0x07, 0x30, 0x30, 0xBC, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x02, 0x23, +0x03, 0x24, 0x04, 0x70, 0x43, 0x70, 0x0B, 0x7C, 0x49, 0x7B, 0x5D, 0xF8, 0x04, 0x4B, 0x82, 0x80, 0x1B, 0x03, 0x9B, 0xB2, +0x01, 0x29, 0x08, 0xBF, 0x43, 0xF4, 0x00, 0x63, 0x43, 0x80, 0x06, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x41, +0x82, 0xB0, 0x16, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x07, 0x46, 0x88, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0xA8, 0xB3, 0x9D, 0xF8, +0x07, 0x40, 0x83, 0x1C, 0x7C, 0xB1, 0x02, 0x34, 0x20, 0x44, 0x00, 0x24, 0x1D, 0x78, 0x25, 0xF0, 0x81, 0x02, 0x7E, 0x2A, +0x03, 0xF1, 0x01, 0x03, 0x03, 0xD0, 0x32, 0x19, 0x01, 0x34, 0x55, 0x70, 0xE4, 0xB2, 0x98, 0x42, 0xF2, 0xD1, 0x0D, 0xF1, +0x07, 0x02, 0x41, 0x46, 0x38, 0x46, 0xFD, 0xF7, 0x7F, 0xFB, 0xB0, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x81, 0x1C, 0x93, 0xB1, +0x02, 0x33, 0x1F, 0x18, 0x0A, 0x78, 0x22, 0xF0, 0x81, 0x00, 0x63, 0x1C, 0x7E, 0x28, 0x06, 0xEB, 0x04, 0x05, 0x01, 0xF1, +0x01, 0x01, 0xDB, 0xB2, 0x03, 0xD0, 0x0B, 0x2B, 0x6A, 0x70, 0x1C, 0x46, 0x01, 0xD8, 0x8F, 0x42, 0xEE, 0xD1, 0x34, 0x70, +0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x04, 0x46, 0x34, 0x70, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x10, 0xB5, 0x14, 0x46, +0xFD, 0xF7, 0xE8, 0xFC, 0x00, 0xB1, 0x80, 0x78, 0x84, 0xF8, 0xDA, 0x00, 0x10, 0xBD, 0x00, 0xBF, 0xF0, 0xB5, 0x83, 0xB0, +0x14, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0x8B, 0xFB, 0x60, 0xB3, 0xD4, 0xF8, 0xA4, 0xE0, 0x9E, 0xF8, 0x02, 0x40, +0x4C, 0xB3, 0x01, 0x2C, 0xBE, 0xF8, 0x00, 0x30, 0x40, 0xD0, 0x00, 0x24, 0x04, 0x25, 0x9D, 0xF8, 0x07, 0x70, 0x02, 0x37, +0xFF, 0xB2, 0x08, 0x2F, 0x8D, 0xF8, 0x07, 0x70, 0x19, 0xD9, 0x05, 0x26, 0x06, 0xEB, 0x00, 0x0C, 0x33, 0x5C, 0x9C, 0xF8, +0x01, 0x10, 0x69, 0xB1, 0x9C, 0x42, 0x25, 0xD0, 0x01, 0x39, 0xC9, 0xB2, 0x00, 0x22, 0x01, 0xE0, 0x9C, 0x42, 0x1F, 0xD0, +0x2B, 0x44, 0x8A, 0x42, 0xDB, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xF7, 0xD1, 0x03, 0x36, 0xF6, 0xB2, 0xF3, 0x1C, 0x9F, 0x42, +0xE6, 0xDC, 0x03, 0xB0, 0xF0, 0xBD, 0xBE, 0xF8, 0x00, 0x30, 0xA3, 0xF6, 0x6C, 0x12, 0x48, 0x2A, 0x12, 0xD8, 0x40, 0xF6, +0xB4, 0x12, 0x93, 0x42, 0x20, 0xD0, 0x12, 0x4A, 0xA3, 0xF6, 0x67, 0x14, 0xA2, 0xFB, 0x04, 0x34, 0xC4, 0xF3, 0x87, 0x04, +0x01, 0x25, 0xC8, 0xE7, 0x9C, 0xF8, 0x02, 0x30, 0x8E, 0xF8, 0x04, 0x30, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x25, 0xC0, 0xE7, +0xA3, 0xF5, 0x9C, 0x53, 0xA3, 0xF1, 0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xB6, 0xD8, 0x05, 0x4C, 0x08, 0x3B, +0xA4, 0xFB, 0x03, 0x34, 0xC4, 0xF3, 0x87, 0x04, 0x04, 0x25, 0xB0, 0xE7, 0x0E, 0x24, 0x01, 0x25, 0xAD, 0xE7, 0x00, 0xBF, +0xCD, 0xCC, 0xCC, 0xCC, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x96, 0xFC, 0x48, 0xB1, 0x83, 0x78, 0xC2, 0x78, 0x43, 0xEA, +0x02, 0x23, 0xA4, 0xF8, 0xE4, 0x30, 0x03, 0x79, 0x84, 0xF8, 0xE6, 0x30, 0x10, 0xBD, 0x84, 0xF8, 0xE6, 0x00, 0xA4, 0xF8, +0xE4, 0x00, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x47, 0x82, 0xB0, 0x1C, 0x46, 0x05, 0x46, 0x0E, 0x46, 0x91, 0x46, 0xFD, 0xF7, +0x49, 0xFB, 0x31, 0x46, 0x07, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x64, 0xFB, 0x57, 0xEA, 0x00, 0x03, 0x72, 0xD0, 0x80, 0x46, +0x0D, 0xF1, 0x07, 0x02, 0x31, 0x46, 0x28, 0x46, 0xFD, 0xF7, 0x7A, 0xFB, 0x82, 0x46, 0x18, 0xB1, 0x9D, 0xF8, 0x07, 0x30, +0x00, 0x2B, 0x65, 0xD0, 0x31, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0x28, 0x46, 0xFD, 0xF7, 0x90, 0xFB, 0x01, 0x46, 0x00, 0x28, +0x58, 0xD1, 0x00, 0x2F, 0x7A, 0xD0, 0xBB, 0x78, 0x38, 0x79, 0x89, 0xF8, 0x00, 0x30, 0x97, 0xF8, 0x03, 0xC0, 0x00, 0x28, +0x08, 0xBF, 0x02, 0x20, 0xBC, 0xF1, 0x0E, 0x0F, 0x0C, 0xF1, 0xFF, 0x33, 0x8C, 0xBF, 0x01, 0x27, 0x00, 0x27, 0x4D, 0xD8, +0x0D, 0x2B, 0x70, 0xD8, 0xBC, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, 0x97, 0x80, 0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF6, 0x67, 0x16, +0x00, 0x29, 0x4A, 0xD0, 0x8D, 0x78, 0xCA, 0x78, 0x91, 0xF8, 0x04, 0xE0, 0x05, 0xF1, 0xFF, 0x38, 0xB8, 0xF1, 0x02, 0x0F, +0x9A, 0xBF, 0x01, 0x35, 0xED, 0xB2, 0x01, 0x25, 0xBC, 0xF1, 0x0E, 0x0F, 0x93, 0xB2, 0x1F, 0xFA, 0x8E, 0xF1, 0x57, 0xD8, +0x02, 0xF1, 0xFF, 0x3C, 0xBC, 0xF1, 0x0D, 0x0F, 0x72, 0xD8, 0x0E, 0x2A, 0x00, 0xF0, 0x90, 0x80, 0x03, 0xEB, 0x83, 0x03, +0x03, 0xF6, 0x67, 0x13, 0x61, 0xB1, 0x0E, 0xF1, 0xFF, 0x32, 0x0D, 0x2A, 0x60, 0xD8, 0xBE, 0xF1, 0x0E, 0x0F, 0x00, 0xF0, +0x9A, 0x80, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x89, 0xB2, 0x4B, 0x4A, 0x92, 0xF8, 0x75, 0x21, 0xAA, 0x42, +0x24, 0xD2, 0x01, 0x2A, 0x67, 0xD0, 0x02, 0x2A, 0x5E, 0xD0, 0x00, 0x2A, 0x08, 0xBF, 0x33, 0x46, 0x15, 0x46, 0x1B, 0xE0, +0x9D, 0xF8, 0x07, 0x30, 0x00, 0x2B, 0xA2, 0xD1, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x2B, 0x22, 0xD8, +0x0C, 0xEB, 0x8C, 0x06, 0x06, 0xF5, 0x9C, 0x56, 0x08, 0x36, 0x00, 0x29, 0xB4, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x31, 0xD0, +0x9A, 0xF8, 0x02, 0x50, 0x01, 0x2D, 0x3A, 0xD0, 0x03, 0x2D, 0x50, 0xD0, 0x0D, 0x46, 0x33, 0x46, 0x27, 0x70, 0x65, 0x70, +0x66, 0x80, 0xA3, 0x80, 0xE1, 0x80, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x98, 0xF8, 0x02, 0x30, 0x98, 0xF8, 0x05, 0x00, +0x89, 0xF8, 0x00, 0x30, 0x98, 0xF8, 0x04, 0xC0, 0x81, 0xE7, 0x4F, 0xF6, 0xFF, 0x76, 0x93, 0xE7, 0x01, 0x3A, 0xA4, 0x2A, +0x19, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0x00, 0x29, 0xB7, 0xD0, 0x0E, 0xF1, 0xFF, 0x3E, +0xBE, 0xF1, 0xA4, 0x0F, 0x0A, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, 0x08, 0x31, 0x89, 0xB2, 0xAB, 0xE7, +0x51, 0x46, 0x55, 0x46, 0x33, 0x46, 0xD1, 0xE7, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xE7, 0x4F, 0xF6, 0xFF, 0x73, 0xE7, 0xE7, +0x4F, 0xF6, 0xFF, 0x73, 0x90, 0xE7, 0x06, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, 0xC4, 0xE7, 0x40, 0xF6, 0xB4, 0x16, 0x69, 0xE7, +0x9E, 0x42, 0x94, 0xBF, 0x28, 0x3B, 0x28, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xBA, 0xE7, 0x02, 0x2D, 0x0F, 0xD0, 0x03, 0xF1, +0x28, 0x05, 0xB5, 0x42, 0x15, 0xDA, 0x3C, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0xB0, 0xE7, 0xA6, 0xF1, 0x0A, 0x03, 0x9B, 0xB2, +0x01, 0x25, 0xAB, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x70, 0xE7, 0x9E, 0x42, 0x03, 0xD8, 0x14, 0x3B, 0x9B, 0xB2, 0x15, 0x46, +0xA2, 0xE7, 0x14, 0x33, 0x9B, 0xB2, 0x15, 0x46, 0x9E, 0xE7, 0x9E, 0x42, 0xF9, 0xD8, 0xA3, 0xF1, 0x27, 0x05, 0xAE, 0x42, +0xF1, 0xDA, 0x3C, 0x3B, 0x9B, 0xB2, 0x15, 0x46, 0x94, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0x67, 0xE7, 0xE4, 0xB8, 0x17, 0x00, +0x70, 0xB5, 0x1D, 0x46, 0x14, 0x46, 0xFD, 0xF7, 0x95, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0x28, 0x48, 0xD0, 0x02, 0x7A, +0xA1, 0x7C, 0x02, 0xF0, 0x0F, 0x03, 0x99, 0x42, 0x40, 0xD0, 0x01, 0x21, 0x29, 0x70, 0xA3, 0x74, 0x22, 0x74, 0xD0, 0xF8, +0x0A, 0x20, 0x13, 0x0A, 0xD1, 0x08, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x03, 0x12, 0x04, 0xBF, 0x40, 0xF6, 0x43, 0x23, +0x63, 0x60, 0xD0, 0xF8, 0x0E, 0x30, 0x18, 0xBF, 0x62, 0x60, 0x1D, 0x0A, 0x03, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x05, 0x12, +0x08, 0xBF, 0x40, 0xF6, 0x47, 0x22, 0x22, 0x60, 0xD0, 0xF8, 0x12, 0x20, 0x95, 0x08, 0x16, 0x0A, 0x02, 0xF0, 0x0F, 0x02, +0x52, 0xEA, 0x06, 0x12, 0x08, 0xBF, 0x12, 0x4A, 0xA2, 0x60, 0xD0, 0xF8, 0x16, 0x20, 0xC3, 0xF3, 0x00, 0x13, 0x50, 0x08, +0x05, 0xF0, 0x04, 0x05, 0x01, 0xF0, 0x02, 0x01, 0x2B, 0x43, 0x00, 0xF0, 0x08, 0x00, 0x49, 0xB2, 0x03, 0x43, 0x0B, 0x43, +0x11, 0x0A, 0x02, 0xF0, 0x0F, 0x02, 0x52, 0xEA, 0x01, 0x12, 0x63, 0x74, 0x0A, 0xBF, 0x07, 0x4B, 0xE2, 0x60, 0xE3, 0x60, +0x01, 0x20, 0x70, 0xBD, 0x40, 0xF6, 0x43, 0x23, 0xC4, 0xE9, 0x00, 0x33, 0xC4, 0xE9, 0x02, 0x33, 0x70, 0xBD, 0x00, 0xBF, +0x32, 0xE4, 0x05, 0x00, 0x22, 0xF3, 0x02, 0x00, 0x38, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0x4A, 0xFB, 0xE8, 0xB1, 0xC2, 0x78, +0x83, 0x78, 0x43, 0xEA, 0x02, 0x23, 0x23, 0x80, 0x23, 0x46, 0x02, 0x79, 0x03, 0xF8, 0x02, 0x2F, 0x04, 0xF1, 0x12, 0x05, +0xC4, 0xF1, 0x03, 0x02, 0xC1, 0x18, 0x89, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0xAB, 0x42, 0xF9, 0xD1, 0x43, 0x7D, 0x82, 0x7D, +0xB0, 0xF8, 0x17, 0x10, 0xA1, 0x61, 0x43, 0xEA, 0x02, 0x23, 0xA3, 0x82, 0xC3, 0x7E, 0x23, 0x77, 0x01, 0x20, 0x38, 0xBD, +0xF8, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xCA, 0xFB, 0xB8, 0xB1, 0xC7, 0x79, 0x43, 0x7A, 0x85, 0x79, 0x02, 0x7A, 0x81, 0x7A, +0xC6, 0x7A, 0x45, 0xEA, 0x07, 0x25, 0x42, 0xEA, 0x03, 0x22, 0xD0, 0xF8, 0x02, 0x70, 0x03, 0x7B, 0x40, 0x7B, 0x27, 0x60, +0x43, 0xEA, 0x00, 0x23, 0x41, 0xEA, 0x06, 0x21, 0xA5, 0x80, 0x21, 0x81, 0xE2, 0x80, 0x63, 0x81, 0x01, 0x20, 0xF8, 0xBD, +0xF0, 0xB5, 0x83, 0xB0, 0x15, 0x46, 0x0D, 0xF1, 0x07, 0x02, 0xFD, 0xF7, 0xC9, 0xFB, 0x00, 0x28, 0x45, 0xD0, 0x9D, 0xF8, +0x07, 0x30, 0xC6, 0x1C, 0xC5, 0xF1, 0x04, 0x04, 0x1E, 0x44, 0x04, 0x44, 0x6B, 0x1E, 0x69, 0x1D, 0x1A, 0x5D, 0x03, 0xF8, +0x01, 0x2F, 0x8B, 0x42, 0xFA, 0xD1, 0x05, 0xF1, 0x10, 0x02, 0x19, 0x5D, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, +0x02, 0x7D, 0x47, 0x7D, 0x83, 0x7D, 0xC4, 0x7D, 0xA9, 0x79, 0x42, 0xEA, 0x07, 0x22, 0x43, 0xEA, 0x04, 0x23, 0x6A, 0x82, +0x4A, 0x10, 0x09, 0x07, 0xAB, 0x82, 0x00, 0xF1, 0x18, 0x03, 0x0E, 0xD5, 0x00, 0xF1, 0x1C, 0x01, 0xB1, 0x42, 0x1C, 0xD8, +0x5F, 0x78, 0x04, 0x7E, 0x83, 0x7E, 0xC0, 0x7E, 0x44, 0xEA, 0x07, 0x24, 0x43, 0xEA, 0x00, 0x20, 0xEC, 0x82, 0x0B, 0x46, +0x28, 0x83, 0x12, 0x07, 0x12, 0xD5, 0x1A, 0x1D, 0xB2, 0x42, 0x0C, 0xD8, 0x58, 0x78, 0x19, 0x78, 0x9A, 0x78, 0xDB, 0x78, +0x41, 0xEA, 0x00, 0x21, 0x42, 0xEA, 0x03, 0x23, 0x01, 0x20, 0x69, 0x83, 0xAB, 0x83, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0x20, +0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0x10, 0xB5, 0x82, 0xB0, 0x14, 0x46, 0x0D, 0xF1, +0x07, 0x02, 0xFD, 0xF7, 0xC7, 0xFB, 0x40, 0xB1, 0xD0, 0xF8, 0x03, 0x30, 0xC4, 0xF8, 0xDC, 0x30, 0x00, 0x38, 0x18, 0xBF, +0x01, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x01, 0x4B, 0xF6, 0xE7, 0x00, 0xBF, 0x00, 0x00, 0x01, 0x80, 0xF8, 0xB5, 0x1D, 0x46, +0x14, 0x46, 0xFD, 0xF7, 0xC7, 0xFB, 0x00, 0x23, 0x2B, 0x70, 0x00, 0xB3, 0xC2, 0x78, 0x61, 0x7C, 0x02, 0xF0, 0x0F, 0x03, +0x99, 0x42, 0x1B, 0xD0, 0x01, 0x26, 0x2E, 0x70, 0x22, 0x74, 0x63, 0x74, 0xB0, 0xF8, 0x05, 0x10, 0x03, 0x79, 0x02, 0x89, +0xB0, 0xF8, 0x0B, 0x70, 0xC5, 0x89, 0x43, 0xEA, 0x01, 0x23, 0x63, 0x60, 0xC1, 0x79, 0x41, 0xEA, 0x02, 0x21, 0x21, 0x60, +0x82, 0x7A, 0x42, 0xEA, 0x07, 0x22, 0xA2, 0x60, 0x43, 0x7B, 0x43, 0xEA, 0x05, 0x23, 0x30, 0x46, 0xE3, 0x60, 0xF8, 0xBD, +0x01, 0x20, 0xF8, 0xBD, 0x10, 0xB5, 0x14, 0x46, 0xFD, 0xF7, 0xAC, 0xFB, 0x40, 0xB1, 0xC3, 0x78, 0x03, 0xF0, 0x07, 0x02, +0xC3, 0xF3, 0xC2, 0x03, 0x22, 0x70, 0x63, 0x70, 0x01, 0x20, 0x10, 0xBD, 0x03, 0x22, 0x05, 0x23, 0x22, 0x70, 0x63, 0x70, +0x10, 0xBD, 0x00, 0xBF, 0x38, 0xB5, 0x07, 0x48, 0x1C, 0x46, 0x15, 0x46, 0xFE, 0x22, 0x10, 0xF0, 0x67, 0xFD, 0x2A, 0x46, +0x21, 0x46, 0x41, 0xF2, 0x03, 0x40, 0xFC, 0xF7, 0x41, 0xFA, 0x00, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x5A, 0xB9, 0x17, 0x00, +0x70, 0xB5, 0x32, 0x4C, 0x08, 0x78, 0x24, 0x68, 0x01, 0x28, 0x19, 0x46, 0x20, 0x70, 0x29, 0xD0, 0x02, 0x28, 0x05, 0xD0, +0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x2E, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x2B, 0x4C, 0x2C, 0x48, 0x23, 0x68, 0x2C, 0x4E, +0x2C, 0x4D, 0x43, 0xF4, 0x80, 0x33, 0x23, 0x60, 0x03, 0x68, 0x2B, 0x4C, 0x23, 0xF0, 0x00, 0x73, 0x03, 0x60, 0x3F, 0x23, +0x33, 0x60, 0x2B, 0x68, 0x28, 0x48, 0x23, 0xF0, 0x01, 0x03, 0x2B, 0x60, 0x23, 0x6D, 0x23, 0xF4, 0x80, 0x23, 0x23, 0x65, +0x03, 0x69, 0x43, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0x0C, 0xFA, 0x00, 0x20, 0x70, 0xBD, +0x20, 0x4B, 0x1B, 0x4C, 0x93, 0xF8, 0xB5, 0x30, 0x0B, 0xBB, 0x23, 0x68, 0x19, 0x4E, 0x1E, 0x4D, 0x43, 0xF0, 0x00, 0x73, +0x23, 0x60, 0x04, 0xF5, 0x00, 0x44, 0x04, 0x23, 0x28, 0x34, 0x33, 0x60, 0x28, 0x60, 0x23, 0x68, 0x23, 0xF4, 0x80, 0x23, +0x23, 0xF0, 0x01, 0x03, 0x23, 0x60, 0x13, 0x4C, 0x13, 0x48, 0x23, 0x6D, 0x43, 0xF4, 0x80, 0x23, 0x23, 0x65, 0x03, 0x69, +0x23, 0xF0, 0x80, 0x03, 0x03, 0x61, 0x41, 0xF2, 0x16, 0x40, 0xFC, 0xF7, 0xE5, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x23, 0x68, +0x09, 0x48, 0x08, 0x4D, 0x23, 0xF0, 0x00, 0x73, 0x23, 0x60, 0x03, 0x68, 0x24, 0x24, 0x43, 0xF4, 0x00, 0x13, 0x03, 0x60, +0x2C, 0x60, 0xE2, 0xE7, 0x74, 0x36, 0x17, 0x00, 0x44, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, 0x98, 0x80, 0x32, 0x40, +0x6C, 0x00, 0x32, 0x40, 0x00, 0x60, 0x50, 0x40, 0x00, 0x00, 0x50, 0x40, 0x2C, 0x19, 0x17, 0x00, 0x70, 0x80, 0x32, 0x40, +0xF8, 0xB5, 0x4C, 0x78, 0x08, 0x78, 0x16, 0x46, 0x1D, 0x46, 0x2C, 0xB3, 0x17, 0x4C, 0x18, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, +0x02, 0xFB, 0x00, 0x44, 0x4F, 0xF4, 0xA4, 0x61, 0x94, 0xF8, 0x22, 0x20, 0x01, 0xFB, 0x02, 0x32, 0x02, 0x23, 0x92, 0xF8, +0x62, 0x70, 0x84, 0xF8, 0x30, 0x30, 0x5F, 0xB9, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xFC, 0xF7, 0x3E, 0xF9, +0x07, 0x70, 0x94, 0xF8, 0x22, 0x20, 0x42, 0x70, 0xFC, 0xF7, 0x68, 0xF9, 0x32, 0x46, 0x29, 0x46, 0x41, 0xF2, 0x05, 0x40, +0xFC, 0xF7, 0x9A, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x04, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x00, 0x30, 0x01, 0x23, +0x80, 0xF8, 0x30, 0x30, 0xEE, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, +0x0C, 0x20, 0x0C, 0x46, 0x17, 0x46, 0x00, 0x21, 0x05, 0x22, 0x1E, 0x46, 0x01, 0x23, 0xFC, 0xF7, 0x17, 0xF9, 0xDF, 0xF8, +0x6C, 0x90, 0xDF, 0xF8, 0x6C, 0x80, 0xD9, 0xF8, 0x24, 0x30, 0x05, 0x46, 0x20, 0x78, 0x98, 0x47, 0x23, 0x78, 0x2B, 0x70, +0x28, 0x46, 0xFC, 0xF7, 0x39, 0xF9, 0x20, 0x78, 0xD9, 0xF8, 0xD8, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0xF0, +0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x98, 0x47, 0x63, 0x78, 0x43, 0xB9, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0A, 0x40, +0xFC, 0xF7, 0x5E, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, +0xFC, 0xF7, 0xEC, 0xF8, 0x00, 0x22, 0x02, 0x70, 0x22, 0x78, 0x05, 0xFB, 0x02, 0x88, 0x98, 0xF8, 0x22, 0x20, 0x42, 0x70, +0xFC, 0xF7, 0x12, 0xF9, 0xE4, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x0C, 0x46, 0x89, 0x78, 0x25, 0x78, 0xDF, 0xF8, 0xAC, 0x80, 0x1E, 0x46, 0x17, 0x46, 0x63, 0x78, 0xA1, 0xB1, 0x00, 0x2B, +0x44, 0xD1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x02, 0xF0, 0xFB, 0x02, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x2E, 0x11, 0x83, 0xF8, 0x31, 0x20, 0x0F, 0x29, 0x1E, 0xD1, 0x0A, 0xE0, +0x2B, 0xBB, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x22, 0xF0, 0x01, 0x02, 0x83, 0xF8, +0x31, 0x20, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x41, 0x20, 0xFC, 0xF7, 0xAB, 0xF8, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x05, 0x85, 0x95, 0xF8, 0x22, 0x30, 0x2A, 0x8C, 0x02, 0x80, 0xC3, 0x70, 0x63, 0x78, 0x83, 0x70, 0xFC, 0xF7, 0xCE, 0xF8, +0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x0D, 0x40, 0xFC, 0xF7, 0x00, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x01, 0x02, 0x83, 0xF8, 0x31, 0x20, 0xD8, 0xE7, +0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x83, 0x93, 0xF8, 0x31, 0x20, 0x42, 0xF0, 0x04, 0x02, 0xB9, 0xE7, 0x00, 0xBF, +0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x31, 0x20, 0x0D, 0x46, 0x4B, 0x4C, 0x91, 0x46, 0x98, 0x46, 0x05, 0x22, +0x01, 0x23, 0x00, 0x21, 0xFC, 0xF7, 0x72, 0xF8, 0x00, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, 0x67, 0x30, 0x82, 0x46, +0x5B, 0xB1, 0x01, 0x23, 0x84, 0xF8, 0x76, 0x31, 0x2F, 0x46, 0x0F, 0xCF, 0x04, 0xF1, 0x0C, 0x06, 0x0F, 0xC6, 0x97, 0xE8, +0x0F, 0x00, 0x86, 0xE8, 0x0F, 0x00, 0x95, 0xF8, 0x68, 0x30, 0x5B, 0xB1, 0x94, 0xF8, 0x76, 0x21, 0x3C, 0x4B, 0x42, 0xF0, +0x02, 0x02, 0x84, 0xF8, 0x76, 0x21, 0x05, 0xF1, 0x20, 0x02, 0x07, 0xCA, 0x83, 0xE8, 0x07, 0x00, 0x95, 0xF8, 0x69, 0x30, +0x93, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x36, 0x4E, 0x43, 0xF0, 0x04, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x05, 0xF1, 0x2C, 0x07, +0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x0F, 0xCF, 0x0F, 0xC6, 0x97, 0xE8, 0x03, 0x00, 0x86, 0xE8, 0x03, 0x00, +0x95, 0xF8, 0x6A, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x76, 0x31, 0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x76, 0x31, 0x95, 0xF8, +0x66, 0x30, 0x84, 0xF8, 0x75, 0x31, 0x4A, 0x46, 0x41, 0x46, 0x41, 0xF2, 0x01, 0x40, 0xFC, 0xF7, 0x8F, 0xF8, 0x94, 0xF8, +0x76, 0x31, 0x13, 0xF0, 0x01, 0x03, 0x14, 0xD1, 0x84, 0xF8, 0x74, 0x31, 0x95, 0xF8, 0x6B, 0x30, 0xB5, 0xF8, 0x64, 0x10, +0x84, 0xF8, 0x77, 0x31, 0x95, 0xF8, 0x6D, 0x20, 0xA1, 0x85, 0x00, 0x2A, 0x14, 0xBF, 0x02, 0x22, 0x01, 0x22, 0x84, 0xF8, +0x78, 0x21, 0xF3, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xDA, 0xF7, 0xE3, 0xFC, 0x94, 0xF8, 0x76, 0x31, 0x01, 0x30, +0x40, 0x10, 0x5B, 0x07, 0x84, 0xF8, 0x74, 0x01, 0xE2, 0xD5, 0x94, 0xF8, 0x75, 0x21, 0x94, 0xF8, 0x44, 0x30, 0x02, 0x2A, +0x88, 0xBF, 0x94, 0xF8, 0x49, 0x20, 0x4F, 0xEA, 0x93, 0x03, 0x88, 0xBF, 0x03, 0xEA, 0x92, 0x13, 0x03, 0xF0, 0x01, 0x03, +0x84, 0xF8, 0x74, 0x30, 0xD0, 0xE7, 0xFF, 0x23, 0x23, 0x81, 0x50, 0x46, 0x8A, 0xF8, 0x00, 0x20, 0xFC, 0xF7, 0x1A, 0xF8, +0x01, 0x21, 0x05, 0x20, 0xFC, 0xF7, 0xE0, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, +0x14, 0xB9, 0x17, 0x00, 0x20, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x41, 0xF2, 0x08, 0x40, 0x97, 0xB0, 0x0C, 0x46, +0x19, 0x46, 0x03, 0x23, 0xFB, 0xF7, 0xD2, 0xFF, 0x4F, 0xF0, 0x00, 0x0A, 0xCD, 0xE9, 0x0C, 0xAA, 0x05, 0x46, 0xAD, 0xF8, +0x2E, 0xA0, 0x8D, 0xF8, 0x2C, 0xA0, 0x08, 0xF0, 0xEB, 0xFB, 0x94, 0xF8, 0x81, 0x70, 0xA2, 0x6F, 0x06, 0x90, 0x4F, 0xF4, +0xA4, 0x61, 0x01, 0xFB, 0x07, 0xF1, 0x12, 0xF0, 0x02, 0x06, 0x07, 0x91, 0x1B, 0xD0, 0x12, 0xF0, 0x04, 0x06, 0x04, 0xF1, +0x14, 0x08, 0x40, 0xF0, 0xDC, 0x81, 0xB1, 0x46, 0x0B, 0xAB, 0x12, 0xF0, 0x20, 0x02, 0x0D, 0xF1, 0x34, 0x0C, 0x02, 0x93, +0x0C, 0xAB, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, 0x04, 0xF1, 0x40, 0x02, 0x0D, 0xF1, 0x2E, 0x03, 0x49, 0x46, 0x40, 0x46, +0x00, 0xF0, 0x00, 0xFE, 0x94, 0xF8, 0x81, 0x30, 0x00, 0xE0, 0x3B, 0x46, 0x00, 0x22, 0xDF, 0xF8, 0xC4, 0x93, 0x20, 0x68, +0x0C, 0x99, 0xB4, 0xF8, 0x04, 0xE0, 0xBD, 0xF8, 0x2E, 0xC0, 0x0E, 0x92, 0x8D, 0xF8, 0x55, 0x20, 0x8D, 0xF8, 0x56, 0x20, +0x9D, 0xF8, 0x2C, 0x20, 0x8D, 0xF8, 0x51, 0x30, 0xCD, 0xF8, 0x4A, 0x00, 0x10, 0x91, 0x8D, 0xF8, 0x50, 0x20, 0xD9, 0xF8, +0xC4, 0x31, 0x11, 0x96, 0xAD, 0xF8, 0x4E, 0xE0, 0xAD, 0xF8, 0x48, 0xC0, 0x0D, 0xF1, 0x2D, 0x02, 0x29, 0x46, 0x0E, 0xA8, +0x98, 0x47, 0x83, 0x46, 0x68, 0x70, 0x00, 0x28, 0x40, 0xF0, 0x1C, 0x81, 0x23, 0x46, 0x2E, 0x78, 0x53, 0xF8, 0x06, 0x0F, +0xDF, 0xF8, 0x70, 0x83, 0x59, 0x68, 0x9A, 0x68, 0x93, 0xF8, 0x0C, 0xE0, 0xD4, 0xF8, 0x78, 0xC0, 0x04, 0x96, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x06, 0xF3, 0x08, 0xEB, 0x03, 0x0A, 0x08, 0x93, 0x0A, 0xF1, 0xB8, 0x03, 0x07, 0xC3, 0x1C, 0xF0, +0x01, 0x0F, 0x83, 0xF8, 0x00, 0xE0, 0x40, 0xF0, 0x06, 0x81, 0xC7, 0x4B, 0x05, 0x93, 0x1C, 0xF0, 0x08, 0x0F, 0x08, 0xD0, +0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x5A, 0x68, 0x42, 0xF0, 0x08, 0x02, 0x5A, 0x60, 0x04, 0x9A, +0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0x94, 0xF8, 0x7E, 0x20, 0x83, 0xF8, 0x2E, 0x21, 0x94, 0xF8, 0x7F, 0x10, +0xB4, 0xF8, 0x7C, 0x20, 0x1A, 0x84, 0x83, 0xF8, 0x2F, 0x11, 0x50, 0x46, 0x09, 0x93, 0x00, 0xF0, 0xBB, 0xFE, 0xA2, 0x6F, +0xD2, 0x06, 0x06, 0xD5, 0x94, 0xF9, 0x80, 0x20, 0x94, 0xF8, 0x80, 0x10, 0x00, 0x2A, 0x80, 0xF2, 0x77, 0x81, 0xBB, 0xF1, +0x00, 0x0F, 0x40, 0xF0, 0x7F, 0x81, 0x05, 0x9B, 0xAF, 0x48, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x34, 0x04, 0x9B, +0xB4, 0xF8, 0xE0, 0x20, 0x4F, 0xF4, 0x1E, 0x7B, 0x0B, 0xFB, 0x03, 0x86, 0xD4, 0xF8, 0xB0, 0x34, 0x96, 0xF8, 0x56, 0x11, +0xC6, 0xF8, 0x68, 0xA2, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x86, 0xF8, 0x30, 0x30, 0x41, 0xF0, 0x10, 0x01, +0xA3, 0x4B, 0x86, 0xF8, 0x56, 0x11, 0x52, 0xBA, 0x4F, 0xF0, 0x01, 0x0A, 0xC6, 0xF8, 0x64, 0x02, 0xB2, 0x86, 0x08, 0x98, +0x86, 0xF8, 0x70, 0xA2, 0x1A, 0x69, 0x9E, 0x49, 0xD9, 0xF8, 0xE0, 0x31, 0x00, 0xF5, 0x18, 0x70, 0x40, 0x44, 0x11, 0x44, +0x98, 0x47, 0x06, 0x9B, 0xAB, 0x70, 0x00, 0x2B, 0x00, 0xF0, 0x9A, 0x80, 0x94, 0xF8, 0xDE, 0x20, 0x86, 0xF8, 0x24, 0x30, +0x00, 0x2A, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x63, 0x60, 0x0A, 0x36, 0xF6, 0xB2, 0x0B, 0xFB, 0x06, 0xF3, 0x08, 0xEB, +0x03, 0x0B, 0x04, 0x93, 0x9B, 0xF8, 0x24, 0x30, 0x53, 0x45, 0x77, 0xD0, 0x02, 0x23, 0x0C, 0x21, 0x49, 0x20, 0xFB, 0xF7, +0xDB, 0xFE, 0x8B, 0xF8, 0x24, 0xA0, 0x06, 0x70, 0x80, 0xF8, 0x01, 0xA0, 0xFB, 0xF7, 0x04, 0xFF, 0x9B, 0xF8, 0x24, 0x30, +0x00, 0x2B, 0x40, 0xF0, 0x48, 0x81, 0x9B, 0xF8, 0x23, 0x30, 0x09, 0x2B, 0x00, 0xF2, 0x43, 0x81, 0x9B, 0xF8, 0x22, 0x00, +0x05, 0x9C, 0xCD, 0xF8, 0x18, 0xA0, 0x9E, 0x23, 0xA4, 0x21, 0x4F, 0xF4, 0xA4, 0x6C, 0x11, 0xFB, 0x00, 0x31, 0x0C, 0xFB, +0x00, 0x4A, 0x4F, 0x23, 0x46, 0x20, 0x13, 0xFB, 0x06, 0x03, 0x7B, 0x4A, 0x05, 0x98, 0x7B, 0x4C, 0x08, 0x95, 0x08, 0xEB, +0xC3, 0x08, 0x04, 0x9B, 0x00, 0xEB, 0xC1, 0x06, 0x13, 0x44, 0x35, 0x46, 0x1E, 0x46, 0xDB, 0xF8, 0x08, 0x22, 0x1A, 0xB3, +0xEF, 0xF3, 0x10, 0x82, 0xD3, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x73, 0x4B, 0x06, 0x9A, 0x1A, 0x60, 0x22, 0x68, 0xA8, 0xF1, +0x28, 0x00, 0x01, 0x32, 0xA5, 0xF1, 0x28, 0x01, 0x04, 0x90, 0x22, 0x60, 0xFC, 0xF7, 0x18, 0xFC, 0xDB, 0xE9, 0x82, 0x21, +0x04, 0x98, 0xCA, 0xF8, 0xC8, 0x24, 0xCA, 0xF8, 0xCC, 0x14, 0xFC, 0xF7, 0x19, 0xFB, 0x22, 0x68, 0x51, 0x1E, 0x2A, 0xB1, +0x66, 0x4B, 0x21, 0x60, 0x1A, 0x68, 0x09, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0xDB, 0xF8, 0x30, 0x22, 0x28, 0x46, 0x41, 0x46, +0x0B, 0xF1, 0x08, 0x0B, 0x08, 0x35, 0x0A, 0xF1, 0x08, 0x0A, 0x22, 0xB1, 0xFC, 0xF7, 0xFA, 0xFB, 0x40, 0x46, 0xFC, 0xF7, +0x01, 0xFB, 0x08, 0xF1, 0x08, 0x08, 0x46, 0x45, 0xC5, 0xD1, 0x40, 0x20, 0x08, 0x9D, 0xFC, 0xF7, 0x5B, 0xFA, 0x05, 0x9A, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x23, 0x93, 0xF8, 0xDE, 0x20, 0x05, 0x9C, 0xD9, 0xF8, 0x0C, 0x32, 0x4F, 0xF4, +0xA4, 0x61, 0x01, 0xFB, 0x07, 0x47, 0x07, 0x99, 0x01, 0x32, 0x21, 0x44, 0x08, 0x46, 0x87, 0xF8, 0xDE, 0x20, 0x98, 0x47, +0x28, 0x46, 0xFB, 0xF7, 0x87, 0xFE, 0x00, 0x20, 0x17, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDA, 0xF8, 0x04, 0x30, 0x05, 0x93, +0x1C, 0xF0, 0x02, 0x0F, 0x43, 0xF0, 0x01, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x3F, 0xF4, 0xEF, 0xAE, 0x45, 0x4B, 0x93, 0xF8, +0x76, 0x31, 0x09, 0x93, 0x13, 0xF0, 0x01, 0x0B, 0x3F, 0xF4, 0xE7, 0xAE, 0x04, 0xF1, 0x14, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, +0x0A, 0xF1, 0xC8, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x0F, 0x00, 0x05, 0x9E, 0x1C, 0xF0, 0x20, 0x0F, 0x46, 0xF0, +0x03, 0x0E, 0x8B, 0xE8, 0x0F, 0x00, 0xCA, 0xF8, 0x04, 0xE0, 0x22, 0xD0, 0x09, 0x9B, 0x58, 0x07, 0x1F, 0xD5, 0x04, 0xF1, +0x40, 0x0E, 0xBE, 0xE8, 0x0F, 0x00, 0x0A, 0xF1, 0xF4, 0x0B, 0xAB, 0xE8, 0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, +0x0F, 0x00, 0xBE, 0xE8, 0x0F, 0x00, 0xAB, 0xE8, 0x0F, 0x00, 0x9E, 0xE8, 0x03, 0x00, 0x46, 0xF0, 0x23, 0x03, 0xCA, 0xF8, +0x04, 0x30, 0x09, 0x9B, 0x8B, 0xE8, 0x03, 0x00, 0x19, 0x07, 0x04, 0xD5, 0x50, 0x46, 0xEC, 0xF7, 0x85, 0xFF, 0xD4, 0xF8, +0x78, 0xC0, 0x1C, 0xF0, 0x04, 0x0F, 0x1F, 0xD0, 0x24, 0x4B, 0x04, 0x9A, 0x93, 0xF8, 0x76, 0x31, 0x13, 0xF0, 0x02, 0x0F, +0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x83, 0xD3, 0xF8, 0x04, 0xC0, 0x02, 0xD1, 0x1C, 0xF0, 0x20, 0x0F, 0x0F, 0xD0, +0x04, 0xF1, 0x34, 0x03, 0x93, 0xE8, 0x07, 0x00, 0x04, 0x9E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x83, 0x03, 0xF1, +0xE8, 0x0E, 0x8E, 0xE8, 0x07, 0x00, 0x4C, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x07, 0x9A, 0x0D, 0x4B, 0x05, 0x93, 0x02, 0xF1, +0xEC, 0x01, 0x19, 0x44, 0x50, 0x46, 0x00, 0xF0, 0x53, 0xFB, 0xD4, 0xF8, 0x78, 0xC0, 0x83, 0x46, 0x81, 0xE6, 0x07, 0x4B, +0x05, 0x93, 0x0B, 0x44, 0x04, 0xF1, 0x34, 0x09, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x43, 0xD0, 0x03, 0x2B, 0x2F, 0xD0, +0xA3, 0xB3, 0x56, 0x46, 0x16, 0xE6, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x1D, 0x66, 0x12, 0x00, 0x00, 0x10, 0x50, 0x40, +0x40, 0x4B, 0x4C, 0x00, 0xC0, 0x67, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x09, 0x9B, 0x0A, 0x09, 0x93, 0xF8, 0x23, 0x00, 0x01, 0xF0, 0x03, 0x01, +0x01, 0xF0, 0x34, 0xF8, 0xBB, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x81, 0xAE, 0x04, 0x9A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x02, 0x83, 0xFF, 0x21, 0x93, 0xF8, 0x23, 0x00, 0x00, 0x22, 0x01, 0xF0, 0x25, 0xF8, 0x74, 0xE6, 0x20, 0x46, 0xFC, 0xF7, +0x61, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xE3, 0xE5, 0x09, 0x4B, 0x01, 0xF5, 0xB2, 0x70, 0x03, 0x44, 0xB4, 0xF8, 0x7C, 0x10, +0x18, 0x46, 0xFC, 0xF7, 0x5D, 0xFF, 0xA2, 0x6F, 0x06, 0x46, 0xD7, 0xE5, 0x07, 0x9B, 0x03, 0xF1, 0x5C, 0x00, 0x05, 0x9B, +0xF1, 0xE7, 0x94, 0xF8, 0xDE, 0x20, 0x1B, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xF0, 0xB5, 0x0C, 0x46, 0x21, 0x4D, 0x09, 0x78, +0x6F, 0x68, 0x1E, 0x46, 0x63, 0x78, 0x01, 0x20, 0x83, 0xB0, 0x98, 0x40, 0xC1, 0xB1, 0x38, 0x43, 0x95, 0xF8, 0x77, 0x31, +0x68, 0x60, 0x5B, 0xB1, 0x05, 0x20, 0x01, 0x92, 0xFC, 0xF7, 0x10, 0xF8, 0x01, 0x28, 0x2C, 0xD0, 0x17, 0xF0, 0xFF, 0x0F, +0x23, 0x78, 0x01, 0x9A, 0x0B, 0xD0, 0x63, 0xB1, 0x41, 0xF2, 0x1A, 0x40, 0x31, 0x46, 0xFB, 0xF7, 0xC9, 0xFD, 0x00, 0x20, +0x03, 0xB0, 0xF0, 0xBD, 0x27, 0xEA, 0x00, 0x00, 0xE4, 0xE7, 0x00, 0x2B, 0xF2, 0xD0, 0x01, 0x23, 0x00, 0x21, 0x31, 0x20, +0x01, 0x92, 0xFB, 0xF7, 0x53, 0xFD, 0x6B, 0x68, 0x01, 0x9A, 0x2E, 0x81, 0x63, 0xB1, 0x00, 0x23, 0x03, 0x70, 0x01, 0x92, +0xFB, 0xF7, 0x7A, 0xFD, 0x01, 0x9A, 0x01, 0x21, 0x10, 0x46, 0xFB, 0xF7, 0x3F, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, +0x95, 0xF8, 0x78, 0x31, 0xF0, 0xE7, 0x02, 0x20, 0xDC, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0x11, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, 0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, +0x22, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, 0x91, 0xFD, 0x20, 0x46, 0x00, 0x21, 0xFB, 0xF7, 0x1F, 0xFF, 0x00, 0x20, +0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0xC2, 0xFF, 0x01, 0x28, 0xEB, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x7F, 0x22, +0xFD, 0xF7, 0xFA, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x3C, 0xB8, 0x15, 0x00, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x10, 0xB5, 0x14, 0x46, 0x0E, 0xDB, +0x0E, 0x4B, 0x19, 0x89, 0xFF, 0x29, 0x04, 0xD0, 0x22, 0x46, 0x41, 0xF2, 0x1A, 0x40, 0xFB, 0xF7, 0x65, 0xFD, 0x20, 0x46, +0x00, 0x21, 0xFB, 0xF7, 0xF3, 0xFE, 0x00, 0x20, 0x10, 0xBD, 0x10, 0x46, 0xFB, 0xF7, 0x96, 0xFF, 0x01, 0x28, 0xEB, 0xD0, +0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x15, 0x32, 0xFD, 0xF7, 0xCE, 0xFD, 0xE4, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xB8, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x46, 0x41, 0xF2, 0x0F, 0x40, +0x19, 0x46, 0xC8, 0x23, 0xFB, 0xF7, 0xDA, 0xFC, 0x22, 0x78, 0x37, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, +0x06, 0x46, 0xD3, 0xF8, 0x4C, 0x51, 0x02, 0x70, 0x00, 0x2D, 0x5C, 0xD0, 0xB5, 0xF8, 0xB4, 0x00, 0xB5, 0xF8, 0x90, 0x10, +0xB5, 0xF8, 0x92, 0x20, 0xD5, 0xF8, 0x94, 0x30, 0xB3, 0x60, 0x70, 0x80, 0xB1, 0x80, 0xF2, 0x80, 0x95, 0xF8, 0xA4, 0x30, +0x33, 0x73, 0xB5, 0xF8, 0x98, 0x30, 0x73, 0x73, 0x08, 0x22, 0x05, 0xF1, 0x88, 0x01, 0x06, 0xF1, 0x0E, 0x00, 0x10, 0xF0, +0x3D, 0xF8, 0x78, 0x22, 0x29, 0x1D, 0x06, 0xF1, 0x16, 0x00, 0x10, 0xF0, 0x37, 0xF8, 0xB5, 0xF8, 0xB4, 0x30, 0x83, 0xB1, +0x00, 0x24, 0x00, 0x22, 0xE1, 0xB2, 0x28, 0x46, 0x0C, 0xF0, 0x2C, 0xFE, 0xA3, 0xB2, 0x06, 0xEB, 0x83, 0x03, 0xB5, 0xF8, +0xB4, 0x20, 0xC3, 0xF8, 0x9C, 0x00, 0x01, 0x34, 0xA3, 0xB2, 0x9A, 0x42, 0xEF, 0xD8, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x16, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x05, 0xF1, 0x7C, 0x03, 0x07, 0xCB, 0x14, 0x4C, 0xC6, 0xF8, +0x8E, 0x00, 0x23, 0x68, 0xC6, 0xF8, 0x92, 0x10, 0x01, 0x33, 0xC6, 0xF8, 0x96, 0x20, 0x28, 0x46, 0x00, 0x22, 0x0A, 0x21, +0x23, 0x60, 0x0C, 0xF0, 0x07, 0xFE, 0x23, 0x68, 0xC6, 0xF8, 0xC4, 0x00, 0x33, 0xB1, 0x0A, 0x4A, 0x01, 0x3B, 0x12, 0x68, +0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x30, 0x46, 0xFB, 0xF7, 0xA3, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x45, 0x80, +0x30, 0x46, 0xFB, 0xF7, 0x9D, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, +0x6C, 0x28, 0x17, 0x00, 0x70, 0xB5, 0x23, 0x4A, 0x0B, 0x78, 0x12, 0x68, 0x0C, 0x46, 0x22, 0x49, 0xB2, 0xF9, 0x00, 0x20, +0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x22, 0xDB, 0x66, 0x88, 0x4F, 0xF6, +0xFF, 0x73, 0x9E, 0x42, 0x0B, 0xD1, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x03, 0xF0, 0xCF, 0x03, 0x85, 0xF8, +0xA2, 0x30, 0x1B, 0x06, 0x1C, 0xD4, 0x00, 0x20, 0x70, 0xBD, 0x31, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x65, 0xFD, 0x00, 0x28, +0xF7, 0xD0, 0x95, 0xF8, 0xA2, 0x30, 0xA5, 0xF8, 0xBA, 0x60, 0x23, 0xF0, 0x30, 0x03, 0x43, 0xF0, 0x10, 0x03, 0x85, 0xF8, +0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x2D, 0xDA, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x40, 0xF2, 0xAF, 0x32, 0xFD, 0xF7, +0x0B, 0xFD, 0xD3, 0xE7, 0x20, 0x78, 0x0C, 0xF0, 0xC9, 0xFB, 0x95, 0xF8, 0xA2, 0x30, 0x03, 0xF0, 0x7F, 0x03, 0x85, 0xF8, +0xA2, 0x30, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x68, 0x8E, 0x15, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0E, 0x46, 0x15, 0x46, 0x1C, 0x46, 0xFB, 0xF7, 0xAF, 0xFE, 0x01, 0x28, +0x4F, 0xD0, 0x2A, 0x46, 0x0C, 0x23, 0x21, 0x46, 0x41, 0xF2, 0x12, 0x40, 0xFB, 0xF7, 0x04, 0xFC, 0x37, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x2A, 0xDB, 0x35, 0x4B, 0x1C, 0x7C, 0xDA, 0xF7, 0x7F, 0xF8, 0x00, 0x28, +0x30, 0xD1, 0xF3, 0x7A, 0x53, 0xB1, 0x32, 0x4B, 0x32, 0x49, 0x9A, 0x68, 0xD1, 0xF8, 0x2C, 0x12, 0x11, 0x66, 0xA3, 0xF5, +0x40, 0x63, 0x4F, 0xF4, 0x80, 0x72, 0x1A, 0x60, 0x2E, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x77, 0x3C, 0x6C, +0x4C, 0xB3, 0x23, 0x7E, 0x2B, 0x70, 0xB3, 0x7A, 0xE3, 0xB9, 0x23, 0x1D, 0x03, 0xCB, 0x1B, 0x88, 0x6B, 0x81, 0xC5, 0xF8, +0x02, 0x00, 0xC5, 0xF8, 0x06, 0x10, 0x28, 0x46, 0xFB, 0xF7, 0x04, 0xFC, 0x00, 0x20, 0xF8, 0xBD, 0x1F, 0x4F, 0x3C, 0x7C, +0xFF, 0x2C, 0xD2, 0xD1, 0x21, 0x49, 0x22, 0x48, 0x40, 0xF2, 0xEB, 0x32, 0xFD, 0xF7, 0xAA, 0xFC, 0x3C, 0x7C, 0xCA, 0xE7, +0xF0, 0x7A, 0xDA, 0xF7, 0x53, 0xF8, 0xCA, 0xE7, 0x1D, 0x48, 0xFC, 0xF7, 0xD1, 0xF8, 0x01, 0x28, 0x0A, 0xD0, 0x3C, 0x6C, +0xDB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xFF, 0x23, 0x28, 0x46, 0x2B, 0x70, 0xFB, 0xF7, 0xE4, 0xFB, 0x20, 0x46, 0xF8, 0xBD, +0x05, 0x22, 0x0C, 0x23, 0x00, 0x21, 0x3B, 0x20, 0xFB, 0xF7, 0xAC, 0xFB, 0x39, 0x6C, 0x03, 0x46, 0x09, 0x7E, 0x03, 0xF8, +0x02, 0x1B, 0x31, 0x89, 0x37, 0x68, 0x74, 0x68, 0xC0, 0xF8, 0x02, 0x70, 0x19, 0x81, 0x5C, 0x60, 0xFB, 0xF7, 0xCE, 0xFB, +0x31, 0x68, 0x72, 0x68, 0x33, 0x89, 0x6B, 0x81, 0xC5, 0xF8, 0x02, 0x10, 0xC5, 0xF8, 0x06, 0x20, 0xBD, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x00, 0xED, 0x00, 0xE0, 0x88, 0x1A, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x60, 0xB8, 0x15, 0x00, 0x08, 0x88, 0x17, 0x00, 0xF8, 0xB5, 0x05, 0x20, 0x0C, 0x46, 0x15, 0x46, +0x1E, 0x46, 0xFB, 0xF7, 0x1F, 0xFE, 0x01, 0x28, 0x3C, 0xD0, 0x1F, 0x4F, 0x3B, 0x68, 0x73, 0xB1, 0x22, 0x78, 0xB2, 0xB1, +0x61, 0x78, 0x01, 0x22, 0x8A, 0x40, 0x13, 0x43, 0x31, 0x46, 0x2A, 0x46, 0x41, 0xF2, 0x18, 0x40, 0x3B, 0x60, 0xFB, 0xF7, +0xD3, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x23, 0x78, 0x3B, 0xB9, 0x2A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x18, 0x40, 0xFB, 0xF7, +0xC9, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x23, 0x00, 0x21, 0x2A, 0x46, 0x22, 0x20, 0xFB, 0xF7, 0x59, 0xFB, 0x23, 0x78, +0x61, 0x78, 0x8B, 0xB1, 0x3A, 0x68, 0x01, 0x23, 0x8B, 0x40, 0x13, 0x43, 0xB3, 0xFA, 0x83, 0xF2, 0x52, 0x09, 0x3B, 0x60, +0x3E, 0x81, 0x02, 0x70, 0xFB, 0xF7, 0x7A, 0xFB, 0x28, 0x46, 0x01, 0x21, 0xFB, 0xF7, 0x40, 0xFD, 0x00, 0x20, 0xF8, 0xBD, +0x3B, 0x68, 0x01, 0x22, 0x8A, 0x40, 0x23, 0xEA, 0x02, 0x03, 0xEB, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, +0xF8, 0xB5, 0x05, 0x20, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFB, 0xF7, 0xD5, 0xFD, 0x01, 0x28, 0x24, 0xD0, 0x13, 0x4C, +0x2B, 0x78, 0x61, 0x68, 0x00, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x84, 0xF8, 0x77, 0x31, 0x81, 0xB9, 0x01, 0x23, 0x05, 0x22, +0x31, 0x20, 0xFB, 0xF7, 0x23, 0xFB, 0x94, 0xF8, 0x77, 0x31, 0xFF, 0x22, 0x22, 0x81, 0x73, 0xB9, 0x03, 0x70, 0xFB, 0xF7, +0x4B, 0xFB, 0x01, 0x21, 0x05, 0x20, 0xFB, 0xF7, 0x11, 0xFD, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF2, 0x14, 0x40, 0xFB, 0xF7, +0x79, 0xFB, 0x00, 0x20, 0xF8, 0xBD, 0x94, 0xF8, 0x78, 0x31, 0xED, 0xE7, 0x02, 0x20, 0xF8, 0xBD, 0xE4, 0xB8, 0x17, 0x00, +0x08, 0xB5, 0x4F, 0xF4, 0xBE, 0x72, 0x00, 0x21, 0x09, 0x48, 0xD8, 0xF7, 0xFB, 0xFE, 0x00, 0x21, 0x05, 0x20, 0xFB, 0xF7, +0xF7, 0xFC, 0x04, 0xF0, 0xFB, 0xFF, 0x04, 0xF0, 0x7D, 0xFA, 0x02, 0xF0, 0x25, 0xF9, 0x09, 0xF0, 0x41, 0xF9, 0xBD, 0xE8, +0x08, 0x40, 0x0E, 0xF0, 0xD5, 0xB8, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xA8, 0xB9, 0x10, 0x4B, 0x93, 0xF8, 0x72, 0x01, +0x76, 0x33, 0xC8, 0xB1, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, 0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x0D, 0xD0, +0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, 0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x05, 0x4B, +0x93, 0xF8, 0x73, 0x01, 0xCA, 0x33, 0xE8, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x70, 0x47, 0x00, 0xBF, +0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB9, 0x4B, 0x1E, 0x0D, 0x2B, 0x31, 0xD8, 0x0E, 0x29, 0x32, 0xD0, 0x01, 0xEB, 0x81, 0x01, +0x01, 0xF6, 0x67, 0x11, 0x19, 0x4B, 0x93, 0xF8, 0x72, 0x01, 0x76, 0x33, 0x60, 0xB3, 0x00, 0xEB, 0x40, 0x00, 0x10, 0xB4, +0x03, 0xEB, 0x40, 0x04, 0x01, 0xE0, 0xA3, 0x42, 0x1A, 0xD0, 0x1A, 0x88, 0x8A, 0x42, 0x18, 0x46, 0x03, 0xF1, 0x06, 0x03, +0xF7, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x28, 0x06, 0xD0, 0x4F, 0xF6, 0xFF, 0x71, 0x0C, 0x4B, 0x93, 0xF8, +0x73, 0x01, 0xCA, 0x33, 0xE4, 0xE7, 0x4B, 0x1E, 0xA4, 0x2B, 0xF5, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, 0x9C, 0x51, +0x08, 0x31, 0xF1, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x4F, 0xF6, 0xFF, 0x71, 0xD0, 0xE7, 0x40, 0xF6, +0xB4, 0x11, 0xCD, 0xE7, 0x70, 0x47, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, 0xF0, 0xB4, 0x03, 0x46, 0x42, 0x48, 0x5C, 0x68, +0x90, 0xF8, 0x75, 0x21, 0xA5, 0x06, 0x2E, 0xD5, 0x93, 0xF8, 0xFA, 0x70, 0x93, 0xF8, 0xFC, 0x50, 0x93, 0xF8, 0x01, 0x61, +0x7C, 0x10, 0xFF, 0x06, 0x4F, 0xEA, 0xD5, 0x05, 0x55, 0xD5, 0x04, 0x24, 0x05, 0xEA, 0xD6, 0x16, 0x90, 0xF8, 0x74, 0x50, +0xB3, 0xF8, 0xC8, 0x00, 0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x94, 0x42, 0x28, 0xBF, 0x14, 0x46, 0x83, 0xF8, 0x2C, 0x41, +0x91, 0xF8, 0xD9, 0x20, 0x04, 0x2A, 0x46, 0xD0, 0xA2, 0x42, 0x28, 0xBF, 0x22, 0x46, 0x04, 0x2A, 0x43, 0xD0, 0xD2, 0xB2, +0x00, 0xF0, 0x0C, 0x00, 0x0C, 0x38, 0x83, 0xF8, 0x2D, 0x21, 0x83, 0xF8, 0x30, 0x51, 0x18, 0xBF, 0x01, 0x20, 0xF0, 0xBC, +0x70, 0x47, 0x90, 0xF8, 0x74, 0x51, 0x60, 0x07, 0x13, 0xD5, 0xD3, 0xF8, 0xE8, 0x00, 0x00, 0xF0, 0x0C, 0x04, 0x04, 0x2C, +0x44, 0xD0, 0x08, 0x2C, 0x0C, 0xBF, 0x04, 0x24, 0x02, 0x24, 0xC0, 0xF3, 0x02, 0x20, 0x04, 0x28, 0x27, 0xD8, 0x85, 0x42, +0x28, 0xBF, 0x05, 0x46, 0xB3, 0xF8, 0xC8, 0x00, 0xCD, 0xE7, 0xB3, 0xF8, 0xC8, 0x00, 0x10, 0xF0, 0x02, 0x04, 0xC0, 0xF3, +0x01, 0x26, 0x28, 0xD0, 0x01, 0x2A, 0x28, 0xBF, 0x01, 0x22, 0x83, 0xF8, 0x2C, 0x21, 0x14, 0x46, 0x91, 0xF8, 0xD9, 0x20, +0xB5, 0x42, 0x28, 0xBF, 0x35, 0x46, 0x04, 0x2A, 0xC2, 0xD1, 0x02, 0x2C, 0x22, 0x46, 0x28, 0xBF, 0x02, 0x22, 0xD2, 0xB2, +0xC2, 0xE7, 0x67, 0x07, 0x09, 0xD5, 0x03, 0x24, 0xA6, 0xE7, 0x04, 0x2C, 0xF3, 0xD1, 0x03, 0x22, 0xBA, 0xE7, 0xB3, 0xF8, +0xC8, 0x00, 0x00, 0x25, 0xA7, 0xE7, 0xA6, 0x07, 0x47, 0xBF, 0x05, 0xF0, 0x01, 0x06, 0x02, 0x24, 0x04, 0xF0, 0x01, 0x04, +0x05, 0xF0, 0x01, 0x06, 0x96, 0xE7, 0xB5, 0x42, 0x83, 0xF8, 0x2C, 0x41, 0x28, 0xBF, 0x35, 0x46, 0x22, 0x46, 0xA5, 0xE7, +0x03, 0x24, 0xBC, 0xE7, 0xE4, 0xB8, 0x17, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, 0x02, 0x28, 0x14, 0xBF, +0x07, 0x20, 0x09, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x00, 0xF0, 0x03, 0x00, 0x01, 0x28, 0x04, 0xD0, +0x02, 0x28, 0x14, 0xBF, 0x07, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x09, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x10, 0xB4, 0x0E, 0x22, +0x04, 0x46, 0x07, 0x20, 0x44, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, +0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xC3, 0x78, 0x33, 0xB9, +0x83, 0x78, 0x33, 0xB9, 0x40, 0x78, 0x00, 0x28, 0x18, 0xBF, 0x01, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x02, 0x20, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x23, 0x40, 0xFA, 0x03, 0xF2, 0x12, 0xF0, 0x01, 0x0F, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, +0x02, 0xD1, 0x0C, 0x2B, 0xF5, 0xD1, 0x19, 0x46, 0x08, 0x46, 0x70, 0x47, 0x68, 0xB1, 0x00, 0x23, 0xC3, 0xF1, 0x0B, 0x02, +0x40, 0xFA, 0x02, 0xF2, 0xD2, 0x07, 0xD9, 0xB2, 0x03, 0xF1, 0x01, 0x03, 0x05, 0xD4, 0x0C, 0x2B, 0xF4, 0xD1, 0xFF, 0x20, +0x70, 0x47, 0x0C, 0x20, 0x70, 0x47, 0xC1, 0xF1, 0x0B, 0x01, 0xC8, 0xB2, 0x70, 0x47, 0x00, 0xBF, 0xF0, 0xB5, 0xDD, 0xE9, +0x05, 0x56, 0x00, 0x24, 0x1C, 0x80, 0x2C, 0x60, 0x34, 0x60, 0x50, 0xB3, 0x84, 0x78, 0xC4, 0xF3, 0x82, 0x0C, 0xBC, 0xF1, +0x02, 0x0F, 0x04, 0xF0, 0x03, 0x04, 0x23, 0xDC, 0x4F, 0xF0, 0x01, 0x0C, 0x04, 0xF1, 0x0D, 0x00, 0x4F, 0xF0, 0x01, 0x0E, +0x0E, 0xFA, 0x00, 0xF0, 0x07, 0x9F, 0x01, 0x38, 0x80, 0xB2, 0x87, 0xF8, 0x00, 0xC0, 0x18, 0x80, 0xF9, 0xB1, 0x09, 0x68, +0xC1, 0xF3, 0xC2, 0x51, 0x01, 0xF1, 0x0D, 0x03, 0x0E, 0xFA, 0x03, 0xF3, 0x01, 0x3B, 0x2B, 0x60, 0x4A, 0xB1, 0x07, 0x29, +0x11, 0xD1, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, 0x14, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, +0xAC, 0xF1, 0x03, 0x00, 0x4F, 0xF0, 0x01, 0x0C, 0x0C, 0xFA, 0x00, 0xFC, 0x5F, 0xFA, 0x8C, 0xFC, 0xD4, 0xE7, 0x33, 0x60, +0xF0, 0xBD, 0x00, 0x2A, 0xF1, 0xD0, 0x03, 0x2C, 0x01, 0xD0, 0x30, 0x60, 0xF0, 0xBD, 0xD3, 0x78, 0xC3, 0xF3, 0xC1, 0x03, +0x10, 0x33, 0x0E, 0xFA, 0x03, 0xF7, 0x01, 0x3F, 0x37, 0x60, 0xF0, 0xBD, 0x00, 0xF0, 0x7F, 0x03, 0x48, 0x2B, 0x31, 0xD8, +0x10, 0xF0, 0x7E, 0x0F, 0x2C, 0xD0, 0x02, 0x3B, 0x46, 0x2B, 0x29, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x26, 0x28, 0x24, 0x28, +0x28, 0x28, 0x28, 0x28, 0x28, 0x35, 0x37, 0x28, 0x28, 0x28, 0x28, 0x28, 0x39, 0x28, 0x28, 0x28, 0x3B, 0x28, 0x3D, 0x28, +0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x3F, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, +0x28, 0x28, 0x41, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, +0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x33, 0x00, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0xFF, 0x20, 0x70, 0x47, +0x60, 0x2B, 0x04, 0xD0, 0x6C, 0x2B, 0x14, 0xBF, 0xFF, 0x20, 0x0B, 0x20, 0x70, 0x47, 0x0A, 0x20, 0x70, 0x47, 0x09, 0x20, +0x70, 0x47, 0x02, 0x20, 0x70, 0x47, 0x04, 0x20, 0x70, 0x47, 0x05, 0x20, 0x70, 0x47, 0x03, 0x20, 0x70, 0x47, 0x06, 0x20, +0x70, 0x47, 0x07, 0x20, 0x70, 0x47, 0x08, 0x20, 0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x4F, 0x90, 0xF8, 0x00, 0xB0, +0xBB, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0xDF, 0xF8, 0x70, 0x80, 0xDF, 0xF8, 0x70, 0xA0, 0xDF, 0xF8, 0x70, 0x90, 0x05, 0x46, +0x0E, 0x46, 0x04, 0x46, 0x00, 0x27, 0x9E, 0xB9, 0x60, 0x78, 0xFF, 0xF7, 0x9B, 0xFF, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x4F, 0xF0, 0x01, 0x03, 0x0E, 0xDB, 0x0B, 0x28, 0x0E, 0xDD, 0x01, 0x34, 0x63, 0x1B, 0x5B, 0x45, +0xED, 0xDB, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0x94, 0xF9, 0x01, 0x30, 0x60, 0x78, 0x00, 0x2B, 0xE7, 0xDB, 0xF2, 0xE7, +0x0B, 0x28, 0x04, 0xDC, 0x03, 0xFA, 0x00, 0xF0, 0x07, 0x43, 0xBF, 0xB2, 0xEB, 0xE7, 0x4F, 0xF4, 0x15, 0x72, 0x51, 0x46, +0x48, 0x46, 0xFD, 0xF7, 0xC5, 0xF9, 0x95, 0xF8, 0x00, 0xB0, 0xE2, 0xE7, 0x5F, 0x46, 0x38, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xB8, 0x15, 0x00, 0xF0, 0xB4, 0x00, 0x24, 0x4F, 0xF6, 0xFF, 0x77, +0x03, 0x26, 0x40, 0xFA, 0x04, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x06, 0xFA, 0x04, 0xF2, 0x41, 0xFA, 0x04, 0xF5, 0x03, 0x2B, +0x27, 0xEA, 0x02, 0x02, 0x05, 0xF0, 0x03, 0x05, 0x0A, 0xD0, 0x03, 0x2D, 0x08, 0xD0, 0xAB, 0x42, 0x28, 0xBF, 0x2B, 0x46, +0xA3, 0x40, 0x02, 0x34, 0x1A, 0x43, 0x10, 0x2C, 0x97, 0xB2, 0xE6, 0xD1, 0x38, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, +0x08, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x41, 0xF2, 0x21, 0x42, 0xD0, 0xF8, 0x90, 0x31, 0x98, 0x78, +0x41, 0xF2, 0x21, 0x53, 0x01, 0x28, 0x14, 0xBF, 0x10, 0x46, 0x18, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0xD0, 0xF8, 0xDC, 0x30, 0xC3, 0xF3, 0x05, 0x60, 0x5B, 0x00, 0x54, 0xBF, 0x40, 0xF4, 0x80, 0x70, 0x40, 0xF4, 0x40, 0x70, +0x70, 0x47, 0x00, 0xBF, 0x10, 0xB5, 0x04, 0x46, 0x0C, 0xF0, 0x86, 0xFB, 0x03, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x5C, 0x31, +0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x05, 0x46, 0x90, 0xF8, 0xB8, 0x00, 0x18, 0xDB, 0x68, 0xB1, 0x05, 0xF1, 0xB8, 0x03, 0x1C, 0x18, +0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x22, 0xF0, 0x80, 0x01, 0x81, 0x42, 0xC8, 0xBF, 0x02, 0xF0, 0x7F, 0x00, 0xA3, 0x42, +0xF5, 0xD1, 0xFF, 0xF7, 0xFF, 0xFE, 0x01, 0x46, 0x28, 0x46, 0x0C, 0xF0, 0x5F, 0xF9, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, +0x38, 0xBD, 0x00, 0x28, 0xE5, 0xD1, 0x05, 0x48, 0x05, 0x49, 0x40, 0xF2, 0xC1, 0x22, 0xFD, 0xF7, 0x25, 0xF9, 0x95, 0xF8, +0xB8, 0x00, 0xDB, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xB0, 0xB8, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x90, 0xF8, 0x56, 0x31, 0xD0, 0xF8, 0x48, 0x71, 0x99, 0xB0, 0x00, 0x2B, 0x00, 0xF0, 0xDB, 0x80, 0xFA, 0x6B, 0x09, 0x92, +0x7A, 0x68, 0x05, 0x92, 0x07, 0xF1, 0x14, 0x04, 0xBA, 0x68, 0x07, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0x50, 0x08, 0x05, 0x46, +0x22, 0x46, 0xB4, 0x46, 0x40, 0x46, 0x07, 0xF1, 0x24, 0x0B, 0x52, 0xF8, 0x04, 0x1B, 0x4C, 0xF8, 0x04, 0x1B, 0x5A, 0x45, +0xD1, 0x68, 0x40, 0xF8, 0x04, 0x1B, 0xF6, 0xD1, 0x13, 0xF0, 0x01, 0x02, 0x06, 0x92, 0x40, 0xF0, 0xC0, 0x80, 0x09, 0x9A, +0xC2, 0xF3, 0xC0, 0x02, 0x06, 0x92, 0x9A, 0x06, 0x00, 0xF1, 0x16, 0x81, 0x98, 0x07, 0x1A, 0xD5, 0xDF, 0xF8, 0x64, 0x93, +0x06, 0xF1, 0x10, 0x0E, 0x31, 0x46, 0x51, 0xF8, 0x04, 0x2B, 0xC2, 0xF3, 0xC2, 0x2A, 0x02, 0xF0, 0x7C, 0x00, 0x5A, 0xEA, +0x00, 0x00, 0xC2, 0xF3, 0xC1, 0x1C, 0x02, 0xEA, 0x09, 0x02, 0x06, 0xD0, 0xD5, 0xF8, 0x50, 0x01, 0x02, 0x43, 0x42, 0xEA, +0x0C, 0x62, 0x41, 0xF8, 0x04, 0x2C, 0x8E, 0x45, 0xE9, 0xD1, 0xD9, 0x06, 0x5C, 0xD5, 0x95, 0xF8, 0x22, 0x10, 0xC3, 0x4A, +0xC3, 0x4B, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x01, 0x20, 0xD3, 0xF8, 0x38, 0x33, 0x0D, 0xF1, 0x3F, 0x02, 0x0D, 0xF1, +0x3E, 0x01, 0x98, 0x47, 0x06, 0xF1, 0x10, 0x03, 0x06, 0x94, 0x08, 0x95, 0x0D, 0xF1, 0x50, 0x09, 0x1C, 0x46, 0x35, 0x46, +0xBA, 0x4B, 0x59, 0xF8, 0x04, 0xAB, 0x55, 0xF8, 0x04, 0x1B, 0x93, 0xF8, 0xBD, 0x30, 0x4F, 0xEA, 0x1A, 0x4A, 0xC1, 0xF3, +0xC7, 0x22, 0xC1, 0xF3, 0xC2, 0x20, 0x5F, 0xFA, 0x81, 0xFC, 0x4F, 0xEA, 0x0A, 0x4A, 0x01, 0xF0, 0x7F, 0x01, 0xD3, 0xB9, +0x0C, 0xF0, 0x7C, 0x0C, 0x50, 0xEA, 0x0C, 0x03, 0x00, 0xF0, 0x29, 0x81, 0xAD, 0x4B, 0x93, 0xF8, 0xBA, 0x30, 0x00, 0x2B, +0x00, 0xF0, 0xF3, 0x80, 0xAB, 0x4B, 0x93, 0xF8, 0x2A, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xED, 0x80, 0x00, 0x28, 0x40, 0xF0, +0x2F, 0x81, 0x09, 0x29, 0x00, 0xF2, 0x2C, 0x81, 0x02, 0xF0, 0x06, 0x02, 0x2D, 0xE1, 0xD9, 0xF7, 0x47, 0xFE, 0xA4, 0x4B, +0x1A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x5A, 0x7D, 0x00, 0x2A, 0x00, 0xF0, 0x02, 0x81, 0x4A, 0xEA, 0x00, 0x20, +0x40, 0xF0, 0xA8, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAC, 0x42, 0xBD, 0xD1, 0x08, 0x9D, 0x06, 0x9C, 0x95, 0xF8, 0x56, 0x31, +0x5A, 0x06, 0x13, 0xD5, 0x94, 0x4A, 0x95, 0xF8, 0x22, 0x30, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x07, 0x9A, +0xD3, 0xF8, 0xC8, 0x31, 0x22, 0xF0, 0x7C, 0x72, 0x00, 0x2B, 0x07, 0x92, 0x04, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x42, 0xEA, +0x03, 0x53, 0x07, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x8D, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0x8C, 0x4A, 0x05, 0x9B, 0x11, 0x68, 0x7B, 0x60, 0x48, 0x1C, 0x07, 0x9B, 0xBB, 0x60, 0x10, 0x60, 0x56, 0xF8, 0x04, 0x3B, +0x44, 0xF8, 0x04, 0x3B, 0x58, 0xF8, 0x04, 0x3B, 0xE3, 0x60, 0xA3, 0x45, 0xF6, 0xD1, 0x28, 0xB1, 0x82, 0x4B, 0x11, 0x60, +0x1B, 0x68, 0x09, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x00, 0x23, 0x85, 0xF8, 0x56, 0x31, 0x38, 0x46, 0x19, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0xD5, 0xF8, 0x4C, 0x01, 0x95, 0xF8, 0x30, 0x21, 0x0D, 0x92, 0xCD, 0xE9, 0x0B, 0x34, 0x00, 0x22, 0x08, 0x92, +0x00, 0xF1, 0x88, 0x0E, 0x0A, 0x92, 0x31, 0x46, 0x82, 0x46, 0x3E, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, +0x83, 0x03, 0x58, 0x89, 0xC0, 0xF3, 0x0D, 0x03, 0x43, 0xF0, 0x80, 0x43, 0x4F, 0xEA, 0xD3, 0x29, 0x19, 0xF0, 0x06, 0x0C, +0x00, 0xF0, 0x8E, 0x80, 0x09, 0xF0, 0x07, 0x09, 0xB9, 0xF1, 0x04, 0x0F, 0x03, 0xF0, 0x7F, 0x0C, 0x00, 0xF0, 0xE5, 0x80, +0xB9, 0xF1, 0x05, 0x0F, 0x00, 0xF0, 0xE4, 0x80, 0xCC, 0xF3, 0xC1, 0x0C, 0x00, 0x2A, 0x00, 0xF0, 0xD1, 0x80, 0x08, 0x98, +0x00, 0x28, 0x40, 0xF0, 0x95, 0x80, 0x08, 0x68, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, 0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, +0x18, 0x43, 0x08, 0x60, 0x01, 0x32, 0x04, 0x2A, 0x01, 0xF1, 0x04, 0x01, 0xCB, 0xD1, 0x05, 0x9A, 0x22, 0xF4, 0xC0, 0x71, +0x08, 0x9A, 0x05, 0x91, 0xDD, 0xE9, 0x0B, 0x34, 0x22, 0xB1, 0x0A, 0x9A, 0x01, 0x32, 0x41, 0xEA, 0xC2, 0x12, 0x05, 0x92, +0x06, 0x9A, 0x00, 0x2A, 0x7E, 0xD1, 0x09, 0x9A, 0x22, 0xF0, 0x08, 0x02, 0x43, 0xF0, 0x02, 0x03, 0xFA, 0x63, 0x9A, 0x06, +0x85, 0xF8, 0x56, 0x31, 0x7F, 0xF5, 0xEA, 0xAE, 0xD5, 0xF8, 0x4C, 0x01, 0x7A, 0x69, 0x90, 0xF8, 0xA0, 0x30, 0xDF, 0xF8, +0x38, 0xE1, 0x05, 0x99, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x0E, 0xEA, 0x02, 0x0E, 0xB3, 0xF8, 0x0A, 0xC0, +0xCC, 0xF3, 0x0D, 0x02, 0xC1, 0xF3, 0xC1, 0x13, 0x42, 0xF0, 0x80, 0x42, 0x11, 0xF4, 0xC0, 0x7F, 0xCC, 0xF3, 0x80, 0x3C, +0x4E, 0xEA, 0x02, 0x01, 0x03, 0xF1, 0xFF, 0x33, 0xDB, 0xB2, 0x80, 0xF8, 0xA1, 0xC0, 0xC0, 0xF8, 0x9C, 0x10, 0x4F, 0xF0, +0x00, 0x02, 0x06, 0x98, 0x00, 0x93, 0x03, 0x90, 0x14, 0xBF, 0x01, 0x23, 0x13, 0x46, 0xCD, 0xE9, 0x01, 0x22, 0x38, 0x46, +0x0C, 0xF0, 0x56, 0xFF, 0x95, 0xF8, 0x56, 0x31, 0xB6, 0xE6, 0x9D, 0xF8, 0x3F, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, +0x0A, 0x00, 0x02, 0xF0, 0x06, 0x02, 0x49, 0xF8, 0x04, 0x0C, 0x00, 0x2A, 0x3F, 0xF4, 0x20, 0xAF, 0x09, 0x29, 0x7F, 0xF6, +0x1D, 0xAF, 0x29, 0x4B, 0x59, 0xF8, 0x04, 0x2C, 0x93, 0xF8, 0xAF, 0x10, 0x12, 0x0C, 0x41, 0xEA, 0x01, 0x21, 0x12, 0x04, +0x0A, 0x43, 0x49, 0xF8, 0x04, 0x2C, 0x0F, 0xE7, 0x08, 0x68, 0xCD, 0xF8, 0x18, 0xC0, 0x20, 0xF0, 0x60, 0x40, 0x20, 0xF4, +0x7F, 0x50, 0x20, 0xF0, 0x3F, 0x00, 0x18, 0x43, 0x08, 0x60, 0x83, 0xE7, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, +0x49, 0xF8, 0x04, 0x0C, 0xFC, 0xE6, 0x9D, 0xF8, 0x3E, 0x20, 0x42, 0xEA, 0x02, 0x22, 0x42, 0xEA, 0x0A, 0x02, 0x49, 0xF8, +0x04, 0x2C, 0xF3, 0xE6, 0x0A, 0x98, 0xAC, 0xEB, 0x00, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0x90, 0x62, 0xE7, +0x09, 0x9A, 0x42, 0xF0, 0x08, 0x02, 0x7F, 0xE7, 0x12, 0xF0, 0x06, 0x02, 0x0B, 0xD0, 0x04, 0x29, 0x09, 0xD8, 0x0C, 0x4B, +0x93, 0xF8, 0xBB, 0x00, 0x40, 0xEA, 0x00, 0x20, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xB5, 0xE7, 0x07, 0x4B, +0xB3, 0xF8, 0xBB, 0x00, 0x40, 0xBA, 0x80, 0xB2, 0x40, 0xEA, 0x0A, 0x00, 0x49, 0xF8, 0x04, 0x0C, 0xAB, 0xE7, 0x00, 0xBF, +0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xBC, 0x34, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0xFF, 0x3F, 0x00, 0xE0, 0x00, 0xC0, 0xFF, 0x1F, 0x0D, 0x98, 0x84, 0x45, +0x0A, 0x98, 0x38, 0xBF, 0x60, 0x46, 0x0A, 0x90, 0x08, 0x98, 0x38, 0xBF, 0x01, 0x20, 0x08, 0x90, 0x27, 0xE7, 0x4F, 0xEA, +0x1C, 0x1C, 0x1D, 0xE7, 0x14, 0xAC, 0x03, 0xF4, 0xC0, 0x69, 0x54, 0xF8, 0x22, 0x40, 0xB9, 0xF5, 0x80, 0x6F, 0x0C, 0xBF, +0x4F, 0xF4, 0x00, 0x39, 0x4F, 0xF4, 0x80, 0x39, 0x24, 0xF4, 0x40, 0x34, 0x44, 0xEA, 0x09, 0x09, 0x40, 0x04, 0x14, 0xAC, +0x4C, 0xBF, 0x49, 0xF4, 0x80, 0x20, 0x29, 0xF4, 0x80, 0x20, 0x44, 0xF8, 0x22, 0x00, 0x4F, 0xEA, 0x1C, 0x1C, 0x01, 0xE7, +0xF0, 0xB4, 0xD2, 0xF8, 0xA4, 0x50, 0x2C, 0x88, 0x30, 0xBB, 0x00, 0x29, 0x44, 0xD0, 0x51, 0x4E, 0x03, 0x46, 0x96, 0xF8, +0x75, 0x01, 0x26, 0x46, 0x01, 0x28, 0x4F, 0xD9, 0x8F, 0x78, 0x17, 0xF0, 0x03, 0x07, 0x3C, 0xD0, 0xAD, 0x78, 0xCB, 0x78, +0x09, 0x79, 0x00, 0x2D, 0x41, 0xD1, 0x5E, 0x1E, 0x0D, 0x2E, 0x40, 0xD8, 0x0E, 0x2B, 0x00, 0xF0, 0x86, 0x80, 0x03, 0xEB, +0x83, 0x03, 0x03, 0xF6, 0x67, 0x13, 0x00, 0x29, 0x47, 0xD0, 0x03, 0x2F, 0x60, 0xD0, 0x02, 0x2F, 0x57, 0xD0, 0x02, 0x20, +0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0x05, 0xE0, 0x3E, 0x4B, 0x93, 0xF8, 0x75, 0x31, 0x5B, 0xB9, 0x18, 0x46, 0x00, 0x21, +0xA2, 0xF8, 0xA8, 0x40, 0x82, 0xF8, 0xD8, 0x30, 0xF0, 0xBC, 0x82, 0xF8, 0xD9, 0x00, 0xA2, 0xF8, 0xAA, 0x10, 0x70, 0x47, +0xC0, 0x78, 0x10, 0xF0, 0x03, 0x00, 0x12, 0xD0, 0x01, 0x28, 0x4F, 0xF6, 0xF6, 0x76, 0x08, 0xBF, 0x0A, 0x26, 0x26, 0x44, +0xB6, 0xB2, 0x51, 0xBB, 0x01, 0x23, 0x34, 0x46, 0x18, 0x46, 0xE5, 0xE7, 0x08, 0x46, 0x0B, 0x46, 0xE2, 0xE7, 0x34, 0x46, +0x39, 0x46, 0x18, 0x46, 0xDE, 0xE7, 0x99, 0xB1, 0x1F, 0x46, 0x26, 0x46, 0x03, 0x46, 0x38, 0x46, 0xB2, 0xE7, 0x01, 0x2D, +0x1A, 0xD0, 0x4F, 0xF6, 0xFF, 0x73, 0xC2, 0xE7, 0x34, 0x46, 0xCF, 0xE7, 0x4F, 0xF6, 0xD8, 0x71, 0x9C, 0x42, 0x94, 0xBF, +0x0C, 0x46, 0x28, 0x24, 0x23, 0x44, 0x9C, 0xB2, 0x03, 0x46, 0x00, 0x21, 0xC6, 0xE7, 0x02, 0x2F, 0x11, 0xD0, 0x03, 0x2F, +0x20, 0xD0, 0x02, 0x20, 0x1C, 0x46, 0x03, 0x46, 0xBE, 0xE7, 0x18, 0x46, 0x01, 0x23, 0x95, 0xE7, 0x5E, 0x1E, 0xA4, 0x2E, +0xE1, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x53, 0x08, 0x33, 0xA1, 0xE7, 0x02, 0x28, 0xDE, 0xD0, 0x03, 0x20, +0x1C, 0x46, 0x00, 0x21, 0x03, 0x46, 0xAB, 0xE7, 0x85, 0xB9, 0x4C, 0x1E, 0x0D, 0x2C, 0x0A, 0xD8, 0x0E, 0x29, 0x19, 0xD0, +0x01, 0xEB, 0x81, 0x01, 0x01, 0xF6, 0x67, 0x11, 0x04, 0x28, 0x94, 0xD1, 0x1C, 0x46, 0x03, 0x23, 0x9C, 0xE7, 0x4F, 0xF6, +0xFF, 0x71, 0xF7, 0xE7, 0x01, 0x2D, 0xFA, 0xD1, 0x4C, 0x1E, 0xA4, 0x2C, 0xF7, 0xD8, 0x01, 0xEB, 0x81, 0x01, 0x01, 0xF5, +0x9C, 0x51, 0x08, 0x31, 0xEC, 0xE7, 0x40, 0xF6, 0xB4, 0x13, 0x7A, 0xE7, 0x40, 0xF6, 0xB4, 0x11, 0xE6, 0xE7, 0x00, 0xBF, +0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x7B, 0x4F, 0xDF, 0xF8, 0x08, 0x92, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x00, 0x73, 0x04, 0x46, 0x93, 0xF8, 0x22, 0x60, 0x58, 0x68, 0x77, 0x4B, 0x1B, 0x68, 0x10, 0xF0, 0x20, 0x0A, 0xB3, 0xF9, +0x00, 0x30, 0x0D, 0x46, 0x90, 0x46, 0x4F, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0x9F, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x04, 0x73, 0x0E, 0x21, 0xB3, 0xF8, 0x06, 0xC1, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, +0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0xB3, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x90, 0x46, +0xB9, 0xF8, 0x50, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, +0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, 0x9B, 0x80, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0x5D, 0x4B, 0x4F, 0xF4, +0x1E, 0x70, 0x00, 0xFB, 0x04, 0x74, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x06, 0x36, 0x94, 0xF8, 0x2C, 0x31, 0x96, 0xF8, +0xC4, 0x11, 0x94, 0xF8, 0x23, 0x00, 0x04, 0x2B, 0x08, 0xBF, 0x03, 0x23, 0xA9, 0x42, 0x28, 0xBF, 0x29, 0x46, 0x99, 0x42, +0x28, 0xBF, 0x19, 0x46, 0x84, 0xF8, 0x2D, 0x11, 0x0B, 0xF0, 0x22, 0xFD, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x08, 0x03, +0x84, 0xF8, 0x56, 0x31, 0xBD, 0xE8, 0xF8, 0x8F, 0x10, 0xF0, 0x04, 0x0B, 0x28, 0xD0, 0x00, 0x2B, 0x58, 0xDB, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x0E, 0x22, 0xB3, 0xF8, 0xEC, 0xC0, 0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, +0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x6A, 0xD1, 0x11, 0xF0, 0xFF, 0x00, 0xF2, 0xD1, +0xB9, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, 0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, +0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x54, 0xD1, 0x10, 0xF0, 0xFF, 0x02, 0xF2, 0xD1, 0xAF, 0xE7, 0x00, 0x2B, 0x3A, 0xDB, +0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x73, 0x03, 0xF1, 0xCB, 0x02, 0x93, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x54, 0xD1, +0x93, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x53, 0x78, 0x01, 0x20, 0x00, 0x2B, 0x48, 0xD1, 0x99, 0xF8, 0x12, 0x30, 0x00, 0x2B, +0x4B, 0xD1, 0x99, 0xF8, 0x11, 0x30, 0x00, 0x2B, 0x49, 0xD1, 0x99, 0xF8, 0x10, 0x20, 0x00, 0x3A, 0x18, 0xBF, 0x01, 0x22, +0x93, 0x45, 0x58, 0x46, 0x28, 0xBF, 0x10, 0x46, 0xC2, 0xB2, 0x89, 0xE7, 0x99, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x3F, 0xF5, +0x5C, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x55, 0x52, 0xFC, 0xF7, 0x99, 0xFD, 0x54, 0xE7, 0x99, 0xF8, 0x76, 0x31, +0x9A, 0x07, 0xA2, 0xD4, 0x1B, 0x49, 0x1D, 0x48, 0x40, 0xF2, 0x62, 0x52, 0xFC, 0xF7, 0x8E, 0xFD, 0x9B, 0xE7, 0x99, 0xF8, +0x76, 0x31, 0xDB, 0x07, 0xC0, 0xD4, 0x16, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x6D, 0x52, 0xFC, 0xF7, 0x83, 0xFD, 0xB9, 0xE7, +0x42, 0x45, 0x28, 0xBF, 0x42, 0x46, 0xD2, 0xB2, 0x62, 0xE7, 0x90, 0x45, 0x28, 0xBF, 0x90, 0x46, 0x4C, 0xE7, 0x52, 0x45, +0x28, 0xBF, 0x52, 0x46, 0xD2, 0xB2, 0x59, 0xE7, 0x40, 0x45, 0x28, 0xBF, 0x40, 0x46, 0x82, 0x46, 0x92, 0xE7, 0x02, 0x20, +0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0xC3, 0x46, 0xB1, 0xE7, 0x03, 0x20, 0xF8, 0xE7, 0x03, 0x22, 0xBA, 0xE7, 0x02, 0x22, +0xB8, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xC4, 0xB8, 0x15, 0x00, 0xD4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x2D, 0xED, 0x02, 0x8B, 0xDF, 0xF8, 0xE4, 0xA3, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x0A, 0xEB, 0x03, 0x06, +0x8B, 0xB0, 0xB6, 0xF8, 0xC2, 0x41, 0x02, 0x93, 0x01, 0x90, 0xD6, 0xF8, 0x90, 0x31, 0x96, 0xF8, 0xC6, 0x51, 0x04, 0x95, +0x00, 0x20, 0xA6, 0xF8, 0xC2, 0x01, 0x98, 0x78, 0x02, 0x9D, 0xD6, 0xF8, 0xC8, 0x31, 0x03, 0x94, 0x03, 0xF0, 0x7F, 0x43, +0x05, 0xF1, 0xEC, 0x0C, 0x24, 0x32, 0x05, 0x93, 0x0A, 0xEB, 0x0C, 0x03, 0xD6, 0xF8, 0xE4, 0x40, 0x96, 0xF8, 0xC5, 0x71, +0x08, 0xEE, 0x10, 0x2A, 0x08, 0xEE, 0x90, 0x3A, 0xA1, 0xF1, 0x24, 0x09, 0x00, 0x28, 0x00, 0xF0, 0xDD, 0x81, 0x1F, 0xFA, +0x89, 0xF8, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0xA9, 0xD9, 0xF8, 0xCC, 0x31, 0xDD, 0x07, 0x05, 0xD5, +0x99, 0xF8, 0x62, 0xB0, 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0x5C, 0x82, 0xD2, 0x4B, 0x93, 0xF8, 0x76, 0xB1, 0x1B, 0xF0, +0x01, 0x0B, 0x40, 0xF0, 0xE9, 0x81, 0xD9, 0x46, 0x48, 0x46, 0x18, 0xEE, 0x90, 0x2A, 0x59, 0x46, 0xFF, 0xF7, 0xF8, 0xFD, +0x02, 0x9B, 0x03, 0xF2, 0xB4, 0x43, 0x18, 0xEE, 0x10, 0x0A, 0x53, 0x44, 0x0D, 0xF1, 0x25, 0x02, 0x41, 0x46, 0xFD, 0xF7, +0xD5, 0xFF, 0x10, 0xF0, 0xFF, 0x09, 0x1F, 0xD0, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x03, 0xAB, 0x9B, 0xF8, +0x62, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x9D, 0x81, 0x9B, 0xF8, 0x8A, 0x10, 0x00, 0x29, 0x00, 0xF0, 0x6F, 0x82, 0x89, 0x45, +0x07, 0xD0, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x01, 0x22, 0x83, 0xF8, 0x8C, 0x20, 0x01, 0x9A, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0xF8, 0x8A, 0x90, 0x18, 0xEE, 0x90, 0x2A, 0x41, 0x46, 0x18, 0xEE, +0x10, 0x0A, 0xFD, 0xF7, 0x25, 0xFF, 0x01, 0x9A, 0x04, 0x99, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x93, 0xF8, +0xC6, 0x21, 0x8A, 0x42, 0x0E, 0xD0, 0xD3, 0xF8, 0x90, 0x11, 0xAC, 0x4B, 0x09, 0x79, 0xD3, 0xF8, 0x40, 0x33, 0x8A, 0x1A, +0x8D, 0xF8, 0x26, 0x20, 0x0D, 0xF1, 0x26, 0x01, 0x0D, 0xF1, 0x27, 0x02, 0x30, 0x46, 0x98, 0x47, 0x01, 0x9B, 0x4F, 0xF4, +0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x00, 0xF2, 0x01, 0x81, 0x00, 0x2C, 0x00, 0xF0, +0x8E, 0x80, 0x01, 0x9B, 0x9F, 0x4E, 0x03, 0x9D, 0xDD, 0xF8, 0x14, 0x90, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x03, 0xA8, +0xB8, 0xF8, 0xC2, 0x21, 0xAA, 0x42, 0x1D, 0xD0, 0x29, 0x46, 0x30, 0x46, 0xFC, 0xF7, 0x1A, 0xFA, 0x94, 0xF8, 0x56, 0x31, +0xB8, 0xF8, 0xC2, 0x21, 0x94, 0xF8, 0x23, 0x00, 0x43, 0xF0, 0x02, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x53, 0x07, 0x4F, 0xF0, +0x00, 0x01, 0x58, 0xBF, 0x4F, 0xF4, 0x80, 0x63, 0xC4, 0xF8, 0x50, 0x11, 0x4E, 0xBF, 0xA4, 0xF8, 0x54, 0x11, 0xA4, 0xF8, +0x54, 0x31, 0x01, 0x21, 0x0B, 0xF0, 0x02, 0xFC, 0x98, 0xF8, 0xC5, 0x31, 0xBB, 0x42, 0x4B, 0xD0, 0x04, 0x2B, 0x94, 0xF8, +0x2C, 0xA1, 0x5F, 0xD0, 0x53, 0x45, 0x28, 0xBF, 0x53, 0x46, 0x04, 0x2B, 0x00, 0xF0, 0x93, 0x80, 0x5F, 0xFA, 0x83, 0xFA, +0x94, 0xF8, 0x2D, 0x31, 0x53, 0x45, 0x3B, 0xD0, 0x63, 0x68, 0x13, 0xF0, 0x20, 0x0B, 0x58, 0xD0, 0x7F, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0x06, 0xC1, 0x0E, 0x22, 0x07, 0x20, 0x4C, 0xFA, +0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, 0x02, 0xD1, 0x11, 0xF0, +0xFF, 0x00, 0xF2, 0xD1, 0x70, 0x4B, 0x07, 0x22, 0xB3, 0xF8, 0x50, 0xE0, 0x0E, 0x23, 0x4E, 0xFA, 0x03, 0xF1, 0x01, 0xF0, +0x03, 0x01, 0x03, 0x29, 0x02, 0xF1, 0xFF, 0x3C, 0xA3, 0xF1, 0x02, 0x03, 0x40, 0xF0, 0xF4, 0x80, 0x1C, 0xF0, 0xFF, 0x02, +0xF1, 0xD1, 0x94, 0xF8, 0x23, 0x00, 0x84, 0xF8, 0x2D, 0xA1, 0x51, 0x46, 0x0B, 0xF0, 0x54, 0xFB, 0x94, 0xF8, 0x56, 0x31, +0x43, 0xF0, 0x08, 0x03, 0x84, 0xF8, 0x56, 0x31, 0xD8, 0xF8, 0xC8, 0x31, 0x03, 0xF0, 0x7F, 0x43, 0x4B, 0x45, 0x08, 0xD0, +0x63, 0x68, 0x9B, 0x06, 0x05, 0xD5, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x24, 0x68, +0x00, 0x2C, 0x7F, 0xF4, 0x7B, 0xAF, 0x0B, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xBA, 0xF1, 0x03, 0x0F, +0x35, 0xD8, 0xBA, 0xF1, 0x02, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x02, 0x0A, 0x9E, 0xE7, 0x13, 0xF0, 0x04, 0x0F, 0x52, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x2B, 0xD0, 0x00, 0x2B, 0xC0, 0xF2, 0xA7, 0x80, 0xB4, 0xF8, 0xEC, 0xC0, 0x0E, 0x22, +0x07, 0x20, 0x4C, 0xFA, 0x02, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF1, 0xFF, 0x31, 0xA2, 0xF1, 0x02, 0x02, +0x40, 0xF0, 0x97, 0x81, 0x11, 0xF0, 0xFF, 0x00, 0xF1, 0xD1, 0x42, 0x4B, 0xB3, 0xF8, 0x38, 0xC0, 0x0E, 0x21, 0x07, 0x22, +0x4C, 0xFA, 0x01, 0xF3, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x02, 0xF1, 0xFF, 0x30, 0xA1, 0xF1, 0x02, 0x01, 0x40, 0xF0, +0x7F, 0x81, 0x10, 0xF0, 0xFF, 0x02, 0xF1, 0xD1, 0xA1, 0xE7, 0x4F, 0xF0, 0x03, 0x0A, 0x6B, 0xE7, 0x00, 0x2B, 0x5E, 0xDB, +0x94, 0xF8, 0xCE, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xDF, 0x81, 0x94, 0xF8, 0xCD, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0xE0, 0x81, +0x94, 0xF8, 0xCC, 0x20, 0x11, 0x1E, 0x18, 0xBF, 0x01, 0x21, 0x2E, 0x4A, 0x93, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD2, 0x81, +0x53, 0x7C, 0x00, 0x2B, 0x40, 0xF0, 0xD0, 0x81, 0x13, 0x7C, 0x1A, 0x1E, 0x18, 0xBF, 0x01, 0x22, 0x8A, 0x42, 0x28, 0xBF, +0x0A, 0x46, 0x7C, 0xE7, 0x25, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x58, 0x07, 0x3F, 0xF5, 0x53, 0xAF, 0x26, 0x49, 0x27, 0x48, +0x40, 0xF2, 0xCD, 0x12, 0xFC, 0xF7, 0xA8, 0xFB, 0x4B, 0xE7, 0x0C, 0x23, 0x05, 0x22, 0x00, 0x21, 0x3B, 0x20, 0xFA, 0xF7, +0xBF, 0xFA, 0x1F, 0x4B, 0xD8, 0xF8, 0x40, 0x20, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x81, 0x46, 0xC0, 0xF2, +0x18, 0x81, 0x13, 0x7E, 0x89, 0xF8, 0x00, 0x30, 0xD6, 0xF8, 0x90, 0x31, 0x99, 0x78, 0x89, 0xF8, 0x02, 0x10, 0x96, 0xF8, +0xC5, 0x11, 0x89, 0xF8, 0x03, 0x10, 0xB3, 0xF8, 0x00, 0xC0, 0xB6, 0xF8, 0x94, 0x01, 0xB6, 0xF8, 0x96, 0x11, 0xA9, 0xF8, +0x08, 0x10, 0xA9, 0xF8, 0x06, 0x00, 0xA9, 0xF8, 0x04, 0xC0, 0x12, 0x7B, 0x89, 0xF8, 0x0A, 0x20, 0xDB, 0x78, 0x89, 0xF8, +0x0B, 0x30, 0x48, 0x46, 0xFA, 0xF7, 0xC4, 0xFA, 0xCC, 0xE6, 0x06, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0xDA, 0x07, 0x9B, 0xD4, +0x07, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xE5, 0x12, 0xFC, 0xF7, 0x6A, 0xFB, 0x94, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x0C, 0xB9, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC4, 0xB8, 0x15, 0x00, +0xE4, 0xB8, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0xB9, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x99, 0x07, 0x3F, 0xF5, 0x53, 0xAF, +0xB7, 0x49, 0xB8, 0x48, 0x4F, 0xF4, 0xED, 0x72, 0xFC, 0xF7, 0x4C, 0xFB, 0x4B, 0xE7, 0x02, 0x2B, 0x08, 0xBF, 0x8B, 0xF8, +0xDB, 0x90, 0x73, 0xE6, 0x82, 0x42, 0x28, 0xBF, 0x02, 0x46, 0x0A, 0xE7, 0x1F, 0xFA, 0x89, 0xF8, 0x41, 0x46, 0x10, 0x46, +0xFB, 0xF7, 0x42, 0xFA, 0x00, 0x28, 0x3F, 0xF4, 0x1A, 0xAE, 0xB6, 0xF8, 0xC2, 0x31, 0x82, 0x78, 0x23, 0xF0, 0x07, 0x03, +0x9B, 0xB2, 0xD1, 0x07, 0x48, 0xBF, 0x43, 0xF0, 0x01, 0x03, 0xA6, 0xF8, 0xC2, 0x31, 0x53, 0x07, 0x7F, 0xF5, 0x0B, 0xAE, +0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xB3, 0xF8, 0xC2, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xA3, 0xF8, +0xC2, 0x21, 0x00, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x89, 0xFB, 0x9A, 0x4B, 0x93, 0xF8, 0x76, 0xB1, +0x1B, 0xF0, 0x06, 0x0B, 0x81, 0x46, 0x3F, 0xF4, 0x0B, 0xAE, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0xFB, 0xF7, 0x9C, 0xFB, +0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x83, 0x46, 0x93, 0xF8, 0x62, 0x20, 0x00, 0x2A, 0x00, 0xF0, +0xAA, 0x80, 0x8E, 0x4B, 0x93, 0xF8, 0x76, 0x31, 0x59, 0x07, 0x7F, 0xF5, 0xF5, 0xAD, 0x18, 0xEE, 0x90, 0x2A, 0x18, 0xEE, +0x10, 0x0A, 0x41, 0x46, 0xFD, 0xF7, 0xD6, 0xFF, 0x00, 0x28, 0x00, 0xF0, 0x09, 0x81, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x31, 0xC3, 0xF3, 0x09, 0x12, 0x15, 0x46, 0xA2, 0xB1, 0x04, 0x23, 0x05, 0x22, +0x00, 0x21, 0x6F, 0x20, 0xFA, 0xF7, 0xFE, 0xF9, 0x01, 0x9B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0xA2, 0x06, 0x92, +0x92, 0xF8, 0x63, 0x10, 0x81, 0x70, 0x05, 0x80, 0xFA, 0xF7, 0x22, 0xFA, 0x06, 0x9A, 0xD2, 0xF8, 0xC8, 0x31, 0x05, 0x9A, +0x03, 0xF0, 0x7F, 0x43, 0x93, 0x42, 0x3F, 0xF4, 0xC5, 0xAD, 0x04, 0x23, 0x05, 0x22, 0x00, 0x21, 0x71, 0x20, 0xFA, 0xF7, +0xE3, 0xF9, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0xD3, 0xF8, 0xC8, 0x21, 0xC2, 0xF3, 0x05, 0x63, +0x52, 0x00, 0x54, 0xBF, 0x43, 0xF4, 0x80, 0x73, 0x43, 0xF4, 0x40, 0x73, 0x03, 0x60, 0xFA, 0xF7, 0x01, 0xFA, 0xAB, 0xE5, +0x02, 0x9B, 0x03, 0xF5, 0xD6, 0x72, 0x52, 0x44, 0x0D, 0xF1, 0x27, 0x03, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x92, +0xFD, 0xF7, 0x92, 0xFE, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x93, 0xAD, 0x06, 0x9A, 0x06, 0x97, 0x03, 0x9F, +0x25, 0x46, 0x4C, 0x46, 0x91, 0x46, 0x08, 0x23, 0x05, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xFA, 0xF7, 0xB3, 0xF9, 0x59, 0xF8, +0x04, 0x1B, 0x80, 0xF8, 0x05, 0xB0, 0x94, 0xF8, 0x63, 0x20, 0x82, 0x71, 0x4F, 0xF0, 0x00, 0x02, 0x01, 0x60, 0x0B, 0xF1, +0x01, 0x0B, 0x02, 0x71, 0xFA, 0xF7, 0xD4, 0xF9, 0xBB, 0xF1, 0x04, 0x0F, 0xE7, 0xD1, 0x03, 0x97, 0x2C, 0x46, 0x06, 0x9F, +0x70, 0xE5, 0x00, 0x2A, 0x7F, 0xF4, 0xE5, 0xAE, 0x45, 0x22, 0x4C, 0x49, 0x4D, 0x48, 0xFC, 0xF7, 0x77, 0xFA, 0xD8, 0xF8, +0x40, 0x20, 0xDC, 0xE6, 0x9B, 0xF8, 0x8C, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x96, 0xAD, 0x9D, 0xF8, 0x25, 0x30, 0x01, 0x2B, +0x7F, 0xF4, 0x91, 0xAD, 0x46, 0x4B, 0x9B, 0xF8, 0x63, 0x00, 0xD3, 0xF8, 0xC0, 0x31, 0x98, 0x47, 0x9B, 0xF8, 0x8A, 0x10, +0x00, 0x29, 0x3F, 0xF4, 0x86, 0xAD, 0x7A, 0xE5, 0x5A, 0x45, 0x28, 0xBF, 0x5A, 0x46, 0xD2, 0xB2, 0x21, 0xE6, 0x83, 0x46, +0x69, 0xE6, 0x18, 0xEE, 0x10, 0x0A, 0x41, 0x46, 0x06, 0x93, 0xFB, 0xF7, 0x77, 0xF9, 0xB0, 0xB1, 0x06, 0x9B, 0x3A, 0x49, +0x93, 0xF8, 0x6C, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x5B, 0x68, 0x13, 0xF0, 0x24, 0x0F, 0x0A, 0xD0, +0x90, 0xF9, 0x02, 0x30, 0x81, 0x78, 0x00, 0x2B, 0x05, 0xDB, 0x10, 0x46, 0x0A, 0x09, 0x01, 0xF0, 0x03, 0x01, 0xFF, 0xF7, +0xDD, 0xFB, 0x01, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0xA3, 0x06, 0x93, 0xD3, 0xF8, 0xCC, 0x31, 0x18, 0x07, +0x7F, 0xF5, 0x2D, 0xAF, 0x02, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6D, 0x20, 0xFA, 0xF7, 0x46, 0xF9, 0x41, 0x46, 0x02, 0x46, +0x07, 0x90, 0x18, 0xEE, 0x10, 0x0A, 0xFD, 0xF7, 0x45, 0xFF, 0x07, 0x9A, 0x10, 0x46, 0xFA, 0xF7, 0x6B, 0xF9, 0x22, 0x4B, +0x1B, 0x69, 0x00, 0x2B, 0x3F, 0xF4, 0x17, 0xAF, 0x02, 0x9B, 0x03, 0xF5, 0xA8, 0x72, 0x18, 0xEE, 0x10, 0x0A, 0x0D, 0xF1, +0x27, 0x03, 0x52, 0x44, 0x41, 0x46, 0xFD, 0xF7, 0x05, 0xFF, 0x9D, 0xF8, 0x27, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x07, 0xAF, +0x10, 0x23, 0x05, 0x22, 0x00, 0x21, 0x6B, 0x20, 0xFA, 0xF7, 0x20, 0xF9, 0x06, 0x9A, 0x11, 0x46, 0x15, 0x46, 0xD2, 0xF8, +0x50, 0xE1, 0xD2, 0xF8, 0x54, 0x21, 0xD1, 0xF8, 0x58, 0x11, 0xD5, 0xF8, 0x5C, 0x51, 0xC5, 0x60, 0xC0, 0xE9, 0x00, 0xE2, +0x81, 0x60, 0xFA, 0xF7, 0x3F, 0xF9, 0xEE, 0xE6, 0x03, 0x21, 0x28, 0xE6, 0x03, 0x22, 0x33, 0xE6, 0x02, 0x22, 0x31, 0xE6, +0x02, 0x21, 0x22, 0xE6, 0x40, 0xF2, 0xFF, 0x33, 0x1D, 0x46, 0xFD, 0xE6, 0xE4, 0xB8, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xD4, 0xB8, 0x15, 0x00, 0xF4, 0xB8, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x94, 0x64, 0x17, 0x00, +0x70, 0xB5, 0x0C, 0x46, 0x84, 0xB0, 0x89, 0x78, 0x0C, 0x4D, 0x26, 0x79, 0x8D, 0xF8, 0x04, 0x10, 0xAD, 0xF8, 0x08, 0x20, +0x01, 0x46, 0x9D, 0xF8, 0x20, 0x20, 0x20, 0x88, 0xE4, 0x78, 0xAD, 0xF8, 0x0A, 0x30, 0xAD, 0xF8, 0x06, 0x00, 0x6B, 0x6C, +0x8D, 0xF8, 0x0C, 0x60, 0x8D, 0xF8, 0x0D, 0x40, 0x8D, 0xF8, 0x05, 0x20, 0x01, 0xA8, 0x98, 0x47, 0x04, 0xB0, 0x70, 0xBD, +0x88, 0x1A, 0x17, 0x00, 0x03, 0x68, 0x30, 0xB4, 0x0C, 0x68, 0x5A, 0x40, 0x84, 0xEA, 0xF2, 0x34, 0x22, 0x44, 0x13, 0x0A, +0x15, 0x02, 0x05, 0xF0, 0xFF, 0x25, 0x03, 0xF0, 0xFF, 0x13, 0x2B, 0x43, 0x63, 0x40, 0x1A, 0x44, 0x83, 0xEA, 0x72, 0x73, +0x1A, 0x44, 0x83, 0xEA, 0xB2, 0x03, 0x1A, 0x44, 0x0B, 0x60, 0x30, 0xBC, 0x02, 0x60, 0x70, 0x47, 0xF8, 0xB5, 0x1F, 0x88, +0xD3, 0xF8, 0x02, 0x50, 0x0B, 0x68, 0x96, 0x88, 0x12, 0x68, 0x03, 0x60, 0x9D, 0xF8, 0x18, 0x40, 0x4B, 0x68, 0x43, 0x60, +0x00, 0x23, 0xFF, 0x2C, 0x83, 0x60, 0x03, 0x73, 0x00, 0xF1, 0x04, 0x01, 0x46, 0xEA, 0x07, 0x46, 0x14, 0xBF, 0x04, 0xF0, +0x07, 0x04, 0x00, 0x24, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x46, 0xFF, 0xF7, 0xC9, 0xFF, 0x2A, 0x46, 0xFF, 0xF7, 0xC6, 0xFF, +0x22, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xC1, 0xBF, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x21, 0xF0, 0x03, 0x06, +0x01, 0xF0, 0x03, 0x01, 0xC1, 0xF1, 0x04, 0x03, 0x37, 0x68, 0x90, 0xF8, 0x0C, 0xC0, 0x85, 0x68, 0xDB, 0xB2, 0x04, 0x36, +0xC9, 0x00, 0x9A, 0x42, 0x83, 0xB0, 0x27, 0xFA, 0x01, 0xF1, 0xB1, 0x46, 0x78, 0xD2, 0xC2, 0xF1, 0x04, 0x04, 0xE3, 0x00, +0x4F, 0xF0, 0xFF, 0x34, 0x4F, 0xF0, 0x00, 0x0B, 0xDC, 0x40, 0x21, 0x40, 0xD8, 0x46, 0x5F, 0x46, 0x0C, 0xEB, 0x02, 0x04, +0x03, 0x2C, 0x52, 0xD8, 0x4F, 0xEA, 0xCC, 0x0C, 0x01, 0xFA, 0x0C, 0xF1, 0x0D, 0x43, 0xB8, 0xF1, 0x00, 0x0F, 0x22, 0xD0, +0xE3, 0x00, 0xC4, 0xF1, 0x04, 0x0A, 0x00, 0x93, 0x4F, 0xEA, 0x88, 0x03, 0x4F, 0xEA, 0xCA, 0x0A, 0x01, 0x1D, 0x01, 0x93, +0x06, 0xEB, 0x88, 0x08, 0xB1, 0x46, 0xD9, 0xF8, 0x00, 0x30, 0x00, 0x9A, 0x03, 0xFA, 0x02, 0xF2, 0xBA, 0xF1, 0x20, 0x0F, +0x42, 0xEA, 0x05, 0x02, 0x09, 0xF1, 0x04, 0x09, 0x14, 0xBF, 0x23, 0xFA, 0x0A, 0xF5, 0x00, 0x25, 0xFF, 0xF7, 0x76, 0xFF, +0xC1, 0x45, 0xEC, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0x99, 0x46, 0x5F, 0x45, 0x20, 0xD9, 0x07, 0xF0, 0x03, 0x07, 0xC7, 0xF1, +0x04, 0x03, 0xDA, 0x00, 0x20, 0x2A, 0xD9, 0xF8, 0x00, 0x10, 0x40, 0xD0, 0x4F, 0xF0, 0xFF, 0x33, 0xD3, 0x40, 0x0B, 0x40, +0xE2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x15, 0x43, 0x27, 0x44, 0x03, 0x2F, 0x2F, 0xD9, 0xC4, 0xF1, 0x04, 0x04, 0xE4, 0x00, +0x20, 0x2C, 0x14, 0xBF, 0xE3, 0x40, 0x00, 0x23, 0x2A, 0x46, 0x01, 0x1D, 0x3C, 0x1F, 0x1D, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, +0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x4F, 0xEA, 0xCC, 0x02, 0xCC, 0xF1, 0x04, 0x0C, 0x4F, 0xEA, +0xCC, 0x0C, 0xBC, 0xF1, 0x20, 0x0F, 0x01, 0xFA, 0x02, 0xF2, 0x42, 0xEA, 0x05, 0x02, 0x18, 0xBF, 0x21, 0xFA, 0x0C, 0xF5, +0x00, 0xF1, 0x04, 0x01, 0x08, 0xBF, 0x00, 0x25, 0x04, 0x3C, 0xFF, 0xF7, 0x33, 0xFF, 0x9A, 0xE7, 0xD7, 0x1A, 0x4F, 0xEA, +0x97, 0x08, 0x1A, 0x46, 0x27, 0xF0, 0x03, 0x0B, 0x8A, 0xE7, 0x3C, 0x46, 0x85, 0x60, 0x04, 0x73, 0x03, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x00, 0x23, 0xC4, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x10, 0x4B, 0x85, 0x68, 0x1B, 0x68, 0x02, 0x7B, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x0D, 0xDB, 0x5A, 0x23, 0xD2, 0x00, 0x03, 0xFA, 0x02, 0xF2, 0x2A, 0x43, 0x21, 0x1D, +0x20, 0x46, 0xFF, 0xF7, 0x0F, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x00, 0x22, 0xFF, 0xF7, 0x0A, 0xBF, 0x03, 0x2A, 0xEF, 0xD9, +0x40, 0xF2, 0x41, 0x12, 0x03, 0x49, 0x04, 0x48, 0xFC, 0xF7, 0xB8, 0xF8, 0x22, 0x7B, 0xE7, 0xE7, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x20, 0xB9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x06, 0x20, 0x83, 0xB0, 0x00, 0x24, 0xCD, 0xE9, +0x00, 0x44, 0x91, 0xF8, 0x3D, 0x90, 0x0D, 0x46, 0x17, 0x46, 0x1E, 0x46, 0xFA, 0xF7, 0x62, 0xFA, 0x09, 0x28, 0x79, 0xD0, +0x01, 0x23, 0x3A, 0x46, 0x31, 0x46, 0x41, 0xF6, 0x01, 0x00, 0xF9, 0xF7, 0xB7, 0xFF, 0x80, 0x46, 0x06, 0x20, 0xFA, 0xF7, +0x55, 0xFA, 0x48, 0xB1, 0x08, 0x26, 0x40, 0x46, 0x88, 0xF8, 0x00, 0x60, 0xF9, 0xF7, 0xDC, 0xFF, 0x20, 0x46, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0xDF, 0xF8, 0xAC, 0xA1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA3, 0x93, 0xF8, 0x62, 0x20, +0x00, 0x2A, 0x4F, 0xD1, 0x93, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x4B, 0xD1, 0xDF, 0xF8, 0x94, 0xB1, 0x5A, 0x4A, 0x5B, 0x49, +0x13, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x13, 0x60, 0x95, 0xF8, 0x3B, 0x30, 0x01, 0x22, 0x02, 0x2B, 0xCA, 0x75, 0x0E, 0xD0, +0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x09, 0xA2, 0x92, 0xF8, 0x64, 0x10, 0x29, 0xB9, 0x53, 0x4C, 0x21, 0x68, 0xB1, 0xF9, +0x00, 0x10, 0x00, 0x29, 0x7F, 0xDB, 0x03, 0x2B, 0x57, 0xD0, 0x3A, 0x46, 0x4F, 0xF4, 0x55, 0x73, 0x31, 0x46, 0x41, 0xF6, +0x02, 0x00, 0xCB, 0xF8, 0x00, 0x50, 0xF9, 0xF7, 0x73, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0xCB, 0xF8, 0x04, 0x00, 0x00, 0x27, +0x02, 0x2B, 0x8B, 0xF8, 0x16, 0x70, 0x4F, 0xD0, 0x9B, 0xF8, 0x1E, 0x60, 0x3E, 0xB3, 0x95, 0xF8, 0x3D, 0x10, 0x44, 0x48, +0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x0E, 0xF0, 0xE4, 0xFA, 0x09, 0x21, 0x06, 0x20, +0xFA, 0xF7, 0x52, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x04, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0xCB, 0xF8, 0x3E, 0x46, +0x01, 0x24, 0x9C, 0xE7, 0x95, 0xF8, 0x3B, 0x30, 0x02, 0x2B, 0xAF, 0xD0, 0x2C, 0x6B, 0x14, 0xF0, 0x20, 0x04, 0x17, 0xD1, +0x09, 0x26, 0x92, 0xE7, 0x02, 0x24, 0x20, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0xA9, 0x68, 0x46, 0x00, 0xF0, +0x75, 0xFD, 0xDD, 0xE9, 0x00, 0x01, 0x28, 0xB1, 0x21, 0xB1, 0x32, 0x46, 0x00, 0xF0, 0x14, 0xFE, 0x01, 0x24, 0x80, 0xE7, +0x00, 0xF0, 0x90, 0xFD, 0x01, 0x24, 0x7C, 0xE7, 0xDF, 0xF8, 0xBC, 0xB0, 0x28, 0x48, 0x01, 0x23, 0x8B, 0xF8, 0x1E, 0x30, +0xFB, 0xF7, 0x8E, 0xFD, 0x8C, 0xE7, 0xE9, 0x8E, 0x05, 0xF1, 0x40, 0x00, 0x02, 0xF0, 0x32, 0xF8, 0x00, 0x28, 0xC4, 0xBF, +0x00, 0x23, 0x85, 0xF8, 0x3B, 0x30, 0x9C, 0xE7, 0x95, 0xF8, 0x3D, 0x10, 0x1F, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, +0x01, 0xA1, 0x06, 0x22, 0x38, 0x31, 0x01, 0x24, 0x8B, 0xF8, 0x16, 0x40, 0x0E, 0xF0, 0x94, 0xFA, 0x09, 0x21, 0x06, 0x20, +0xFA, 0xF7, 0x02, 0xF9, 0x95, 0xF8, 0x3D, 0x00, 0x39, 0x46, 0x06, 0xFB, 0x00, 0xA0, 0x01, 0xF0, 0x7B, 0xF8, 0x3E, 0x46, +0x4D, 0xE7, 0x92, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x09, 0xD0, 0x12, 0x49, 0x12, 0x48, 0x64, 0x22, 0xFB, 0xF7, 0xD8, 0xFF, +0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0B, 0xDA, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x09, 0xA9, 0xD9, 0xF8, +0x40, 0x30, 0x23, 0xB1, 0x09, 0x49, 0x0B, 0x48, 0x65, 0x22, 0xFB, 0xF7, 0xC7, 0xFF, 0x95, 0xF8, 0x3B, 0x30, 0x62, 0xE7, +0x94, 0x40, 0x04, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x40, 0xB9, 0x15, 0x00, +0x7C, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x4C, 0xB9, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, +0x64, 0xBA, 0x17, 0x00, 0x38, 0xB5, 0x0B, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x0F, 0x49, 0x1C, 0x78, 0xFB, 0xF7, 0x7C, 0xFD, +0x06, 0x20, 0xFA, 0xF7, 0x63, 0xF9, 0xA8, 0xB9, 0x0C, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, +0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x00, 0x00, 0xB9, 0x38, 0xBD, 0x09, 0x21, 0x06, 0x20, 0xFA, 0xF7, 0xAA, 0xF8, +0x20, 0x46, 0x01, 0x21, 0x01, 0xF0, 0x26, 0xF8, 0x28, 0x46, 0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x70, 0xB9, 0x15, 0x00, +0x18, 0x88, 0x17, 0x00, 0x08, 0xB5, 0x06, 0x20, 0xFA, 0xF7, 0x42, 0xF9, 0x05, 0x28, 0x04, 0xD0, 0x06, 0x20, 0xFA, 0xF7, +0x3D, 0xF9, 0x06, 0x28, 0x04, 0xD1, 0x01, 0x20, 0x01, 0xF0, 0x9C, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xFA, 0xF7, +0x33, 0xF9, 0x07, 0x28, 0xF5, 0xD0, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x16, 0x4B, 0x00, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x20, 0x00, 0x23, 0x83, 0xB0, 0x9A, 0x42, 0xCD, 0xE9, 0x00, 0x33, 0x15, 0xDB, 0x68, 0x46, 0x01, 0xA9, 0x00, 0xF0, +0xB7, 0xFC, 0x00, 0x98, 0x40, 0xB1, 0x01, 0x99, 0x31, 0xB1, 0x00, 0x22, 0x00, 0xF0, 0x56, 0xFD, 0x00, 0x20, 0x03, 0xB0, +0x5D, 0xF8, 0x04, 0xFB, 0x01, 0x20, 0x01, 0xF0, 0x75, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x06, 0x20, +0xFA, 0xF7, 0x0A, 0xF9, 0x01, 0x28, 0xE4, 0xD0, 0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x8F, 0x72, 0xFB, 0xF7, 0x42, 0xFF, +0xDD, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x80, 0xB9, 0x15, 0x00, 0x93, 0x4B, 0x2D, 0xE9, +0xF0, 0x4F, 0x1B, 0x68, 0x92, 0x4D, 0xB3, 0xF9, 0x00, 0x30, 0x2F, 0x68, 0x00, 0x2B, 0x89, 0xB0, 0xC0, 0xF2, 0x91, 0x80, +0x97, 0xF8, 0x3D, 0x80, 0x8E, 0x4E, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0xD4, 0xF8, 0xCC, 0x31, 0x00, 0x2B, +0x18, 0xDB, 0x6B, 0x7D, 0x33, 0xB9, 0x01, 0x20, 0x01, 0xF0, 0x42, 0xF9, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x00, 0x23, 0x07, 0xA9, 0x06, 0xA8, 0xCD, 0xE9, 0x06, 0x33, 0x00, 0xF0, 0x6B, 0xFC, 0xDD, 0xE9, 0x06, 0x01, 0x01, 0x22, +0x00, 0xF0, 0x0C, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x07, 0xA8, 0x00, 0xF0, 0xE1, 0xFD, 0x00, 0x28, +0x74, 0xD1, 0x01, 0x46, 0x20, 0x23, 0x06, 0x22, 0x0A, 0x20, 0xF9, 0xF7, 0x1D, 0xFE, 0x94, 0xF8, 0xC0, 0x34, 0x05, 0x46, +0x2B, 0xB1, 0xD4, 0xF8, 0xCC, 0x21, 0x22, 0xF0, 0x08, 0x02, 0xC4, 0xF8, 0xCC, 0x21, 0x74, 0x4A, 0x92, 0xF8, 0x04, 0x21, +0x4A, 0xB1, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x08, 0xF2, 0xB1, 0x18, 0xD1, 0xF8, 0x90, 0x01, 0x80, 0x78, 0x01, 0x28, +0x6D, 0xD0, 0x6E, 0x4B, 0x97, 0xF8, 0x3D, 0x00, 0xDB, 0x6C, 0x9D, 0xF8, 0x1C, 0x10, 0x98, 0x47, 0x4F, 0xF4, 0xA4, 0x6B, +0x00, 0x23, 0x2B, 0x60, 0x0B, 0xFB, 0x08, 0xFB, 0x97, 0xF8, 0x3D, 0x20, 0x6A, 0x76, 0x06, 0xEB, 0x0B, 0x0A, 0xDA, 0xF8, +0x64, 0x01, 0xBA, 0xF8, 0x68, 0x21, 0xAB, 0x76, 0x9A, 0xF8, 0x8B, 0x31, 0x6B, 0x77, 0x9A, 0xF8, 0x8C, 0x31, 0xAB, 0x77, +0xDA, 0xF8, 0xCC, 0x31, 0xC5, 0xF8, 0x12, 0x00, 0x13, 0xF0, 0x02, 0x04, 0xEA, 0x82, 0x1B, 0xD0, 0x0B, 0xF1, 0xEC, 0x09, +0x13, 0xF0, 0x04, 0x04, 0xB1, 0x44, 0x6E, 0xD1, 0x21, 0x46, 0x13, 0xF0, 0x08, 0x02, 0x05, 0xF1, 0x18, 0x03, 0x18, 0xBF, +0x0B, 0xF5, 0x8C, 0x72, 0x05, 0xF1, 0x04, 0x0C, 0x02, 0x93, 0x05, 0xF1, 0x08, 0x03, 0xCD, 0xE9, 0x00, 0x3C, 0x18, 0xBF, +0x92, 0x19, 0x48, 0x46, 0x05, 0xF1, 0x10, 0x03, 0xFE, 0xF7, 0x22, 0xFC, 0x28, 0x46, 0xEC, 0x60, 0xF9, 0xF7, 0xF0, 0xFD, +0x03, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xB6, 0xFF, 0x0F, 0xE0, 0x06, 0x20, 0xFA, 0xF7, 0x5A, 0xF8, 0x02, 0x28, 0x3F, 0xF4, +0x69, 0xAF, 0x47, 0x49, 0x47, 0x48, 0x4F, 0xF4, 0xA3, 0x72, 0xFB, 0xF7, 0x91, 0xFE, 0x61, 0xE7, 0x01, 0x20, 0x01, 0xF0, +0xB1, 0xF8, 0x3A, 0x6B, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x66, 0x53, 0x07, 0xC6, 0xF8, 0xB0, 0x24, 0x7F, 0xF5, +0x65, 0xAF, 0xD6, 0xF8, 0xCC, 0x31, 0x00, 0x20, 0x23, 0xF0, 0x0E, 0x03, 0xC6, 0xF8, 0xCC, 0x31, 0x09, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0xD1, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x0C, 0x0F, 0x8C, 0xD0, 0x00, 0x2B, 0x8A, 0xD1, 0xDF, 0xF8, 0xD8, 0x90, +0x02, 0xF5, 0xB2, 0x72, 0xB4, 0x18, 0x9A, 0x46, 0xCB, 0x46, 0x58, 0x46, 0x06, 0x22, 0x21, 0x46, 0x0E, 0xF0, 0xDC, 0xF8, +0x0B, 0xF1, 0x14, 0x0B, 0x18, 0xB3, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x05, 0x0F, 0xF2, 0xD1, 0x2C, 0x49, 0x50, 0x22, +0x01, 0xF1, 0x14, 0x00, 0x0E, 0xF0, 0xFE, 0xF8, 0x29, 0x48, 0x21, 0x46, 0x06, 0x22, 0x0E, 0xF0, 0xF9, 0xF8, 0x01, 0x23, +0xA9, 0xF8, 0x06, 0x30, 0x89, 0xF8, 0x08, 0x30, 0x65, 0xE7, 0x0B, 0xF5, 0xB2, 0x70, 0x0B, 0xF5, 0x86, 0x71, 0x31, 0x44, +0x30, 0x44, 0x05, 0x91, 0xFA, 0xF7, 0x28, 0xFF, 0xDA, 0xF8, 0xCC, 0x31, 0x05, 0x99, 0x04, 0x46, 0x83, 0xE7, 0x0A, 0xEB, +0x8A, 0x03, 0x09, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x8A, 0x0B, 0x9A, 0x79, 0x14, 0x23, 0x03, 0xFB, 0x0A, 0x93, 0x4A, 0xB1, +0xDB, 0x79, 0x53, 0xB1, 0x0B, 0xEB, 0x0A, 0x03, 0x09, 0xEB, 0x83, 0x09, 0x01, 0x23, 0x89, 0xF8, 0x08, 0x30, 0x42, 0xE7, +0x01, 0x22, 0x9A, 0x71, 0xF4, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x08, 0x64, 0x00, 0x92, 0xB4, 0xF8, 0x68, 0x31, +0xB4, 0xF8, 0x66, 0x21, 0xB4, 0xF8, 0x64, 0x11, 0x0C, 0x48, 0xFB, 0xF7, 0x9F, 0xFB, 0xD4, 0xF8, 0xCC, 0x31, 0x23, 0xF0, +0x0C, 0x03, 0xC4, 0xF8, 0xCC, 0x31, 0xDF, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x2C, 0x19, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xB9, 0x15, 0x00, 0xCC, 0x35, 0x17, 0x00, +0xCC, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x06, 0x20, +0xF9, 0xF7, 0xB6, 0xFF, 0x04, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0xB1, 0xFF, 0x09, 0x28, 0x01, 0xD0, 0x00, 0x20, +0x08, 0xBD, 0x00, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xA6, 0xFF, 0x04, 0x28, 0xEA, 0xD0, +0x06, 0x20, 0xF9, 0xF7, 0xA1, 0xFF, 0x00, 0x28, 0xE5, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x9C, 0xFF, 0x09, 0x28, 0xE0, 0xD0, +0x04, 0x49, 0x05, 0x48, 0x4F, 0xF4, 0x16, 0x72, 0xFB, 0xF7, 0xD4, 0xFD, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xE4, 0xB9, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x03, 0xDB, 0x00, 0xF0, 0xCD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x7E, 0xFF, 0x04, 0x28, 0xF6, 0xD0, +0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x79, 0x22, 0xFB, 0xF7, 0xB6, 0xFD, 0x00, 0xF0, 0xBE, 0xFC, 0x00, 0x20, 0x08, 0xBD, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x6C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0xAD, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x5E, 0xFF, +0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x29, 0x32, 0xFB, 0xF7, 0x96, 0xFD, 0x00, 0xF0, 0x9E, 0xFC, +0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x8D, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x06, 0x20, +0xF9, 0xF7, 0x3E, 0xFF, 0x09, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x43, 0x32, 0xFB, 0xF7, 0x76, 0xFD, +0x00, 0xF0, 0x7E, 0xFC, 0x00, 0x20, 0x08, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x9C, 0xBA, 0x15, 0x00, +0x37, 0x4B, 0x30, 0xB5, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x83, 0xB0, 0x37, 0xDB, 0x06, 0x20, 0xF9, 0xF7, +0x21, 0xFF, 0x09, 0x28, 0x10, 0xD0, 0x32, 0x4B, 0x9A, 0x7D, 0x01, 0x2A, 0x50, 0xD0, 0x1B, 0x68, 0x93, 0xF8, 0x3B, 0x30, +0x02, 0x2B, 0x3A, 0xD9, 0x03, 0x2B, 0x3F, 0xD1, 0x2D, 0x48, 0x01, 0xF0, 0xF5, 0xFC, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, +0x29, 0x4C, 0xA2, 0x6A, 0x23, 0x7D, 0x00, 0x25, 0xC2, 0xF8, 0xCC, 0x51, 0x00, 0x2B, 0x40, 0xD1, 0xA0, 0x68, 0x0C, 0x30, +0xF9, 0xF7, 0x90, 0xFC, 0xA3, 0x7D, 0x00, 0x22, 0x01, 0x2B, 0xA2, 0x60, 0x01, 0xD0, 0xA1, 0x7F, 0x61, 0xB3, 0x00, 0x24, +0x01, 0xA9, 0x68, 0x46, 0xCD, 0xE9, 0x00, 0x44, 0x00, 0xF0, 0x8C, 0xFA, 0xDD, 0xE9, 0x00, 0x01, 0x22, 0x46, 0x00, 0xF0, +0x2D, 0xFB, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0xE9, 0xFE, 0x04, 0x28, 0xC2, 0xD0, 0x06, 0x20, +0xF9, 0xF7, 0xE4, 0xFE, 0x09, 0x28, 0xBD, 0xD0, 0x15, 0x49, 0x16, 0x48, 0x40, 0xF2, 0x93, 0x22, 0xFB, 0xF7, 0x1C, 0xFD, +0xB6, 0xE7, 0x00, 0x21, 0x01, 0x20, 0x01, 0xF0, 0x2B, 0xF8, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x01, 0x20, 0x00, 0xF0, +0x35, 0xFF, 0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x20, 0xF9, 0xF7, 0x23, 0xFE, 0xDA, 0xE7, 0x01, 0xF0, 0x48, 0xF9, +0x00, 0x20, 0x03, 0xB0, 0x30, 0xBD, 0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF9, 0xF7, 0x85, 0xFC, 0x25, 0x75, +0xB6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x08, 0xAC, 0x0F, 0x00, 0x70, 0x79, 0x15, 0x00, +0xC8, 0xBA, 0x15, 0x00, 0x4B, 0x88, 0x03, 0xF0, 0xFC, 0x03, 0xB0, 0x2B, 0x10, 0xB5, 0x0C, 0x46, 0x13, 0xD0, 0x10, 0x2B, +0x0A, 0xD0, 0x30, 0x2B, 0x08, 0xD0, 0xC0, 0x2B, 0x01, 0xD0, 0xA0, 0x2B, 0x14, 0xD1, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, +0x01, 0xF0, 0x78, 0xBB, 0x06, 0x20, 0xF9, 0xF7, 0x9B, 0xFE, 0x07, 0x28, 0x13, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x06, 0x20, +0xF9, 0xF7, 0x94, 0xFE, 0x05, 0x28, 0xF8, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0x37, 0xFA, 0xF4, 0xE7, 0xD0, 0x2B, 0xF2, 0xD1, +0x23, 0x7B, 0x08, 0x2B, 0xEF, 0xD1, 0x20, 0x46, 0x01, 0xF0, 0xD4, 0xFB, 0xEB, 0xE7, 0x20, 0x46, 0x01, 0xF0, 0x70, 0xFA, +0xE7, 0xE7, 0x00, 0xBF, 0x10, 0xB5, 0x06, 0x20, 0x0C, 0x46, 0xF9, 0xF7, 0x7B, 0xFE, 0x06, 0x28, 0x01, 0xD0, 0x00, 0x20, +0x10, 0xBD, 0x60, 0x88, 0x01, 0xF0, 0xC8, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, +0x03, 0xD4, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x0D, 0x4C, 0x0D, 0x4A, 0x23, 0x68, 0xD2, 0x7D, 0x01, 0x33, +0x01, 0x2A, 0x23, 0x60, 0x0C, 0xD0, 0x33, 0xB1, 0x07, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x23, 0x60, 0x0B, 0xB9, 0x02, 0xB1, +0x62, 0xB6, 0x07, 0x48, 0xFB, 0xF7, 0x1C, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x00, 0xF0, 0x16, 0xFB, 0x23, 0x68, 0xEE, 0xE7, +0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x4C, 0x36, 0x17, 0x00, 0x28, 0xBB, 0x15, 0x00, 0x38, 0xB5, 0x06, 0x20, +0x0D, 0x46, 0xF9, 0xF7, 0x43, 0xFE, 0x30, 0xB9, 0x04, 0x46, 0x29, 0x88, 0xA8, 0x78, 0x00, 0xF0, 0xB7, 0xFD, 0x20, 0x46, +0x38, 0xBD, 0x02, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x8B, 0x4B, 0x2D, 0xE9, 0xF0, 0x4F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x89, 0xB0, 0x0C, 0x46, 0xC0, 0xF2, 0xFD, 0x80, 0x25, 0x78, 0x00, 0x2D, 0x40, 0xF0, 0xF2, 0x80, 0x63, 0x78, +0x00, 0x93, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x03, 0xF4, 0x82, 0x4B, 0xDF, 0xF8, 0x18, 0xA2, 0x1F, 0x19, 0x4F, 0xF4, +0xA4, 0x6C, 0x97, 0xF8, 0x22, 0xE0, 0x0C, 0xFB, 0x0E, 0xAC, 0x0C, 0xF5, 0xCE, 0x73, 0x0F, 0xCB, 0x07, 0xF1, 0xB8, 0x06, +0x07, 0xC6, 0xDC, 0xF8, 0xCC, 0x81, 0x33, 0x70, 0x18, 0xF0, 0x01, 0x0F, 0x03, 0xD0, 0x7B, 0x68, 0x43, 0xF0, 0x01, 0x03, +0x7B, 0x60, 0x18, 0xF0, 0x02, 0x0F, 0x58, 0xD0, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x0E, 0xA3, 0x03, 0xF1, 0xEC, 0x0B, +0x00, 0x9E, 0x01, 0x93, 0xBB, 0xE8, 0x0F, 0x00, 0xB4, 0x46, 0x6E, 0x4E, 0x4F, 0xF4, 0x1E, 0x79, 0x09, 0xFB, 0x0C, 0x69, +0x09, 0xF1, 0xC8, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x9B, 0xE8, 0x0F, 0x00, 0xD9, 0xF8, 0x04, 0xB0, 0x18, 0xF0, 0x08, 0x0F, +0x4B, 0xF0, 0x02, 0x06, 0x8C, 0xE8, 0x0F, 0x00, 0xC9, 0xF8, 0x04, 0x60, 0x15, 0xD0, 0x01, 0x9B, 0x03, 0xF5, 0x8C, 0x76, +0x0F, 0xCE, 0x09, 0xF1, 0xF4, 0x0C, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, 0x0F, 0x00, 0x0F, 0xCE, 0xAC, 0xE8, +0x0F, 0x00, 0x96, 0xE8, 0x03, 0x00, 0x8C, 0xE8, 0x03, 0x00, 0x4B, 0xF0, 0x22, 0x03, 0xC9, 0xF8, 0x04, 0x30, 0x18, 0xF0, +0x04, 0x0F, 0x16, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x00, 0x9E, 0x03, 0xFB, 0x0E, 0xA3, 0x03, 0xF5, 0x86, 0x73, 0x93, 0xE8, +0x07, 0x00, 0xB4, 0x46, 0x51, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0C, 0x63, 0x03, 0xF1, 0xE8, 0x06, 0x86, 0xE8, +0x07, 0x00, 0x5A, 0x68, 0x42, 0xF0, 0x04, 0x02, 0x5A, 0x60, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x0E, 0xA1, 0xEC, 0x31, +0x38, 0x46, 0xFE, 0xF7, 0x81, 0xF8, 0x48, 0x4B, 0xD3, 0xF8, 0x14, 0x33, 0x98, 0x47, 0x47, 0x4B, 0x1B, 0x78, 0x00, 0x2B, +0x66, 0xD0, 0x00, 0x9A, 0x42, 0x49, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x02, 0x13, 0x93, 0xF8, 0xB8, 0x20, 0x00, 0x23, +0xCD, 0xE9, 0x02, 0x33, 0xCD, 0xE9, 0x05, 0x33, 0x04, 0x93, 0x07, 0x93, 0x00, 0x2A, 0x70, 0xD0, 0x01, 0x3A, 0xD2, 0xB2, +0xB8, 0x34, 0x02, 0xAE, 0x0D, 0xF1, 0x14, 0x0C, 0x9B, 0x46, 0x0D, 0xF1, 0x09, 0x03, 0x01, 0x92, 0x0C, 0x44, 0x03, 0xEB, +0x02, 0x09, 0x31, 0x46, 0x62, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x40, 0xF2, 0x05, 0x2A, 0x07, 0xE0, 0x01, 0xF8, 0x01, 0x0B, +0x49, 0x45, 0x82, 0xF8, 0x00, 0x80, 0x02, 0xF1, 0x01, 0x02, 0x14, 0xD0, 0x14, 0xF8, 0x01, 0x0F, 0x00, 0xF0, 0x7F, 0x03, +0x02, 0x3B, 0xDB, 0xB2, 0x09, 0x2B, 0x08, 0xFA, 0x03, 0xFE, 0xED, 0xD8, 0x1E, 0xEA, 0x0A, 0x0F, 0xEA, 0xD0, 0x01, 0xF8, +0x01, 0x0B, 0x49, 0x45, 0x82, 0xF8, 0x00, 0xB0, 0x02, 0xF1, 0x01, 0x02, 0xEA, 0xD1, 0x01, 0x9A, 0x0C, 0xF1, 0x01, 0x03, +0x1A, 0x44, 0x11, 0x46, 0x00, 0x9A, 0x10, 0x46, 0x1E, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x24, 0x00, 0xE0, +0x01, 0x33, 0x9C, 0xF8, 0x00, 0x20, 0x9C, 0x46, 0x2A, 0xB1, 0x62, 0x19, 0x30, 0x78, 0x82, 0xF8, 0xB9, 0x00, 0x01, 0x35, +0xED, 0xB2, 0x8B, 0x42, 0x06, 0xF1, 0x01, 0x06, 0xF0, 0xD1, 0x00, 0x9A, 0x11, 0x46, 0x13, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x01, 0x23, 0x83, 0xF8, 0xB8, 0x50, 0x38, 0x46, 0xFE, 0xF7, 0x1D, 0xFA, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x01, 0x20, 0x00, 0xF0, 0x98, 0xFD, 0x00, 0x20, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0xF9, 0xF7, +0x2D, 0xFD, 0x03, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0xF1, 0x12, 0xFB, 0xF7, 0x64, 0xFB, +0xF5, 0xE6, 0x15, 0x46, 0xD9, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xB8, 0x34, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x40, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x20, +0xF9, 0xF7, 0x0E, 0xFD, 0x08, 0x28, 0x06, 0xD0, 0x06, 0x20, 0xF9, 0xF7, 0x09, 0xFD, 0x09, 0x28, 0x33, 0xD0, 0x00, 0x20, +0x70, 0xBD, 0x22, 0x4A, 0x22, 0x4B, 0x14, 0x68, 0x94, 0xF8, 0x3D, 0x60, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x06, 0x36, +0x06, 0x23, 0x1A, 0x46, 0x00, 0x21, 0x4B, 0x20, 0x96, 0xF8, 0x6C, 0x50, 0xF9, 0xF7, 0x52, 0xFA, 0x94, 0xF8, 0x3A, 0x20, +0x02, 0x71, 0x22, 0x8F, 0x42, 0x80, 0x94, 0xF8, 0x3D, 0x20, 0x02, 0x70, 0xF9, 0xF7, 0x78, 0xFA, 0xD6, 0xF8, 0xB0, 0x34, +0x15, 0x4A, 0xA1, 0x8E, 0x4F, 0xF4, 0x1E, 0x70, 0x03, 0xF0, 0x01, 0x03, 0x00, 0xFB, 0x05, 0x22, 0xC3, 0xF1, 0x02, 0x03, +0x49, 0xBA, 0x02, 0x2B, 0x82, 0xF8, 0x30, 0x30, 0x91, 0x86, 0x08, 0xD0, 0x00, 0x20, 0x00, 0xF0, 0x39, 0xFD, 0x00, 0x20, +0x70, 0xBD, 0x00, 0xF0, 0x1B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF9, 0xF7, +0x27, 0xFA, 0x00, 0x22, 0x02, 0x70, 0x94, 0xF8, 0x3D, 0x20, 0x42, 0x70, 0xF9, 0xF7, 0x50, 0xFA, 0xE8, 0xE7, 0x00, 0xBF, +0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x70, 0xB5, 0x06, 0x46, 0x06, 0x20, 0x0D, 0x46, +0xF9, 0xF7, 0xB4, 0xFC, 0x2B, 0x46, 0x02, 0x46, 0x0A, 0x49, 0x04, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFB, 0xF7, 0xC2, 0xF8, +0x08, 0x4B, 0x1D, 0x42, 0x04, 0xD0, 0x24, 0xF0, 0x02, 0x01, 0x89, 0xB2, 0x05, 0x29, 0x00, 0xD0, 0x70, 0xBD, 0x30, 0x46, +0xE6, 0xF7, 0xDC, 0xFC, 0x01, 0x23, 0x86, 0xF8, 0x5E, 0x30, 0x70, 0xBD, 0x70, 0xBB, 0x15, 0x00, 0x00, 0x00, 0x03, 0x40, +0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, +0xF9, 0xF7, 0x74, 0xBE, 0x08, 0x4B, 0xDB, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x70, 0x22, 0xFB, 0xF7, +0xC3, 0xFA, 0xBD, 0xE8, 0x08, 0x40, 0x02, 0x48, 0xF9, 0xF7, 0x66, 0xBE, 0x38, 0x36, 0x17, 0x00, 0x70, 0xBA, 0x17, 0x00, +0x64, 0xBA, 0x17, 0x00, 0x80, 0xBB, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x03, 0x4A, 0x04, 0x4B, 0x00, 0x21, 0x06, 0x20, +0xD1, 0x75, 0x19, 0x60, 0xF9, 0xF7, 0xC4, 0xBB, 0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x11, 0x4B, +0x1E, 0x68, 0x00, 0x23, 0x03, 0x60, 0x0B, 0x60, 0x96, 0xF8, 0x22, 0x30, 0xDB, 0x07, 0x05, 0x46, 0x0C, 0x46, 0x08, 0xD5, +0x30, 0x46, 0x03, 0xF0, 0x57, 0xFB, 0x58, 0xB1, 0x83, 0x1C, 0x2B, 0x60, 0xC3, 0x6A, 0x23, 0x60, 0x70, 0xBD, 0x06, 0xF1, +0x22, 0x00, 0x28, 0x60, 0x03, 0xF0, 0x46, 0xFB, 0x00, 0x28, 0xF5, 0xD1, 0x32, 0x8D, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, +0x1C, 0xBF, 0x28, 0x36, 0x26, 0x60, 0x70, 0xBD, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x3B, 0x4C, 0x4F, 0xF4, +0xBA, 0x73, 0x06, 0x22, 0x84, 0xB0, 0x80, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x50, 0x04, 0x21, 0x25, 0x68, 0xF9, 0xF7, +0x91, 0xF9, 0x95, 0xF8, 0x3D, 0x30, 0x80, 0xF8, 0x6E, 0x31, 0x04, 0x46, 0x0F, 0xCD, 0x4F, 0xF0, 0x00, 0x0C, 0x04, 0xF1, +0xFC, 0x06, 0xC4, 0xF8, 0x68, 0xC1, 0xA4, 0xF8, 0x6C, 0xC1, 0x0F, 0xC6, 0x0F, 0xCD, 0x0F, 0xC6, 0x01, 0x23, 0x2A, 0x68, +0x32, 0x70, 0x84, 0xF8, 0x70, 0x31, 0xB8, 0xF1, 0x00, 0x0F, 0x19, 0xD0, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, +0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, 0xCF, 0xB1, 0x38, 0x68, 0x20, 0x60, 0xBB, 0x88, 0xA3, 0x80, 0x01, 0x23, +0x84, 0xF8, 0x6F, 0x31, 0x20, 0x46, 0xF9, 0xF7, 0x95, 0xF9, 0x01, 0x21, 0x06, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x41, +0xF9, 0xF7, 0x58, 0xBB, 0x1C, 0x4B, 0x18, 0x68, 0x9B, 0x88, 0xC4, 0xF8, 0x60, 0x01, 0xA4, 0xF8, 0x64, 0x31, 0x00, 0x2F, +0xE5, 0xD1, 0x19, 0x4B, 0x02, 0x93, 0x93, 0xF8, 0xFD, 0x50, 0x93, 0xF8, 0xFC, 0x00, 0x8D, 0xF8, 0x05, 0x50, 0x03, 0xF1, +0x54, 0x02, 0x03, 0x92, 0x84, 0xF8, 0x6F, 0x71, 0x0D, 0xF1, 0x08, 0x0C, 0x06, 0x26, 0xB8, 0xB1, 0x5C, 0xF8, 0x27, 0x30, +0x16, 0xFB, 0x00, 0x30, 0xDA, 0x78, 0x92, 0x07, 0x0D, 0xD4, 0x94, 0xF8, 0x6F, 0x21, 0x51, 0x1C, 0x84, 0xF8, 0x6F, 0x11, +0x02, 0xEB, 0x42, 0x02, 0x19, 0x68, 0x44, 0xF8, 0x12, 0x10, 0x04, 0xEB, 0x42, 0x02, 0x99, 0x88, 0x91, 0x80, 0x06, 0x33, +0x83, 0x42, 0xEB, 0xD1, 0x00, 0x2F, 0xC1, 0xD1, 0x28, 0x46, 0x01, 0x27, 0xE1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, +0xAC, 0xB2, 0x15, 0x00, 0x5A, 0xB9, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x8B, 0x78, 0x0D, 0x46, 0x80, 0x46, 0x17, 0x46, +0x1B, 0xB9, 0x37, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x49, 0xDB, 0x36, 0x4C, 0xDF, 0xF8, 0xEC, 0xA0, 0x4F, 0xF0, 0x00, 0x09, +0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, 0x41, 0xF2, 0x02, 0x00, 0xDA, 0xF8, 0x00, 0xB0, 0x84, 0xF8, 0x17, 0x90, +0xF9, 0xF7, 0x04, 0xF9, 0x04, 0x46, 0x28, 0x68, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0C, 0xB5, 0xF8, 0x04, 0xE0, 0x84, 0xF8, +0x6F, 0xC1, 0x5E, 0x46, 0x0F, 0xCE, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xE0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, +0x33, 0x68, 0x2B, 0x70, 0x84, 0xF8, 0x70, 0xC1, 0xA4, 0xF8, 0x6C, 0x91, 0xC4, 0xF8, 0x68, 0x91, 0x9B, 0xF8, 0x3D, 0x30, +0x84, 0xF8, 0x6E, 0x31, 0xD8, 0xF8, 0x00, 0x00, 0xC4, 0xF8, 0x60, 0x01, 0xB8, 0xF8, 0x04, 0x30, 0xA4, 0xF8, 0x64, 0x31, +0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0C, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF2, 0x20, 0x46, 0x52, 0x09, 0x8A, 0xF8, +0x15, 0x20, 0xF9, 0xF7, 0x01, 0xF9, 0xBD, 0xE8, 0xF8, 0x4F, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0xC5, 0xBA, 0x12, 0x4B, +0x10, 0x4C, 0xD3, 0xF8, 0x24, 0x31, 0x5B, 0x06, 0xB0, 0xD5, 0xE3, 0x7D, 0x01, 0x2B, 0xAD, 0xD1, 0x0E, 0x4A, 0x63, 0x70, +0x13, 0x68, 0x0E, 0x49, 0x0E, 0x48, 0x23, 0xF0, 0x00, 0x43, 0x13, 0x60, 0x08, 0x60, 0x0D, 0x4A, 0xC4, 0xF8, 0x0C, 0x80, +0x06, 0x21, 0x41, 0xF6, 0x09, 0x00, 0x25, 0x61, 0xA7, 0x75, 0xF8, 0xF7, 0x0D, 0xFF, 0xBD, 0xE8, 0xF8, 0x4F, 0xDC, 0xF7, +0xF9, 0xB8, 0x00, 0xBF, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, 0x00, 0x00, 0x50, 0x40, 0x34, 0x04, 0x32, 0x40, +0x20, 0x04, 0x32, 0x40, 0x40, 0x1F, 0xDC, 0x05, 0xA0, 0x86, 0x01, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, +0x27, 0x4D, 0xDF, 0xF8, 0xA0, 0x80, 0xAF, 0x7D, 0xD8, 0xF8, 0x00, 0x90, 0x4F, 0xF4, 0xBA, 0x73, 0x06, 0x22, 0x04, 0x21, +0x41, 0xF2, 0x02, 0x00, 0xF9, 0xF7, 0x8A, 0xF8, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x09, 0x00, 0xF8, 0xF7, 0x92, 0xFF, +0xD5, 0xE9, 0x03, 0x23, 0x4F, 0xF0, 0x00, 0x0C, 0x85, 0xF8, 0x17, 0xC0, 0x10, 0x68, 0xC4, 0xF8, 0x60, 0x01, 0x18, 0x68, +0x95, 0x88, 0x20, 0x60, 0x4F, 0xF0, 0x01, 0x0E, 0xB3, 0xF8, 0x04, 0xA0, 0x84, 0xF8, 0x6F, 0xE1, 0x4E, 0x46, 0x0F, 0xCE, +0xA4, 0xF8, 0x64, 0x51, 0x04, 0xF1, 0xFC, 0x05, 0xA4, 0xF8, 0x04, 0xA0, 0x0F, 0xC5, 0x0F, 0xCE, 0x0F, 0xC5, 0x33, 0x68, +0x2B, 0x70, 0x84, 0xF8, 0x70, 0xE1, 0xA4, 0xF8, 0x6C, 0xC1, 0xC4, 0xF8, 0x68, 0xC1, 0x99, 0xF8, 0x3D, 0x30, 0x84, 0xF8, +0x6E, 0x31, 0x1F, 0xB1, 0xE3, 0x78, 0x43, 0xEA, 0x0E, 0x03, 0xE3, 0x70, 0xB7, 0xFA, 0x87, 0xF3, 0x20, 0x46, 0x5B, 0x09, +0x88, 0xF8, 0x15, 0x30, 0xF9, 0xF7, 0x7E, 0xF8, 0xBD, 0xE8, 0xF0, 0x47, 0x02, 0x21, 0x06, 0x20, 0xF9, 0xF7, 0x42, 0xBA, +0x4C, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x30, 0xB5, 0x14, 0x4A, 0x14, 0x4B, 0x11, 0x68, 0x14, 0x4A, 0x91, 0xF8, +0x3D, 0x10, 0x54, 0x6C, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0xF2, 0x99, 0x18, 0x85, 0xB0, 0xD1, 0xF8, 0x90, 0x31, +0x91, 0xF8, 0xC5, 0x51, 0x8D, 0xF8, 0x05, 0x50, 0x0A, 0x46, 0x99, 0x78, 0xD2, 0xF8, 0x94, 0x21, 0x8D, 0xF8, 0x04, 0x10, +0x19, 0x88, 0x02, 0x92, 0x1A, 0x79, 0xAD, 0xF8, 0x06, 0x10, 0x8D, 0xF8, 0x0C, 0x20, 0xDB, 0x78, 0x8D, 0xF8, 0x0D, 0x30, +0x01, 0x46, 0x01, 0xA8, 0xA0, 0x47, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF9, 0xF7, 0xE2, 0xFC, 0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, 0x10, 0x40, 0xF9, 0xF7, 0x33, 0xB8, 0x00, 0x28, +0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, 0x0D, 0x22, 0xFB, 0xF7, 0xDD, 0xF8, 0xF0, 0xE7, 0x70, 0xBA, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x02, 0x23, 0x04, 0x46, +0x06, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0xE8, 0xFF, 0x06, 0x22, 0x02, 0x23, 0x06, 0x46, 0x05, 0x21, +0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0xE0, 0xFF, 0x38, 0x4F, 0x39, 0x49, 0x05, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, +0x91, 0xFE, 0xFF, 0xF7, 0xE1, 0xFD, 0x20, 0x46, 0xE5, 0xF7, 0x4A, 0xF8, 0x4F, 0xF0, 0x00, 0x08, 0x94, 0xF8, 0x6C, 0x00, +0x7B, 0x6A, 0x98, 0x47, 0x86, 0xF8, 0x00, 0x80, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x2F, 0x48, 0xA6, 0xF1, 0x0C, 0x01, +0xF9, 0xF7, 0x52, 0xFC, 0x94, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0x3F, 0xD1, 0x94, 0xF8, 0x6C, 0x30, 0xFF, 0x2B, 0x0D, 0xD0, +0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x0C, 0x20, 0xF8, 0xF7, 0xB6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x6C, 0x30, 0x01, 0xF8, +0x0C, 0x39, 0x23, 0x48, 0xF9, 0xF7, 0x3C, 0xFC, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x06, 0x22, 0x39, 0x20, +0xF8, 0xF7, 0xA6, 0xFF, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x1B, 0x48, 0xF9, 0xF7, 0x2C, 0xFC, +0x00, 0x26, 0x2E, 0x70, 0x94, 0xF8, 0x63, 0x20, 0x18, 0x4B, 0x6A, 0x70, 0x93, 0xF8, 0x04, 0x31, 0x43, 0xB1, 0xD7, 0xF8, +0xD8, 0x31, 0x04, 0xF1, 0x9C, 0x00, 0x98, 0x47, 0xC4, 0xE9, 0x24, 0x66, 0xC4, 0xF8, 0x98, 0x60, 0x00, 0x23, 0xA5, 0xF1, +0x0C, 0x01, 0xC4, 0xF8, 0xCC, 0x31, 0x0E, 0x48, 0xF9, 0xF7, 0x12, 0xFC, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, 0x6C, 0xBF, +0x41, 0x46, 0x04, 0x23, 0x06, 0x22, 0x1E, 0x20, 0xF8, 0xF7, 0x7A, 0xFF, 0x80, 0xF8, 0x02, 0x80, 0x94, 0xF8, 0x63, 0x30, +0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x04, 0x48, 0xF9, 0xF7, 0xFE, 0xFB, 0xAE, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, +0xA8, 0xBB, 0x15, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x6A, 0x4B, 0xDF, 0xF8, +0xB4, 0xA1, 0x1D, 0x68, 0x83, 0xB0, 0x95, 0xF8, 0x3D, 0x20, 0x00, 0x92, 0x16, 0x46, 0x02, 0x23, 0x06, 0x22, 0x05, 0x21, +0x41, 0xF2, 0x19, 0x40, 0xF8, 0xF7, 0x54, 0xFF, 0x08, 0x23, 0x81, 0x46, 0x06, 0x22, 0x00, 0x21, 0x18, 0x20, 0xF8, 0xF7, +0x4D, 0xFF, 0x08, 0x23, 0x07, 0x46, 0x06, 0x22, 0x00, 0x21, 0x16, 0x20, 0xF8, 0xF7, 0x46, 0xFF, 0x4F, 0xF4, 0xA4, 0x64, +0x04, 0xFB, 0x06, 0xF4, 0x04, 0x23, 0x06, 0x46, 0x06, 0x22, 0x00, 0x21, 0x14, 0x20, 0xF8, 0xF7, 0x3B, 0xFF, 0x02, 0x23, +0x06, 0x22, 0x05, 0x21, 0x83, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF8, 0xF7, 0x33, 0xFF, 0x80, 0x46, 0xFF, 0xF7, 0x3A, 0xFD, +0x4F, 0xF0, 0x01, 0x02, 0x89, 0xF8, 0x00, 0x20, 0x95, 0xF8, 0x3D, 0x30, 0x89, 0xF8, 0x01, 0x30, 0x0A, 0xEB, 0x04, 0x03, +0x01, 0x93, 0x4B, 0x4B, 0xA9, 0xF1, 0x0C, 0x01, 0x03, 0xF1, 0x0C, 0x00, 0xF9, 0xF7, 0xAC, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, +0x64, 0x01, 0xB3, 0xF8, 0x68, 0x21, 0xBA, 0x80, 0x44, 0x4B, 0x38, 0x60, 0x95, 0xF8, 0x3D, 0x20, 0xBA, 0x71, 0x03, 0xF1, +0x0C, 0x00, 0xA7, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x9B, 0xFB, 0x01, 0x9B, 0xD3, 0xF8, 0x90, 0x31, 0x04, 0xF5, 0xCE, 0x70, +0x9B, 0x78, 0x73, 0x71, 0x01, 0x21, 0x50, 0x44, 0xFD, 0xF7, 0xFE, 0xFD, 0x73, 0x79, 0x30, 0x60, 0x95, 0xF8, 0x3D, 0x20, +0x32, 0x71, 0x2B, 0xB9, 0xC1, 0x07, 0x4F, 0xD5, 0x36, 0x4B, 0x4F, 0xF4, 0x80, 0x62, 0x5A, 0x61, 0xA6, 0xF1, 0x0C, 0x01, +0x34, 0x48, 0xF9, 0xF7, 0x7F, 0xFB, 0x00, 0x9B, 0x32, 0x48, 0x4F, 0xF4, 0xA4, 0x66, 0x06, 0xFB, 0x03, 0xA6, 0xAB, 0xF1, +0x0C, 0x01, 0xB6, 0xF8, 0x98, 0x31, 0xAB, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x8B, 0xF8, 0x02, 0x30, 0xF9, 0xF7, +0x6D, 0xFB, 0xD6, 0xF8, 0xCC, 0x31, 0x1B, 0x07, 0x36, 0xD4, 0x04, 0xF5, 0xD6, 0x74, 0x00, 0x26, 0x26, 0x4F, 0xA2, 0x44, +0x34, 0x46, 0x08, 0x23, 0x06, 0x22, 0x00, 0x21, 0x1A, 0x20, 0xF8, 0xF7, 0xCF, 0xFE, 0x5A, 0xF8, 0x04, 0x3B, 0x03, 0x60, +0x46, 0x71, 0x95, 0xF8, 0x3D, 0x30, 0x83, 0x71, 0x04, 0x71, 0xA0, 0xF1, 0x0C, 0x01, 0x01, 0x36, 0x38, 0x46, 0xF9, 0xF7, +0x4F, 0xFB, 0x04, 0x2E, 0xE9, 0xD1, 0x01, 0x23, 0x88, 0xF8, 0x00, 0x30, 0x95, 0xF8, 0x3D, 0x30, 0x17, 0x48, 0x88, 0xF8, +0x01, 0x30, 0xA8, 0xF1, 0x0C, 0x01, 0xF9, 0xF7, 0x41, 0xFB, 0xFF, 0xF7, 0x9D, 0xFE, 0x31, 0x46, 0x06, 0x20, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x4F, 0xF9, 0xF7, 0xA4, 0xB8, 0xC2, 0x06, 0xB1, 0xD5, 0x0D, 0x4B, 0x04, 0x22, 0x5A, 0x61, 0xAD, 0xE7, +0x06, 0x22, 0x00, 0x21, 0x04, 0x23, 0x71, 0x20, 0xF8, 0xF7, 0x9E, 0xFE, 0x04, 0xF1, 0xEC, 0x03, 0x06, 0x46, 0x0A, 0xEB, +0x03, 0x00, 0xFD, 0xF7, 0x0F, 0xFE, 0x31, 0x46, 0x03, 0x46, 0x41, 0xF8, 0x0C, 0x39, 0x04, 0x48, 0xF9, 0xF7, 0x1E, 0xFB, +0xB3, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x70, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0x06, 0x23, 0x2D, 0xE9, 0xF0, 0x41, 0x1A, 0x46, 0x04, 0x46, 0x0F, 0x46, 0x41, 0xF6, 0x05, 0x00, 0x0C, 0x21, 0xF8, 0xF7, +0x7B, 0xFE, 0x38, 0x4E, 0x94, 0xF8, 0xC0, 0x34, 0xB4, 0x62, 0x05, 0x46, 0x00, 0x2B, 0x3F, 0xD0, 0x35, 0x4B, 0x9B, 0x68, +0x00, 0x2B, 0x61, 0xD0, 0x93, 0xF8, 0x62, 0x20, 0x7A, 0xB9, 0x33, 0x49, 0x33, 0x4A, 0xD8, 0x6D, 0x08, 0x60, 0xB3, 0xF8, +0x60, 0x10, 0x11, 0x60, 0x93, 0xF8, 0x64, 0x20, 0x2A, 0xB1, 0x30, 0x49, 0x98, 0x6B, 0x30, 0x4A, 0x08, 0x60, 0x99, 0x8F, +0x11, 0x60, 0x2F, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x2C, 0xDB, 0xDF, 0xF8, 0xC4, 0x80, 0x00, 0x20, 0xDB, 0xF7, 0x86, 0xFE, +0x00, 0x22, 0xD8, 0xF8, 0xD8, 0x31, 0x84, 0xF8, 0xAC, 0x20, 0x04, 0xF1, 0xB0, 0x00, 0x98, 0x47, 0xD8, 0xF8, 0x10, 0x33, +0x20, 0x46, 0x98, 0x47, 0x2F, 0x80, 0x94, 0xF8, 0x63, 0x30, 0xAB, 0x70, 0xB3, 0x7D, 0x01, 0x2B, 0x08, 0xBF, 0xEB, 0x70, +0xB3, 0x7F, 0xA3, 0xF1, 0x01, 0x03, 0xB3, 0xFA, 0x83, 0xF3, 0x5B, 0x09, 0xA5, 0xF1, 0x0C, 0x02, 0x2B, 0x71, 0xB2, 0x60, +0xBD, 0xE8, 0xF0, 0x81, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xD6, 0xDA, 0x13, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0xD2, 0xD0, +0x00, 0x21, 0x93, 0xF8, 0x62, 0x20, 0x1A, 0xB9, 0x93, 0xF8, 0x64, 0x20, 0x02, 0xB1, 0x01, 0x31, 0x1B, 0x68, 0x00, 0x2B, +0xF5, 0xD1, 0x01, 0x29, 0xC5, 0xD1, 0x11, 0x4A, 0x11, 0x49, 0x53, 0x70, 0x0B, 0x68, 0x11, 0x4A, 0x43, 0xF0, 0x00, 0x43, +0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB4, 0xE7, +0x07, 0x4B, 0x1B, 0x68, 0xB1, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x10, 0x00, 0x32, 0x40, +0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x48, 0x30, 0x34, 0x40, 0x4C, 0x36, 0x17, 0x00, +0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x10, 0xB5, 0x0A, 0x46, 0x04, 0x46, 0x05, 0x49, +0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0xA4, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x60, 0xBF, +0xBC, 0xBB, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xC8, 0x81, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x00, 0x84, +0x0B, 0x46, 0x02, 0x46, 0x06, 0x46, 0x0F, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x66, 0x49, 0x94, 0xF8, 0x6C, 0x90, 0xFA, 0xF7, +0x89, 0xFC, 0x94, 0xF8, 0x62, 0x50, 0x15, 0xB9, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, 0xBD, 0xE8, 0xF8, 0x43, 0x06, 0x22, +0x0C, 0x21, 0x41, 0xF6, 0x04, 0x00, 0xF8, 0xF7, 0x2B, 0xBE, 0x5E, 0x4B, 0x01, 0x25, 0x09, 0x21, 0x06, 0x20, 0x1D, 0x75, +0xF8, 0xF7, 0xB6, 0xFF, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x79, 0xD1, 0xD4, 0xF8, 0x90, 0x31, 0x9D, 0x78, 0x2C, 0x1E, +0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0x18, 0xBF, 0x01, 0x24, 0xE4, 0xF7, 0x11, 0xFD, 0x00, 0x28, +0x74, 0xD0, 0x20, 0x46, 0x4F, 0xF4, 0xC0, 0x71, 0xE6, 0xF7, 0x72, 0xF8, 0x04, 0x46, 0x01, 0x46, 0x28, 0x46, 0x00, 0x2C, +0x6C, 0xD0, 0xF8, 0xF7, 0x69, 0xF9, 0x4C, 0x4B, 0xD4, 0xF8, 0x48, 0x80, 0x4B, 0x49, 0xE8, 0x6D, 0x4F, 0xF4, 0x1E, 0x72, +0x02, 0xFB, 0x09, 0x39, 0xB1, 0xF8, 0xFC, 0x31, 0x59, 0xF8, 0x26, 0x2F, 0xC8, 0xF8, 0x6C, 0x20, 0x6F, 0xF0, 0x3F, 0x02, +0x88, 0xF8, 0x68, 0x20, 0xB9, 0xF8, 0x04, 0x20, 0xA8, 0xF8, 0x70, 0x20, 0xB5, 0xF8, 0x60, 0x20, 0xA8, 0xF8, 0x76, 0x20, +0x01, 0x33, 0xD9, 0xF8, 0x00, 0x20, 0xC8, 0xF8, 0x72, 0x00, 0x9B, 0xB2, 0xB9, 0xF8, 0x04, 0x00, 0xC8, 0xF8, 0x78, 0x20, +0x00, 0x22, 0xA8, 0xF8, 0x7C, 0x00, 0x88, 0xF8, 0x69, 0x20, 0x88, 0xF8, 0x6A, 0x20, 0x88, 0xF8, 0x6B, 0x20, 0x18, 0x01, +0xA1, 0xF8, 0xFC, 0x31, 0x35, 0x4B, 0xA8, 0xF8, 0x7E, 0x00, 0x26, 0x77, 0xA5, 0x65, 0x63, 0x65, 0x95, 0xF8, 0x6C, 0x30, +0x63, 0x77, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, 0x35, 0x20, 0xC0, 0x21, 0x20, 0x46, 0x07, 0xF0, 0x5F, 0xF9, 0x01, 0x28, +0x06, 0x46, 0x08, 0xF1, 0x68, 0x09, 0x34, 0xD0, 0x39, 0x46, 0x08, 0xF1, 0x80, 0x00, 0xFB, 0xF7, 0xDD, 0xFD, 0x02, 0x2E, +0x00, 0xF1, 0x18, 0x05, 0x3D, 0xD0, 0xE2, 0x6C, 0x53, 0x6A, 0x01, 0x3B, 0x2B, 0x44, 0x04, 0x35, 0xC2, 0xE9, 0x0A, 0x35, +0x05, 0x21, 0x20, 0x46, 0xE6, 0xF7, 0x20, 0xF8, 0x05, 0x46, 0x88, 0xB1, 0xBD, 0xE8, 0xF8, 0x83, 0x2C, 0x46, 0x4F, 0xF4, +0xA4, 0x65, 0x05, 0xFB, 0x06, 0x85, 0x28, 0x46, 0xE4, 0xF7, 0x9C, 0xFC, 0x00, 0x28, 0x8A, 0xD1, 0x01, 0x46, 0x28, 0x46, +0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0xA8, 0xBE, 0xA4, 0x6D, 0x17, 0x49, 0x02, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, +0xDF, 0xFB, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x9B, 0xBE, 0x18, 0x22, 0x49, 0x46, 0x20, 0x46, +0x05, 0xF0, 0x84, 0xFF, 0x94, 0xF8, 0x33, 0x50, 0x18, 0x35, 0x09, 0xEB, 0x05, 0x00, 0x39, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, +0x94, 0xF8, 0x35, 0x20, 0x15, 0x44, 0x05, 0x44, 0xC1, 0xE7, 0x2A, 0x46, 0x49, 0x46, 0x20, 0x46, 0x07, 0xF0, 0x4A, 0xF9, +0x05, 0x44, 0xBA, 0xE7, 0xD4, 0xBB, 0x15, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, +0xD1, 0x9D, 0x14, 0x00, 0xBC, 0xBB, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x66, 0x4D, 0x67, 0x49, +0xD5, 0xE9, 0x00, 0x34, 0x93, 0xF8, 0x3D, 0x70, 0x67, 0x72, 0x0A, 0x68, 0x20, 0x80, 0x22, 0xF0, 0x10, 0x02, 0x4F, 0xF4, +0xA4, 0x66, 0x83, 0xB0, 0x80, 0x46, 0x06, 0xFB, 0x07, 0xF6, 0x0A, 0x60, 0x00, 0x28, 0x6C, 0xD1, 0xDF, 0xF8, 0x98, 0x91, +0x09, 0xEB, 0x06, 0x01, 0x91, 0xF8, 0x6C, 0x20, 0xD1, 0xF8, 0x64, 0x01, 0xB1, 0xF8, 0x68, 0xC1, 0xA2, 0x72, 0x0A, 0x6C, +0xA4, 0xF8, 0x06, 0xC0, 0xC4, 0xF8, 0x02, 0x00, 0x10, 0x7E, 0xE0, 0x72, 0x10, 0x79, 0x84, 0xF8, 0x36, 0x03, 0xD0, 0x88, +0xB2, 0xF8, 0x08, 0xC0, 0xA4, 0xF8, 0x38, 0x03, 0x50, 0x89, 0xC4, 0xE9, 0xCF, 0xC0, 0x52, 0x79, 0x84, 0xF8, 0x3A, 0x23, +0xD1, 0xF8, 0xCC, 0x21, 0x02, 0xF0, 0x01, 0x02, 0x22, 0x73, 0x00, 0x2A, 0x6D, 0xD1, 0x42, 0x46, 0x62, 0x73, 0x1A, 0x6B, +0x4F, 0xF4, 0xA4, 0x63, 0x02, 0xF0, 0x20, 0x02, 0x03, 0xFB, 0x07, 0x93, 0x22, 0x72, 0x93, 0xF8, 0xC0, 0x24, 0xA2, 0xB1, +0xB3, 0xF8, 0x5E, 0x00, 0xB3, 0xF8, 0x5C, 0x20, 0x42, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x41, 0x4A, 0xB3, 0xF8, +0x60, 0x10, 0x11, 0x60, 0x58, 0x8F, 0x1A, 0x8F, 0x3F, 0x49, 0x42, 0xEA, 0x00, 0x42, 0x0A, 0x60, 0x3E, 0x4A, 0x9B, 0x8F, +0x13, 0x60, 0x20, 0x46, 0xF8, 0xF7, 0xC8, 0xFC, 0x94, 0xF8, 0x3A, 0x33, 0xB4, 0xF8, 0x3C, 0x03, 0x40, 0xEA, 0x03, 0x40, +0x40, 0xF0, 0x00, 0x40, 0xDB, 0xF7, 0xC0, 0xFC, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x97, 0x01, 0x22, 0x35, 0x4B, +0x87, 0xF8, 0xAC, 0x20, 0x1A, 0x69, 0x34, 0x49, 0x34, 0x4B, 0x06, 0xF1, 0xB0, 0x00, 0x48, 0x44, 0x11, 0x44, 0xD3, 0xF8, +0xE0, 0x31, 0x98, 0x47, 0x00, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x72, 0xFE, 0x12, 0xE0, 0x2F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, +0x26, 0xDB, 0x2E, 0x4B, 0x06, 0x20, 0x09, 0x21, 0x1E, 0x44, 0xF8, 0xF7, 0x67, 0xFE, 0x29, 0x4A, 0xAE, 0x62, 0xA4, 0xF1, +0x0C, 0x03, 0xD2, 0xF8, 0x10, 0x23, 0xAB, 0x60, 0x30, 0x46, 0x90, 0x47, 0xB4, 0xF8, 0x34, 0x33, 0x62, 0x7A, 0x26, 0x49, +0x00, 0x93, 0x4F, 0xF4, 0x80, 0x70, 0x43, 0x46, 0xFA, 0xF7, 0x12, 0xFB, 0x28, 0x68, 0x0C, 0x38, 0xF8, 0xF7, 0xD2, 0xFC, +0x00, 0x23, 0x2B, 0x60, 0xAB, 0x75, 0xAB, 0x77, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x91, 0xF8, 0xBD, 0x21, 0x8F, 0xE7, +0x1C, 0x4B, 0x9A, 0x68, 0x62, 0xB1, 0x00, 0x21, 0x92, 0xF8, 0x62, 0x30, 0x1B, 0xB9, 0x92, 0xF8, 0x64, 0x30, 0x03, 0xB1, +0x01, 0x31, 0x12, 0x68, 0x00, 0x2A, 0xF5, 0xD1, 0x00, 0x29, 0xC8, 0xD1, 0x15, 0x4B, 0x16, 0x49, 0x00, 0x22, 0x5A, 0x70, +0x0B, 0x68, 0x15, 0x4A, 0x43, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x43, 0xF4, 0xBB, 0x63, +0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0xB6, 0xE7, 0x64, 0xBA, 0x17, 0x00, 0x94, 0x40, 0x04, 0x40, 0x10, 0x00, 0x32, 0x40, +0x14, 0x00, 0x32, 0x40, 0x20, 0x00, 0x32, 0x40, 0x24, 0x00, 0x32, 0x40, 0x00, 0x10, 0x50, 0x40, 0x40, 0x4B, 0x4C, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x48, 0x30, 0x34, 0x40, 0x18, 0x88, 0x17, 0x00, 0xE8, 0xBB, 0x15, 0x00, 0x00, 0x88, 0x17, 0x00, +0x4C, 0x36, 0x17, 0x00, 0x34, 0x04, 0x32, 0x40, 0x20, 0x04, 0x32, 0x40, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0x4B, 0x8C, 0x4E, +0xD3, 0xF8, 0x00, 0x90, 0x8B, 0x4A, 0x99, 0xF8, 0x3D, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, 0x89, 0xB0, +0x07, 0x46, 0x88, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x86, 0x49, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0xAB, 0xFA, 0x94, 0xF8, +0xC0, 0x34, 0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, +0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xB2, 0xFE, 0x04, 0x46, 0x00, 0x28, 0x7C, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, +0x05, 0x65, 0x28, 0x46, 0x21, 0x46, 0xF7, 0xF7, 0xA5, 0xFF, 0x78, 0x4B, 0xA2, 0x6C, 0x78, 0x49, 0x4F, 0xF4, 0x1E, 0x70, +0x00, 0xFB, 0x0A, 0x3A, 0x53, 0x46, 0xB1, 0xF8, 0xFC, 0x61, 0x53, 0xF8, 0x26, 0x0F, 0xD0, 0x66, 0x6F, 0xF0, 0x4F, 0x00, +0x82, 0xF8, 0x68, 0x00, 0x98, 0x88, 0xA2, 0xF8, 0x70, 0x00, 0xE8, 0x6D, 0xC2, 0xF8, 0x72, 0x00, 0x01, 0x36, 0xB5, 0xF8, +0x60, 0x00, 0xA2, 0xF8, 0x76, 0x00, 0x4F, 0xF0, 0x00, 0x0B, 0x18, 0x68, 0x9B, 0x88, 0xA2, 0xF8, 0x7C, 0x30, 0xB6, 0xB2, +0x90, 0x67, 0x82, 0xF8, 0x69, 0xB0, 0x82, 0xF8, 0x6A, 0xB0, 0x82, 0xF8, 0x6B, 0xB0, 0x65, 0x4B, 0xA1, 0xF8, 0xFC, 0x61, +0x30, 0x01, 0x95, 0xF8, 0x63, 0x10, 0xA2, 0xF8, 0x7E, 0x00, 0x21, 0x77, 0x95, 0xF8, 0x6C, 0x10, 0x1B, 0x68, 0x61, 0x77, +0x84, 0xF8, 0x33, 0xB0, 0x84, 0xF8, 0x35, 0xB0, 0x1B, 0x78, 0x99, 0xF8, 0x3B, 0x10, 0x9B, 0x07, 0x02, 0xF1, 0x68, 0x05, +0x38, 0xD4, 0x01, 0x29, 0x44, 0xD0, 0x18, 0x26, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0xA8, 0x19, 0x00, 0x23, 0xFB, 0xF7, +0xFF, 0xFB, 0x30, 0x44, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, 0x4A, 0x6A, 0xA4, 0x65, 0x18, 0x44, 0x01, 0x3A, 0x02, 0x44, +0x03, 0x1D, 0x50, 0x48, 0x60, 0x65, 0xC1, 0xE9, 0x0A, 0x23, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x59, 0xFE, 0x4D, 0x4B, +0x1B, 0x68, 0x06, 0x21, 0xDA, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0xD1, 0xF9, 0x05, 0x21, 0x06, 0x20, 0xF8, 0xF7, +0x69, 0xFD, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0x35, 0xFE, 0x04, 0x46, +0x00, 0x28, 0x82, 0xD1, 0x01, 0x20, 0xFF, 0xF7, 0x67, 0xFE, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x29, 0x01, 0xD1, +0x03, 0x2F, 0x17, 0xD0, 0xCD, 0xF8, 0x00, 0x80, 0x3A, 0x46, 0x05, 0xF1, 0x18, 0x00, 0x00, 0x23, 0xFB, 0xF7, 0xC4, 0xFB, +0x18, 0x30, 0xC3, 0xE7, 0x03, 0x2F, 0xB8, 0xD1, 0x29, 0x46, 0x20, 0x46, 0x18, 0x22, 0x05, 0xF0, 0xB1, 0xFD, 0x94, 0xF8, +0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0x00, 0xF1, 0x18, 0x06, 0xAD, 0xE7, 0xDA, 0xF8, 0xB4, 0x30, 0x29, 0x46, 0x18, 0x22, +0x20, 0x46, 0x1E, 0x68, 0x05, 0xF0, 0xA2, 0xFD, 0x94, 0xF8, 0x33, 0x00, 0x99, 0xF8, 0x3B, 0x10, 0xCD, 0xF8, 0x00, 0x80, +0x00, 0xF1, 0x18, 0x08, 0x05, 0xEB, 0x08, 0x09, 0x5B, 0x46, 0x3A, 0x46, 0x48, 0x46, 0xFB, 0xF7, 0x9D, 0xFB, 0x05, 0x46, +0x3A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0xFF, 0x33, 0x48, 0x46, 0xDB, 0xF7, 0x67, 0xFD, 0x96, 0xF8, 0x60, 0x30, 0x21, 0x8F, +0x62, 0x8F, 0xAD, 0xF8, 0x10, 0x10, 0x8D, 0xF8, 0x12, 0x20, 0x06, 0xF1, 0x64, 0x01, 0x93, 0xB1, 0x03, 0x2B, 0x1A, 0xD0, +0x03, 0x20, 0xDB, 0xF7, 0x8F, 0xFD, 0x29, 0x1D, 0x02, 0x46, 0x89, 0xB2, 0x48, 0x46, 0x03, 0x91, 0xF7, 0xF7, 0x20, 0xFF, +0x48, 0x46, 0x03, 0x99, 0xF8, 0xF7, 0x16, 0xF9, 0x05, 0xEB, 0x08, 0x00, 0x78, 0xE7, 0x05, 0x22, 0x0D, 0xF1, 0x13, 0x00, +0x0C, 0xF0, 0x88, 0xFE, 0x04, 0xA8, 0x08, 0x21, 0xF8, 0xF7, 0xDE, 0xF8, 0xE4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x13, 0x00, +0x0C, 0xF0, 0x7E, 0xFE, 0x04, 0xA8, 0x10, 0x21, 0xF8, 0xF7, 0xD4, 0xF8, 0xDA, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x9C, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, +0x34, 0x36, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x77, 0x4F, 0x78, 0x4E, +0xD7, 0xF8, 0x00, 0x80, 0x77, 0x4A, 0x98, 0xF8, 0x3D, 0x50, 0x77, 0x49, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x05, 0x64, +0x87, 0xB0, 0x4F, 0xF4, 0x80, 0x70, 0x94, 0xF8, 0x6C, 0xA0, 0xFA, 0xF7, 0x81, 0xF9, 0x94, 0xF8, 0xC0, 0x34, 0x00, 0x2B, +0x40, 0xF0, 0xAA, 0x80, 0xD4, 0xF8, 0x90, 0x31, 0x98, 0x78, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, +0xE5, 0xF7, 0x88, 0xFD, 0x04, 0x46, 0x00, 0x28, 0x00, 0xF0, 0xA5, 0x80, 0x4F, 0xF4, 0xA4, 0x6B, 0x0B, 0xFB, 0x05, 0xFB, +0x06, 0xEB, 0x0B, 0x00, 0x21, 0x46, 0xD7, 0xF8, 0x04, 0x90, 0xF7, 0xF7, 0x77, 0xFE, 0xBA, 0x7D, 0xA3, 0x6C, 0x01, 0x2A, +0x03, 0xF1, 0x68, 0x0C, 0x00, 0xF0, 0x99, 0x80, 0xBA, 0x7F, 0x00, 0x2A, 0x00, 0xF0, 0xA7, 0x80, 0x20, 0x22, 0x00, 0x21, +0x83, 0xF8, 0x68, 0x20, 0x5B, 0x4A, 0x83, 0xF8, 0x69, 0x10, 0x5B, 0x49, 0x5B, 0x4F, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, +0x0A, 0x10, 0xB7, 0xF8, 0xFC, 0xE1, 0x50, 0xF8, 0x26, 0xAF, 0xC3, 0xF8, 0x6C, 0xA0, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, +0x05, 0x65, 0xB0, 0xF8, 0x04, 0xA0, 0xA3, 0xF8, 0x70, 0xA0, 0x0B, 0xF1, 0xEC, 0x01, 0x0E, 0xF1, 0x01, 0x0E, 0xD0, 0xF8, +0x00, 0xA0, 0xB0, 0xF8, 0x04, 0xB0, 0xE8, 0x6D, 0xC3, 0xF8, 0x72, 0x00, 0x1F, 0xFA, 0x8E, 0xFE, 0x31, 0x44, 0x00, 0x26, +0xB5, 0xF8, 0x60, 0x00, 0xC3, 0xF8, 0x78, 0xA0, 0x83, 0xF8, 0x6A, 0x60, 0x83, 0xF8, 0x6B, 0x60, 0x4F, 0xEA, 0x0E, 0x1A, +0x46, 0x4E, 0xA3, 0xF8, 0x76, 0x00, 0xA3, 0xF8, 0x7C, 0xB0, 0x0C, 0xF1, 0x18, 0x00, 0xA7, 0xF8, 0xFC, 0xE1, 0x0D, 0xF1, +0x12, 0x0C, 0xA3, 0xF8, 0x7E, 0xA0, 0x05, 0xAF, 0x95, 0xF8, 0x63, 0x30, 0xCD, 0xF8, 0x08, 0x80, 0xD6, 0xF8, 0x58, 0x61, +0xCD, 0xE9, 0x00, 0x7C, 0xB0, 0x47, 0x95, 0xF8, 0x63, 0x30, 0x23, 0x77, 0x95, 0xF8, 0x6C, 0x30, 0xE1, 0x6C, 0x63, 0x77, +0x4B, 0x6A, 0xBD, 0xF8, 0x12, 0x20, 0x37, 0x4D, 0xA4, 0x65, 0x17, 0x33, 0x03, 0x44, 0xB2, 0xF5, 0x48, 0x7F, 0x00, 0xF1, +0x1C, 0x00, 0x65, 0x65, 0xC1, 0xE9, 0x0A, 0x30, 0x3B, 0xD8, 0x05, 0x98, 0x6A, 0xB1, 0x4A, 0x44, 0x13, 0x38, 0x13, 0x32, +0xA0, 0xEB, 0x09, 0x00, 0x09, 0xF1, 0x13, 0x03, 0xC1, 0x5C, 0x03, 0xF8, 0x01, 0x1F, 0x93, 0x42, 0xFA, 0xD1, 0xBD, 0xF8, +0x12, 0x20, 0xA9, 0xF8, 0x0E, 0x20, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, 0x07, 0xFD, 0x27, 0x4B, 0x1B, 0x68, 0x06, 0x21, +0x9A, 0x68, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, 0x7F, 0xF8, 0x07, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x17, 0xFC, 0x07, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE5, 0xF7, 0xE3, 0xFC, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, +0x5B, 0xAF, 0x01, 0x20, 0xFF, 0xF7, 0x14, 0xFD, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x20, 0x22, 0x00, 0x21, 0x83, 0xF8, +0x68, 0x20, 0x83, 0xF8, 0x69, 0x10, 0x16, 0x4A, 0x69, 0xE7, 0x16, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x08, 0xDB, 0x00, 0x23, 0xA9, 0xF8, 0x0E, 0x30, 0xCB, 0xE7, 0x83, 0xF8, 0x68, 0x20, 0x83, 0xF8, 0x69, 0x20, 0x5A, 0xE7, +0x0F, 0x49, 0x10, 0x48, 0x4F, 0xF4, 0x82, 0x62, 0xFA, 0xF7, 0xE8, 0xFA, 0xEF, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0xAC, 0xBC, 0x15, 0x00, 0xCC, 0xB5, 0x15, 0x00, 0x84, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x20, 0x62, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x89, 0x95, 0x14, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x7C, 0xBA, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x0B, 0x4D, 0x04, 0x46, 0x04, 0x23, +0x00, 0x21, 0x06, 0x22, 0x1E, 0x20, 0x2D, 0x68, 0xF8, 0xF7, 0xC6, 0xF9, 0x01, 0x22, 0x04, 0x80, 0x82, 0x70, 0x95, 0xF8, +0x3D, 0x20, 0xC2, 0x70, 0xF8, 0xF7, 0xEE, 0xF9, 0xBD, 0xE8, 0x38, 0x40, 0x08, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0xB2, 0xBB, +0x64, 0xBA, 0x17, 0x00, 0x70, 0xB5, 0x00, 0xF1, 0x0C, 0x06, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, 0x08, 0x00, 0xF8, 0xF7, +0xBB, 0xF8, 0xB5, 0x88, 0x19, 0x49, 0x2A, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xFA, 0xF7, 0x5E, 0xF8, 0x45, 0xB9, 0xA3, 0x89, +0x13, 0xB1, 0x01, 0x2B, 0x09, 0xD0, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xBE, 0xBE, 0x28, 0x46, 0xBD, 0xE8, +0x70, 0x40, 0xFF, 0xF7, 0x9D, 0xBC, 0x73, 0x88, 0x04, 0x2B, 0xF3, 0xD0, 0x02, 0x2B, 0x11, 0xD0, 0x0D, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0xFF, 0xF7, 0x8D, 0xBC, 0x09, 0x49, +0x09, 0x48, 0x4F, 0xF4, 0x8C, 0x62, 0xFA, 0xF7, 0x7B, 0xFA, 0xF3, 0xE7, 0x04, 0xF1, 0x14, 0x01, 0x03, 0x20, 0xBD, 0xE8, +0x70, 0x40, 0xFF, 0xF7, 0x6F, 0xBD, 0x00, 0xBF, 0x00, 0xBC, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x69, 0x4B, 0xD3, 0xE9, 0x00, 0x2A, 0x05, 0x46, 0x83, 0xB0, 0x06, 0x21, +0x00, 0x24, 0x41, 0xF6, 0x08, 0x00, 0x92, 0xF8, 0x3D, 0x80, 0x8D, 0xF8, 0x06, 0x40, 0xF8, 0xF7, 0x6D, 0xF8, 0x29, 0x88, +0xEE, 0x89, 0x4F, 0xF4, 0xA4, 0x67, 0x05, 0x29, 0x05, 0xF1, 0x0C, 0x09, 0x07, 0xFB, 0x08, 0xF7, 0x34, 0xD9, 0xBA, 0xF8, +0x0E, 0x30, 0x06, 0x39, 0x89, 0xB2, 0xCA, 0x18, 0x05, 0xF1, 0x12, 0x0B, 0xB2, 0xF5, 0x48, 0x7F, 0x5C, 0x46, 0x09, 0xDD, +0x58, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x81, 0x80, 0xC3, 0xF5, 0x48, 0x71, 0x89, 0xB2, +0x0A, 0xF1, 0x14, 0x00, 0x18, 0x44, 0x8B, 0x44, 0x39, 0xB1, 0xA4, 0xF1, 0x12, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x5B, 0x1B, +0x5C, 0x45, 0x1A, 0x54, 0xF7, 0xD1, 0xAA, 0xF8, 0x10, 0x10, 0x32, 0x46, 0x4C, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, +0xE3, 0xFF, 0x9E, 0xB1, 0x4A, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x2B, 0xBB, 0x30, 0x46, 0xFF, 0xF7, 0x29, 0xFC, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x44, 0x49, 0xAA, 0xF8, 0x10, 0x40, 0x32, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0xD0, 0xFF, +0x00, 0x2E, 0xEB, 0xD1, 0xB9, 0xF8, 0x04, 0x00, 0x40, 0x4C, 0xC0, 0xF3, 0x0D, 0x00, 0xFF, 0xF7, 0x3F, 0xFF, 0x3D, 0x4B, +0x93, 0xF8, 0x04, 0x31, 0x63, 0xB3, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0x45, 0xD5, 0xF8, 0x90, 0x31, 0x9A, 0x78, +0x01, 0x2A, 0x48, 0xD0, 0x38, 0x4E, 0x28, 0xE0, 0x12, 0x2E, 0xD7, 0xD1, 0x35, 0x4B, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, +0x08, 0x38, 0xD8, 0xF8, 0x90, 0x21, 0x92, 0x78, 0x01, 0x2A, 0xCD, 0xD1, 0x98, 0xF8, 0xC0, 0x44, 0x00, 0x2C, 0xC9, 0xD1, +0x30, 0x4D, 0x07, 0xF5, 0xB2, 0x77, 0x1F, 0x44, 0xA8, 0x46, 0x40, 0x46, 0x06, 0x22, 0x39, 0x46, 0x0C, 0xF0, 0x3E, 0xFC, +0x08, 0xF1, 0x14, 0x08, 0x00, 0x28, 0x3F, 0xD0, 0x01, 0x34, 0x05, 0x2C, 0xF3, 0xD1, 0xB7, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x08, 0x43, 0x24, 0x4E, 0xD3, 0xF8, 0x90, 0x31, 0x1B, 0x79, 0xD6, 0xF8, 0x40, 0x53, 0x4F, 0xF4, 0xA4, 0x62, +0x02, 0xFB, 0x08, 0x48, 0xE0, 0x19, 0x98, 0xF8, 0xC6, 0x21, 0x9B, 0x1A, 0x8D, 0xF8, 0x07, 0x30, 0x0D, 0xF1, 0x06, 0x02, +0x0D, 0xF1, 0x07, 0x01, 0xA8, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x49, 0x1B, 0x48, 0x40, 0xF2, 0x8B, 0x42, +0xFA, 0xF7, 0xB6, 0xF9, 0xBA, 0xF8, 0x0E, 0x30, 0x75, 0xE7, 0xD5, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0xB1, 0xD0, +0x95, 0xF8, 0xC0, 0x24, 0x00, 0x2A, 0xAD, 0xD1, 0x13, 0x4B, 0x14, 0x49, 0x1B, 0x69, 0x0E, 0x4E, 0x07, 0xF1, 0x9C, 0x00, +0x19, 0x44, 0x20, 0x44, 0xD6, 0xF8, 0xE0, 0x31, 0x98, 0x47, 0xD5, 0xF8, 0x90, 0x31, 0xCA, 0xE7, 0x04, 0xEB, 0x84, 0x04, +0x05, 0xEB, 0x84, 0x04, 0x01, 0x23, 0xE3, 0x71, 0x74, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x14, 0xBC, 0x15, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x80, 0x96, 0x98, 0x00, 0x2D, 0xE9, 0xF0, 0x47, +0x04, 0x46, 0x06, 0x20, 0x25, 0x7A, 0xF8, 0xF7, 0x1F, 0xFB, 0x09, 0x28, 0x0A, 0xD0, 0x06, 0x20, 0xF8, 0xF7, 0x1A, 0xFB, +0x48, 0xB1, 0x2D, 0x4A, 0x23, 0x7A, 0x12, 0x68, 0x92, 0xF8, 0x3D, 0x20, 0x9A, 0x42, 0x0D, 0xD0, 0x02, 0x20, 0xBD, 0xE8, +0xF0, 0x87, 0x29, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x05, 0xF5, 0x7E, 0x19, 0x96, 0xF8, 0x64, 0x00, 0x60, 0xB9, +0xBD, 0xE8, 0xF0, 0x87, 0x24, 0x49, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x15, 0xFF, 0x01, 0x20, 0xFF, 0xF7, 0x60, 0xFB, +0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xA4, 0x89, 0x1F, 0x49, 0x22, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0xF9, 0xF7, 0x08, 0xFF, +0x1D, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x0B, 0xB1, 0x08, 0x2C, 0x0A, 0xD0, 0x09, 0x21, 0x06, 0x20, 0xF8, 0xF7, 0x40, 0xFA, +0x78, 0x19, 0x21, 0x46, 0xFF, 0xF7, 0xBC, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0x90, 0x31, 0x9B, 0x78, +0x01, 0x2B, 0xEF, 0xD1, 0x96, 0xF8, 0xC0, 0x64, 0x00, 0x2E, 0xEB, 0xD1, 0xDF, 0xF8, 0x44, 0x90, 0x05, 0xF5, 0xB2, 0x7A, +0xC8, 0x46, 0xBA, 0x44, 0x40, 0x46, 0x06, 0x22, 0x51, 0x46, 0x0C, 0xF0, 0x83, 0xFB, 0x08, 0xF1, 0x14, 0x08, 0x18, 0xB1, +0x01, 0x36, 0x05, 0x2E, 0xF4, 0xD1, 0xD9, 0xE7, 0x06, 0xEB, 0x86, 0x06, 0x09, 0xEB, 0x86, 0x06, 0x01, 0x23, 0xB3, 0x71, +0xD2, 0xE7, 0x00, 0xBF, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2C, 0xBC, 0x15, 0x00, 0x50, 0xBC, 0x15, 0x00, +0x2C, 0x19, 0x17, 0x00, 0xCC, 0x35, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x46, 0x4B, 0x04, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, +0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x64, 0x30, 0xC3, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0xAB, 0xB9, 0xC3, 0x79, 0xFF, 0x2B, +0x05, 0x46, 0x11, 0xD0, 0x94, 0xF8, 0x6C, 0x20, 0x9A, 0x42, 0x0D, 0xD1, 0x3D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x02, 0x66, 0x96, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x04, 0xD1, 0x90, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x01, 0xD0, +0xBD, 0xE8, 0xF8, 0x83, 0x80, 0x79, 0xB5, 0xF8, 0x0E, 0x80, 0x00, 0x38, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, +0xE5, 0xF7, 0xAE, 0xFA, 0x07, 0x46, 0x00, 0x28, 0xF0, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF7, 0xF7, 0xA5, 0xFB, 0x32, 0x46, +0xDF, 0xF8, 0xB4, 0xC0, 0xBB, 0x6C, 0x52, 0xF8, 0x26, 0x0F, 0xBC, 0xF8, 0xFC, 0x11, 0xD8, 0x66, 0x6F, 0xF0, 0x2F, 0x00, +0x83, 0xF8, 0x68, 0x00, 0x01, 0x31, 0x90, 0x88, 0xA3, 0xF8, 0x70, 0x00, 0x89, 0xB2, 0xE0, 0x6D, 0xB4, 0xF8, 0x60, 0x40, +0xA3, 0xF8, 0x76, 0x40, 0xC3, 0xF8, 0x72, 0x00, 0x14, 0x68, 0x90, 0x88, 0x83, 0xF8, 0x69, 0x90, 0x0A, 0x01, 0x83, 0xF8, +0x6A, 0x90, 0x83, 0xF8, 0x6B, 0x90, 0x9C, 0x67, 0xA3, 0xF8, 0x7C, 0x00, 0xAC, 0xF8, 0xFC, 0x11, 0xA3, 0xF8, 0x7E, 0x20, +0x2A, 0x7A, 0x3A, 0x77, 0xEA, 0x79, 0x7A, 0x77, 0x03, 0xF1, 0x68, 0x04, 0x87, 0xF8, 0x33, 0x90, 0x87, 0xF8, 0x35, 0x90, +0x08, 0x22, 0xD0, 0x21, 0x38, 0x46, 0x06, 0xF0, 0xA5, 0xFB, 0x21, 0x46, 0x38, 0x46, 0x18, 0x22, 0x05, 0xF0, 0x04, 0xFA, +0x97, 0xF8, 0x33, 0x30, 0x18, 0x33, 0x1A, 0x19, 0x08, 0x21, 0x19, 0x55, 0x01, 0x21, 0x51, 0x70, 0xF9, 0x6C, 0xA2, 0xF8, +0x02, 0x80, 0x97, 0xF8, 0x35, 0x00, 0x4A, 0x6A, 0x04, 0x30, 0x03, 0x44, 0x01, 0x3A, 0x1A, 0x44, 0x04, 0x33, 0xC1, 0xE9, +0x0A, 0x23, 0x38, 0x46, 0x05, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xE5, 0xF7, 0x5F, 0xBA, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x31, 0x4B, 0x32, 0x4A, 0x1B, 0x68, 0x2D, 0xE9, 0xF0, 0x41, 0xB3, 0xF9, +0x00, 0x30, 0xD2, 0xF8, 0x00, 0x80, 0x2F, 0x4F, 0x98, 0xF8, 0x3D, 0x50, 0x00, 0x2B, 0x06, 0x46, 0x45, 0xDB, 0x2C, 0x23, +0x06, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x06, 0x00, 0xF7, 0xF7, 0x64, 0xFF, 0x4F, 0xF4, 0xA4, 0x61, 0x03, 0x46, 0x98, 0xF8, +0x3D, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x01, 0xFB, 0x05, 0x71, 0x01, 0xF5, 0xB5, 0x72, 0x04, 0x46, 0x01, 0xF5, 0xC5, 0x71, +0xD2, 0xF8, 0x00, 0xE0, 0xD2, 0xF8, 0x04, 0xC0, 0x90, 0x68, 0xD2, 0xF8, 0x0C, 0x80, 0xC3, 0xF8, 0x0C, 0x80, 0x10, 0x32, +0x8A, 0x42, 0xC3, 0xF8, 0x00, 0xE0, 0xC3, 0xF8, 0x04, 0xC0, 0x98, 0x60, 0x03, 0xF1, 0x10, 0x03, 0xEC, 0xD1, 0x4F, 0xF4, +0xA4, 0x61, 0x12, 0x78, 0x1A, 0x70, 0x01, 0xFB, 0x05, 0x75, 0x36, 0xBA, 0xD5, 0xF8, 0x64, 0x01, 0xB5, 0xF8, 0x68, 0x31, +0xE3, 0x84, 0x06, 0x21, 0xC4, 0xF8, 0x22, 0x00, 0xA6, 0x62, 0x08, 0x46, 0xF8, 0xF7, 0x2A, 0xF9, 0x41, 0xF6, 0x08, 0x00, +0x0E, 0x4A, 0x06, 0x21, 0xF7, 0xF7, 0x88, 0xFD, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xF7, 0xF7, 0x55, 0xBF, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x05, 0x73, 0xD3, 0xF8, 0xCC, 0x31, 0x00, 0x2B, 0xB1, 0xDB, 0x07, 0x49, 0x07, 0x48, 0x4F, 0xF4, +0xAB, 0x62, 0xF9, 0xF7, 0xF9, 0xFF, 0xAA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x64, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0xC0, 0x27, 0x09, 0x00, 0x70, 0x79, 0x15, 0x00, 0x74, 0xBC, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x21, 0x04, 0x46, 0x41, 0xF6, +0x08, 0x00, 0xF7, 0xF7, 0x11, 0xFE, 0x1C, 0xB9, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x20, 0xBC, 0x20, 0x46, 0xBD, 0xE8, +0x10, 0x40, 0xFF, 0xF7, 0xFF, 0xB9, 0x00, 0xBF, 0x08, 0xB5, 0x06, 0x20, 0xF8, 0xF7, 0x96, 0xF9, 0xA0, 0xF1, 0x06, 0x00, +0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x08, 0xBD, 0x00, 0xB5, 0x83, 0xB0, 0x0D, 0xF1, 0x07, 0x02, 0xF8, 0xF7, 0xDE, 0xFD, +0xB8, 0xB1, 0x9D, 0xF8, 0x07, 0x30, 0x1D, 0x2B, 0x16, 0xD9, 0x02, 0x89, 0x92, 0x00, 0x0A, 0x3B, 0x92, 0xB2, 0x9B, 0x1A, +0xDB, 0xB2, 0x15, 0x2B, 0x0E, 0xD9, 0x0A, 0x30, 0x02, 0x3B, 0x81, 0x5A, 0x89, 0x00, 0x89, 0xB2, 0x5B, 0x1A, 0xDB, 0xB2, +0x13, 0x2B, 0x10, 0x44, 0x04, 0xD9, 0x04, 0x30, 0x40, 0x5A, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xFB, 0x00, 0x20, 0x03, 0xB0, +0x5D, 0xF8, 0x04, 0xFB, 0x2D, 0xE9, 0xF0, 0x4F, 0x4F, 0xF4, 0xA4, 0x68, 0x95, 0xB0, 0xDF, 0xF8, 0x50, 0x93, 0xDF, 0xF8, +0x50, 0xB3, 0x08, 0xFB, 0x00, 0xF3, 0x07, 0x93, 0x4B, 0x44, 0x05, 0x46, 0xD3, 0xF8, 0x90, 0x01, 0x93, 0xF8, 0x6C, 0x40, +0x80, 0x78, 0x02, 0x93, 0x17, 0x46, 0x4F, 0xF4, 0x1E, 0x78, 0x00, 0x38, 0x08, 0xFB, 0x04, 0xB6, 0x0A, 0x46, 0x3B, 0x78, +0xD6, 0xF8, 0xB0, 0xA0, 0x04, 0x94, 0x18, 0xBF, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0x05, 0x92, 0x06, 0x93, 0xE5, 0xF7, +0x6F, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0xED, 0x80, 0x02, 0x9B, 0x04, 0x46, 0x21, 0x46, 0x18, 0x46, 0xF7, 0xF7, 0x64, 0xFA, +0xB9, 0x4B, 0x96, 0xF8, 0x23, 0x00, 0xD3, 0xF8, 0x34, 0x21, 0xA3, 0x6C, 0x02, 0x93, 0x00, 0x21, 0x90, 0x47, 0x02, 0x9B, +0x03, 0x90, 0x03, 0xF1, 0x68, 0x02, 0x08, 0x92, 0x00, 0x28, 0x40, 0xF0, 0xD9, 0x80, 0xB2, 0x49, 0xB1, 0xF8, 0xFC, 0x21, +0x01, 0x32, 0x92, 0xB2, 0x08, 0x20, 0x83, 0xF8, 0x68, 0x00, 0x10, 0x01, 0x01, 0x26, 0x80, 0xB2, 0x83, 0xF8, 0x69, 0x60, +0x09, 0x90, 0xA1, 0xF8, 0xFC, 0x21, 0x04, 0x99, 0x02, 0x93, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0xB2, 0x4F, 0xF4, +0xA4, 0x66, 0x52, 0xF8, 0x26, 0x1F, 0xD9, 0x66, 0x06, 0xFB, 0x05, 0x96, 0x91, 0x88, 0xF0, 0x6D, 0xB6, 0xF8, 0x60, 0x20, +0xA3, 0xF8, 0x76, 0x20, 0x4F, 0xF0, 0x00, 0x08, 0xA3, 0xF8, 0x70, 0x10, 0xC3, 0xF8, 0x72, 0x00, 0x05, 0x99, 0x83, 0xF8, +0x6A, 0x80, 0x83, 0xF8, 0x6B, 0x80, 0x06, 0x22, 0x03, 0xF1, 0x78, 0x00, 0x0C, 0xF0, 0xDC, 0xF9, 0x09, 0x9B, 0x96, 0xF8, +0x63, 0x20, 0x19, 0x01, 0x02, 0x9B, 0xA3, 0xF8, 0x7E, 0x10, 0x22, 0x77, 0x96, 0xF8, 0x6C, 0x20, 0x62, 0x77, 0x03, 0x9A, +0x00, 0x2A, 0x00, 0xF0, 0xE1, 0x80, 0x1A, 0x22, 0x83, 0xF8, 0x80, 0x80, 0x83, 0xF8, 0x81, 0x80, 0x02, 0x92, 0x7A, 0x78, +0x00, 0x21, 0x12, 0xF0, 0x40, 0x02, 0xCD, 0xE9, 0x0A, 0x11, 0x40, 0xF0, 0xB5, 0x80, 0x84, 0xF8, 0x33, 0x20, 0x84, 0xF8, +0x35, 0x20, 0x89, 0x4B, 0x02, 0x9A, 0x93, 0xE8, 0x03, 0x00, 0x08, 0x9B, 0x13, 0x44, 0x1E, 0x46, 0x0D, 0xF1, 0x30, 0x0C, +0x07, 0x9B, 0x8C, 0xE8, 0x03, 0x00, 0x08, 0x22, 0x61, 0x46, 0x30, 0x46, 0x03, 0xF1, 0x5C, 0x08, 0x0C, 0xF0, 0xA8, 0xF9, +0x7F, 0x4B, 0xD3, 0xE9, 0x02, 0x01, 0x08, 0x22, 0x0E, 0xAB, 0x83, 0xE8, 0x03, 0x00, 0xC8, 0x44, 0x19, 0x46, 0xB0, 0x18, +0x0C, 0xF0, 0x9C, 0xF9, 0x06, 0x22, 0x41, 0x46, 0x06, 0xF1, 0x10, 0x00, 0x0C, 0xF0, 0x96, 0xF9, 0x4F, 0xF4, 0xA4, 0x60, +0x00, 0xFB, 0x05, 0x95, 0x9D, 0xF9, 0x18, 0x20, 0xD5, 0xF8, 0xC4, 0x34, 0xB3, 0x75, 0xD5, 0xF8, 0xC4, 0x34, 0x1B, 0x0A, +0xF3, 0x75, 0xB5, 0xF8, 0xC6, 0x34, 0x33, 0x76, 0x95, 0xF8, 0xC7, 0x34, 0x73, 0x76, 0x7B, 0x78, 0x58, 0x06, 0x67, 0xD4, +0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x2A, 0x01, 0x4F, 0xF0, 0x0A, 0x02, 0xA8, 0xBF, 0x07, 0xF1, 0x28, 0x01, 0x06, 0xF1, +0x1A, 0x00, 0x0C, 0xF0, 0x73, 0xF9, 0xE2, 0x6C, 0x94, 0xF8, 0x35, 0x50, 0x53, 0x6A, 0x02, 0x99, 0xA4, 0x65, 0x24, 0x35, +0x0D, 0x44, 0x01, 0x3B, 0x2B, 0x44, 0x00, 0x20, 0x29, 0x1D, 0x60, 0x65, 0xC2, 0xE9, 0x0A, 0x31, 0x03, 0x9B, 0x6B, 0xB1, +0x04, 0x9B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xB3, 0x93, 0xF8, 0x23, 0x30, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, +0xA5, 0x91, 0xB9, 0xF1, 0x21, 0x0F, 0x6A, 0xD1, 0x7B, 0x78, 0x59, 0x06, 0x2F, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, +0x00, 0xF0, 0x53, 0x81, 0x52, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x09, 0xD5, 0x9A, 0xF8, 0x60, 0x30, 0x01, 0x2B, +0x0A, 0xF1, 0x64, 0x09, 0x40, 0xF2, 0x36, 0x81, 0x03, 0x2B, 0x00, 0xF0, 0x34, 0x81, 0x20, 0x46, 0x05, 0x21, 0xE5, 0xF7, +0x8F, 0xF8, 0x15, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x96, 0xF8, 0x23, 0x20, 0x08, 0xFB, 0x02, 0xB8, 0x6F, 0xF0, 0x77, 0x02, +0xB8, 0xF8, 0x34, 0x11, 0x83, 0xF8, 0x68, 0x20, 0x4A, 0x1C, 0x01, 0x20, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0xF8, 0x69, 0x00, +0x09, 0x91, 0x03, 0x90, 0xA8, 0xF8, 0x34, 0x21, 0x21, 0xE7, 0x3D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xDE, 0xD5, +0xBA, 0xF1, 0x00, 0x0F, 0xDB, 0xD0, 0xD0, 0xE7, 0x00, 0x2A, 0xB8, 0xBF, 0x07, 0xF1, 0x32, 0x01, 0x4F, 0xF0, 0x0A, 0x02, +0xA8, 0xBF, 0x07, 0xF1, 0x30, 0x01, 0x06, 0xF1, 0x1A, 0x00, 0x0C, 0xF0, 0x0B, 0xF9, 0x96, 0xE7, 0xE2, 0x6C, 0xB3, 0xF8, +0x68, 0x10, 0x90, 0x6B, 0x41, 0xF4, 0x80, 0x41, 0xC2, 0x68, 0xA3, 0xF8, 0x68, 0x10, 0x22, 0xF4, 0x7F, 0x73, 0x9A, 0xF8, +0x62, 0x20, 0x08, 0x99, 0x23, 0xF0, 0x03, 0x03, 0x13, 0x43, 0xC3, 0x60, 0x9A, 0xF8, 0x60, 0x30, 0x02, 0x98, 0x0E, 0x18, +0x04, 0x2B, 0x00, 0xF2, 0xD3, 0x81, 0xDF, 0xE8, 0x03, 0xF0, 0x1E, 0x51, 0xBA, 0x1E, 0x85, 0x00, 0x18, 0x22, 0x02, 0x92, +0x21, 0xE7, 0x4F, 0xEA, 0x09, 0x20, 0x40, 0xF0, 0x08, 0x00, 0xF7, 0xF7, 0xFD, 0xFF, 0x01, 0x28, 0x8C, 0xD1, 0x1E, 0x4B, +0x09, 0x99, 0x09, 0xEB, 0x49, 0x09, 0x03, 0xEB, 0xC9, 0x09, 0x02, 0x22, 0xD9, 0xF8, 0x14, 0x00, 0x02, 0x90, 0x05, 0xF0, +0x1D, 0xFB, 0x02, 0x98, 0x05, 0xF0, 0xF8, 0xFA, 0x7C, 0xE7, 0x04, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, +0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, +0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0xBD, 0xF8, 0x02, 0x99, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x53, 0x52, +0xBD, 0xF8, 0x2A, 0x30, 0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x73, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, +0x02, 0x93, 0xF0, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x8C, 0xBC, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, +0xF4, 0xE4, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x08, 0x22, 0x0C, 0x23, 0x84, 0xF8, 0x33, 0x20, +0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, +0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x89, 0xF8, 0xBD, 0xF8, 0x28, 0x20, 0x02, 0x99, +0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x08, 0x9A, 0x53, 0x52, 0x9D, 0xF8, 0x28, 0x30, +0x9A, 0xF8, 0x61, 0x20, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, +0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, 0x33, 0x30, 0xCB, 0x18, 0x02, 0x93, 0xAE, 0xE6, 0x10, 0x23, 0x12, 0x21, +0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x0F, 0x2A, 0xDA, 0xF8, 0x48, 0x30, 0xDA, 0xF8, 0x4C, 0x20, 0x40, 0xF2, +0x00, 0x81, 0x02, 0x33, 0x42, 0xF1, 0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x08, 0x22, +0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, 0x50, 0xF8, 0x9A, 0xF8, 0x61, 0x30, 0x33, 0x80, 0xBD, 0xF8, 0x28, 0x30, 0x73, 0x80, +0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0xBD, 0xF8, 0x2E, 0x30, 0x33, 0x81, 0x45, 0xF6, +0x36, 0x43, 0x73, 0x81, 0xB3, 0x81, 0xF3, 0x81, 0x33, 0x82, 0x02, 0x9A, 0x94, 0xF8, 0x33, 0x30, 0x1A, 0x44, 0x02, 0x92, +0x79, 0xE6, 0x08, 0x23, 0x84, 0xF8, 0x33, 0x30, 0x84, 0xF8, 0x35, 0x30, 0xDA, 0xE9, 0x12, 0x32, 0x01, 0x33, 0x42, 0xF1, +0x00, 0x02, 0x18, 0x46, 0x11, 0x46, 0x53, 0x46, 0xE3, 0xE9, 0x12, 0x01, 0x06, 0x22, 0x19, 0x46, 0x0A, 0xA8, 0x0C, 0xF0, +0x21, 0xF8, 0x08, 0x9A, 0xBD, 0xF8, 0x28, 0x30, 0x10, 0x46, 0x02, 0x9A, 0x83, 0x52, 0x9A, 0xF8, 0x61, 0x30, 0x9B, 0x03, +0x43, 0xF4, 0x00, 0x53, 0x73, 0x80, 0xBD, 0xF8, 0x2A, 0x30, 0xB3, 0x80, 0xBD, 0xF8, 0x2C, 0x30, 0xF3, 0x80, 0x94, 0xF8, +0x33, 0x30, 0xD3, 0x18, 0x02, 0x93, 0x4E, 0xE6, 0x31, 0xD0, 0x03, 0x9B, 0x0D, 0xF1, 0x40, 0x0B, 0x00, 0x2B, 0x5D, 0xD1, +0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xEC, 0x37, 0x2F, 0x44, 0xBF, 0xB2, +0x5C, 0xE0, 0x05, 0x99, 0x06, 0x22, 0x04, 0xF1, 0x0C, 0x00, 0x0B, 0xF0, 0xF3, 0xFF, 0x06, 0x22, 0x41, 0x46, 0x04, 0xF1, +0x12, 0x00, 0x0B, 0xF0, 0xED, 0xFF, 0x03, 0x9B, 0x00, 0x22, 0xE2, 0x76, 0x00, 0x2B, 0x78, 0xD0, 0x94, 0xF8, 0x35, 0x10, +0x94, 0xF8, 0x33, 0x30, 0x69, 0x48, 0x0B, 0x44, 0xEB, 0x1A, 0xD0, 0xF8, 0x7C, 0x73, 0x00, 0x92, 0x1A, 0x3B, 0x32, 0x46, +0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x8A, 0xE6, 0x03, 0x9B, 0x94, 0xF8, 0x33, 0x70, 0x00, 0x2B, 0x00, 0xF0, +0x82, 0x80, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF2, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, +0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0x7E, 0xFE, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, +0x57, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, +0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF7, 0xF7, 0x45, 0xF8, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x05, 0xFA, 0x9A, 0xF8, +0x60, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x85, 0x80, 0x94, 0xF8, 0x33, 0x70, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, +0x7F, 0x47, 0xEA, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x39, 0x1F, 0x30, 0x46, 0xDA, 0xF7, +0x51, 0xFE, 0x9A, 0xF8, 0x60, 0x30, 0xBA, 0xF8, 0x48, 0x10, 0xBA, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x40, 0x10, 0x8D, 0xF8, +0x42, 0x20, 0x49, 0x46, 0x7B, 0xBB, 0x05, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x84, 0xFF, 0x58, 0x46, 0x08, 0x21, +0xF7, 0xF7, 0xDA, 0xF9, 0x03, 0x20, 0xDA, 0xF7, 0x71, 0xFE, 0x39, 0x46, 0x02, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0x04, 0xF8, +0x39, 0x46, 0x30, 0x46, 0xF7, 0xF7, 0xFA, 0xF9, 0x20, 0x46, 0x05, 0x21, 0xE4, 0xF7, 0xC6, 0xFE, 0x35, 0xE6, 0x94, 0xF8, +0x35, 0x20, 0x94, 0xF8, 0x33, 0x30, 0x2D, 0x49, 0x13, 0x44, 0xD1, 0xF8, 0x7C, 0x73, 0x03, 0x99, 0x00, 0x91, 0xEB, 0x1A, +0x18, 0x3B, 0x32, 0x46, 0x0A, 0xF1, 0x50, 0x01, 0x20, 0x46, 0xB8, 0x47, 0x10, 0xE6, 0x01, 0x33, 0x42, 0xF1, 0x00, 0x02, +0xFE, 0xE6, 0x0D, 0x22, 0x0D, 0xF1, 0x43, 0x00, 0x0B, 0xF0, 0x54, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0xAA, 0xF9, +0xCE, 0xE7, 0x94, 0xF8, 0x35, 0x30, 0x1F, 0x44, 0xC7, 0xF5, 0x7F, 0x47, 0xF4, 0x37, 0x2F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, +0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x30, 0x46, 0xDA, 0xF7, 0xFC, 0xFD, 0xDA, 0xF8, 0x48, 0xC0, 0xDA, 0xF8, 0x4C, 0x00, +0x16, 0x49, 0x4F, 0xEA, 0x1C, 0x43, 0x43, 0xEA, 0x00, 0x43, 0x0D, 0xF1, 0x40, 0x0B, 0x0B, 0x60, 0x42, 0x46, 0x5B, 0x46, +0x48, 0x46, 0xA1, 0xF8, 0x04, 0xC0, 0xF6, 0xF7, 0xC3, 0xFF, 0x58, 0x46, 0x10, 0x21, 0xF7, 0xF7, 0x83, 0xF9, 0x9A, 0xF8, +0x60, 0x30, 0x00, 0x2B, 0x3F, 0xF4, 0x20, 0xAF, 0x03, 0x2B, 0xA1, 0xD1, 0x1C, 0xE7, 0x03, 0x2B, 0x9E, 0xD1, 0x77, 0xE7, +0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xDC, 0xAE, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, +0x2C, 0x62, 0xF9, 0xF7, 0x6B, 0xFC, 0xD4, 0xE6, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x34, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x05, 0xDB, 0x0A, 0x4B, 0x00, 0x20, 0x5B, 0x68, 0x98, 0x47, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x10, 0xFE, +0x02, 0x28, 0xF4, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x31, 0x12, 0xF9, 0xF7, 0x48, 0xFC, 0xED, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xC0, 0xBC, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x0C, 0x46, 0x36, 0x49, 0x60, 0x7C, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x86, 0xB0, 0x90, 0xF8, 0x62, 0x10, +0x00, 0x25, 0x02, 0x29, 0x98, 0x46, 0x8D, 0xF8, 0x0B, 0x50, 0x10, 0xD0, 0x04, 0x25, 0x41, 0x46, 0x02, 0x23, 0x41, 0xF6, +0x05, 0x40, 0xF7, 0xF7, 0x43, 0xFB, 0x05, 0x70, 0x9D, 0xF8, 0x0B, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0x6D, 0xFB, 0x00, 0x20, +0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x90, 0xF8, 0x64, 0x10, 0x09, 0xB1, 0x08, 0x25, 0xEA, 0xE7, 0x07, 0x20, 0x01, 0x92, +0xF7, 0xF7, 0xD2, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0xF6, 0xD1, 0xA7, 0x78, 0x20, 0x7C, 0x21, 0x88, 0x1F, 0x4E, 0x8D, 0xF8, +0x0C, 0x70, 0x8D, 0xF8, 0x0D, 0x00, 0xA7, 0x68, 0xE0, 0x68, 0xAD, 0xF8, 0x0E, 0x10, 0x21, 0x79, 0x75, 0x6C, 0xAD, 0xF8, +0x12, 0x00, 0x8D, 0xF8, 0x14, 0x10, 0xAD, 0xF8, 0x10, 0x70, 0x0D, 0xF1, 0x0B, 0x01, 0x03, 0xA8, 0xA8, 0x47, 0x01, 0x9A, +0x05, 0x46, 0x10, 0xBB, 0xF6, 0x6C, 0x60, 0x7C, 0x9D, 0xF8, 0x0B, 0x10, 0xB0, 0x47, 0xEF, 0xF3, 0x10, 0x81, 0x11, 0xF0, +0x01, 0x0F, 0x01, 0x9A, 0x03, 0xD1, 0x72, 0xB6, 0x0E, 0x49, 0x01, 0x20, 0x08, 0x60, 0x0E, 0x48, 0x0E, 0x4F, 0x04, 0x68, +0x79, 0x68, 0x66, 0x1C, 0x41, 0xF0, 0x10, 0x01, 0x06, 0x60, 0x79, 0x60, 0x00, 0x2E, 0xAE, 0xD0, 0x07, 0x49, 0x04, 0x60, +0x09, 0x68, 0x00, 0x2C, 0xA9, 0xD1, 0x00, 0x29, 0xA7, 0xD0, 0x62, 0xB6, 0xA5, 0xE7, 0x01, 0x25, 0xA3, 0xE7, 0x00, 0xBF, +0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x43, 0x0C, 0x46, 0x85, 0xB0, 0x90, 0x46, 0x4F, 0xF4, 0x80, 0x70, 0x4A, 0x69, 0x4D, 0x49, 0x4E, 0x4F, +0x99, 0x46, 0xF9, 0xF7, 0x8D, 0xF9, 0x94, 0xF8, 0x33, 0x60, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x06, 0x75, 0x95, 0xF8, +0x62, 0x10, 0x02, 0x29, 0x11, 0xD0, 0x04, 0x25, 0x42, 0x46, 0x49, 0x46, 0x04, 0x23, 0x41, 0xF6, 0x01, 0x40, 0xF7, 0xF7, +0xC3, 0xFA, 0x05, 0x70, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x70, 0xF7, 0xF7, 0xED, 0xFA, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x83, 0x07, 0x20, 0xF7, 0xF7, 0x58, 0xFD, 0xC0, 0xB9, 0x95, 0xF8, 0x64, 0x30, 0xBB, 0xB9, 0x3B, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x13, 0xDB, 0x23, 0x7F, 0x39, 0x49, 0x00, 0x93, 0xD4, 0xE9, 0x05, 0x23, 0x0C, 0x60, +0x0D, 0xF1, 0x0D, 0x00, 0x04, 0xF1, 0x0E, 0x01, 0xFD, 0xF7, 0xAC, 0xF9, 0x05, 0x46, 0x70, 0xB1, 0x01, 0x25, 0xD1, 0xE7, +0x08, 0x25, 0xCF, 0xE7, 0x09, 0x25, 0xCD, 0xE7, 0x2B, 0x6C, 0x00, 0x2B, 0xE8, 0xD0, 0x2F, 0x49, 0x2F, 0x48, 0x56, 0x22, +0xF9, 0xF7, 0x72, 0xFB, 0xE2, 0xE7, 0xE1, 0x89, 0x20, 0x7C, 0xDF, 0xF8, 0xB4, 0x80, 0xFB, 0xF7, 0x9B, 0xFF, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x06, 0xF2, 0x07, 0xEB, 0x02, 0x09, 0xC9, 0xF8, 0x90, 0x01, 0x94, 0xF9, 0x12, 0x30, 0x03, 0x71, +0xD4, 0xE9, 0x05, 0x31, 0xA9, 0xF8, 0x96, 0x11, 0xA9, 0xF8, 0x94, 0x31, 0x23, 0x7F, 0x89, 0xF8, 0xC5, 0x31, 0x04, 0x2B, +0x08, 0xBF, 0x03, 0x23, 0x89, 0xF8, 0xC4, 0x31, 0x89, 0xF8, 0xC6, 0x51, 0xD8, 0xF8, 0x4C, 0x30, 0x94, 0xF8, 0x33, 0x00, +0x9D, 0xF8, 0x0D, 0x10, 0x15, 0x46, 0x98, 0x47, 0x23, 0x7C, 0xA3, 0xB1, 0x00, 0xF0, 0x8C, 0xFA, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x06, 0x73, 0x78, 0x19, 0xD3, 0xF8, 0x90, 0x31, 0xD8, 0xF8, 0x40, 0x43, 0x1B, 0x79, 0x8D, 0xF8, 0x0E, 0x30, +0x0D, 0xF1, 0x0F, 0x02, 0x0D, 0xF1, 0x0E, 0x01, 0xA0, 0x47, 0x01, 0x20, 0x92, 0xE7, 0x05, 0xF5, 0xCE, 0x70, 0x38, 0x44, +0x01, 0x21, 0xFC, 0xF7, 0x45, 0xF9, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, 0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, +0x01, 0x23, 0x89, 0xF8, 0xC1, 0x31, 0xD9, 0xE7, 0xEC, 0xBC, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0xA2, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x4F, 0x88, +0x0D, 0x48, 0x0C, 0x46, 0x16, 0x46, 0x04, 0x31, 0x3A, 0x46, 0x1D, 0x46, 0x0B, 0xF0, 0xAE, 0xFD, 0xDF, 0xF8, 0x28, 0xC0, +0x32, 0x46, 0x29, 0x46, 0x02, 0x23, 0x41, 0xF6, 0x09, 0x40, 0xAC, 0xF8, 0x00, 0x70, 0xF7, 0xF7, 0x1B, 0xFA, 0x01, 0x22, +0x02, 0x70, 0x22, 0x78, 0x42, 0x70, 0xF7, 0xF7, 0x45, 0xFA, 0x00, 0x20, 0xF8, 0xBD, 0x00, 0xBF, 0x14, 0x2A, 0x17, 0x00, +0x14, 0x2C, 0x17, 0x00, 0x08, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0F, 0xDB, 0x07, 0x20, +0xF7, 0xF7, 0xA6, 0xFC, 0x01, 0x28, 0x06, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0xA1, 0xFC, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, +0x08, 0xBD, 0x00, 0xF0, 0x01, 0xFA, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x96, 0xFC, 0x01, 0x28, 0xEA, 0xD0, +0x07, 0x20, 0xF7, 0xF7, 0x91, 0xFC, 0x00, 0x28, 0xE5, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x8C, 0xFC, 0x03, 0x28, 0xE0, 0xD0, +0x03, 0x49, 0x04, 0x48, 0xC2, 0x22, 0xF9, 0xF7, 0xC5, 0xFA, 0xDA, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, +0xDB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x70, 0xFC, 0x01, 0x28, 0xF6, 0xD0, 0x05, 0x49, 0x06, 0x48, +0xE6, 0x22, 0xF9, 0xF7, 0xA9, 0xFA, 0x00, 0xF0, 0xCD, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x84, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0x03, 0xDB, 0x00, 0xF0, 0xBB, 0xF9, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0xF7, 0xF7, 0x50, 0xFC, 0x03, 0x28, 0xF6, 0xD0, +0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x4B, 0x12, 0xF9, 0xF7, 0x88, 0xFA, 0x00, 0xF0, 0xAC, 0xF9, 0x00, 0x20, 0x08, 0xBD, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xB4, 0xBD, 0x15, 0x00, 0x08, 0xB5, 0x11, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x06, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x34, 0xFC, 0x03, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x08, 0xBD, +0x07, 0x20, 0xF7, 0xF7, 0x2D, 0xFC, 0x03, 0x28, 0xF3, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x28, 0xFC, 0x00, 0x28, 0xEE, 0xD0, +0x06, 0x49, 0x07, 0x48, 0x40, 0xF2, 0x65, 0x12, 0xF9, 0xF7, 0x60, 0xFA, 0xE7, 0xE7, 0x00, 0xF0, 0x83, 0xF9, 0x00, 0x20, +0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xDC, 0xBD, 0x15, 0x00, 0xF8, 0xB5, 0x0C, 0x46, +0x4F, 0xF4, 0x80, 0x70, 0x13, 0x49, 0x16, 0x46, 0x1D, 0x46, 0xF9, 0xF7, 0x21, 0xF8, 0x24, 0x78, 0x11, 0x4B, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x94, 0xF8, 0x62, 0x70, 0x02, 0x2F, 0x02, 0xD1, 0x94, 0xF8, 0x64, 0x30, 0x3B, 0xB9, +0x32, 0x46, 0x29, 0x46, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, 0xBE, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x07, 0x20, 0xF7, 0xF7, +0xF3, 0xFB, 0x05, 0x46, 0x28, 0xB9, 0x06, 0x4B, 0x20, 0x46, 0x9B, 0x68, 0x98, 0x47, 0x28, 0x46, 0xF8, 0xBD, 0x38, 0x46, +0xF8, 0xBD, 0x00, 0xBF, 0x30, 0xBE, 0x15, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0xB5, 0x0C, 0x46, +0x21, 0x49, 0x20, 0x78, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x00, 0x10, 0x82, 0xB0, 0x90, 0xF8, 0x62, 0x50, 0x02, 0x2D, +0x19, 0x46, 0x06, 0xD0, 0x41, 0xF6, 0x07, 0x40, 0xF7, 0xF7, 0x96, 0xF9, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x90, 0xF8, +0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD1, 0x07, 0x20, 0xCD, 0xE9, 0x00, 0x21, 0xF7, 0xF7, 0xC4, 0xFB, 0xDD, 0xE9, 0x00, 0x21, +0x00, 0x28, 0xEB, 0xD1, 0x12, 0x4B, 0x20, 0x78, 0x5B, 0x6D, 0x98, 0x47, 0xEF, 0xF3, 0x10, 0x83, 0x13, 0xF0, 0x01, 0x0F, +0xDD, 0xE9, 0x00, 0x21, 0x03, 0xD1, 0x72, 0xB6, 0x0D, 0x4B, 0x01, 0x20, 0x18, 0x60, 0x0D, 0x48, 0x0D, 0x4E, 0x04, 0x68, +0x73, 0x68, 0x65, 0x1C, 0x23, 0xF0, 0x10, 0x03, 0x05, 0x60, 0x73, 0x60, 0x00, 0x2D, 0xD1, 0xD0, 0x06, 0x4B, 0x04, 0x60, +0x1B, 0x68, 0x00, 0x2C, 0xCC, 0xD1, 0x00, 0x2B, 0xCA, 0xD0, 0x62, 0xB6, 0xC8, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0x10, 0xB5, 0x22, 0x4C, +0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x28, 0xDB, 0x07, 0x20, 0xF7, 0xF7, 0x88, 0xFB, 0x01, 0x28, 0x13, 0xD1, +0x23, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x03, 0xDB, 0x00, 0xF0, 0x9B, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x19, 0x4B, +0x5B, 0x68, 0x00, 0x2B, 0xF7, 0xD0, 0x18, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x0B, 0x12, 0xF9, 0xF7, 0xB3, 0xF9, 0xF0, 0xE7, +0x07, 0x20, 0xF7, 0xF7, 0x6F, 0xFB, 0x03, 0x28, 0xED, 0xD1, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x03, 0x40, 0xF7, 0xF7, +0x2D, 0xF9, 0x00, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xBB, 0xFA, 0xE2, 0xE7, 0x07, 0x20, 0xF7, 0xF7, 0x5F, 0xFB, 0x01, 0x28, +0xD1, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x5A, 0xFB, 0x00, 0x28, 0xCC, 0xD0, 0x07, 0x20, 0xF7, 0xF7, 0x55, 0xFB, 0x03, 0x28, +0xC7, 0xD0, 0x05, 0x49, 0x06, 0x48, 0x40, 0xF2, 0x03, 0x12, 0xF9, 0xF7, 0x8D, 0xF9, 0xC0, 0xE7, 0x38, 0x36, 0x17, 0x00, +0x94, 0xBA, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x3C, 0xBE, 0x15, 0x00, 0xFC, 0xBC, 0x15, 0x00, 0x08, 0xB5, 0x0C, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDB, 0xBD, 0xE8, 0x08, 0x40, 0x09, 0x48, 0xF7, 0xF7, 0x1E, 0xBD, +0x08, 0x4B, 0x5B, 0x68, 0x00, 0x2B, 0xF6, 0xD0, 0x07, 0x48, 0x08, 0x49, 0x2D, 0x22, 0xF9, 0xF7, 0x6D, 0xF9, 0xBD, 0xE8, +0x08, 0x40, 0x02, 0x48, 0xF7, 0xF7, 0x10, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x98, 0xBA, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, +0x3C, 0xBE, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x10, 0xB5, 0x06, 0x4C, 0x00, 0x21, 0x20, 0x46, 0x10, 0x22, 0xD4, 0xF7, +0x6F, 0xFC, 0x00, 0x21, 0x21, 0x73, 0x07, 0x20, 0xBD, 0xE8, 0x10, 0x40, 0xF7, 0xF7, 0x68, 0xBA, 0x94, 0xBA, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0xDF, 0xF8, 0xD8, 0x80, 0x05, 0x46, 0x04, 0x23, 0x07, 0x22, 0x0C, 0x21, 0x41, 0xF6, 0x01, 0x40, +0xD8, 0xF8, 0x00, 0x60, 0xF7, 0xF7, 0x5E, 0xF8, 0x04, 0x46, 0x95, 0xB1, 0x96, 0xF8, 0x33, 0x30, 0x63, 0x70, 0x20, 0x46, +0x25, 0x70, 0xF7, 0xF7, 0x85, 0xF8, 0xA6, 0xF1, 0x0C, 0x00, 0xF7, 0xF7, 0xCD, 0xF8, 0x00, 0x21, 0xC8, 0xF8, 0x00, 0x10, +0x07, 0x20, 0xBD, 0xE8, 0xF0, 0x47, 0xF7, 0xF7, 0x43, 0xBA, 0x04, 0x23, 0x29, 0x46, 0x07, 0x22, 0x1E, 0x20, 0x96, 0xF8, +0x33, 0x70, 0xF7, 0xF7, 0x41, 0xF8, 0x21, 0x4A, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x07, 0x29, 0x4F, 0xF0, 0x01, 0x0A, +0x80, 0xF8, 0x02, 0xA0, 0x99, 0xF8, 0x63, 0x20, 0xC2, 0x70, 0xF7, 0xF7, 0x63, 0xF8, 0xF1, 0x6A, 0x32, 0x8E, 0xD9, 0xF8, +0x40, 0x30, 0xC9, 0xF8, 0xB0, 0x14, 0xA9, 0xF8, 0xE0, 0x20, 0x89, 0xF8, 0xDE, 0x50, 0x1B, 0x7E, 0xA3, 0x70, 0x96, 0xF8, +0x33, 0x30, 0xDF, 0xF8, 0x54, 0xC0, 0x0A, 0x33, 0xE3, 0x70, 0x96, 0xE8, 0x0F, 0x00, 0x4F, 0xF4, 0x1E, 0x7E, 0x0A, 0x37, +0x0E, 0xFB, 0x07, 0xC7, 0x07, 0xF1, 0xB8, 0x0C, 0xAC, 0xE8, 0x07, 0x00, 0x02, 0x22, 0x87, 0xF8, 0x30, 0x20, 0x8C, 0xF8, +0x00, 0x30, 0x38, 0x46, 0xFB, 0xF7, 0xA0, 0xFF, 0x97, 0xF8, 0x56, 0x31, 0xA7, 0xF8, 0x26, 0xA0, 0x43, 0xF0, 0x10, 0x03, +0x87, 0xF8, 0x56, 0x31, 0x96, 0xF8, 0x33, 0x30, 0x03, 0xF1, 0x0A, 0x02, 0x87, 0xF8, 0x23, 0x20, 0xA4, 0xE7, 0x00, 0xBF, +0x18, 0x88, 0x17, 0x00, 0x94, 0xBA, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x10, 0xB5, 0x0C, 0x48, 0xF7, 0xF7, 0xC6, 0xFC, +0x0B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x05, 0xDB, 0x04, 0xF1, 0x0C, 0x00, 0xBD, 0xE8, +0x10, 0x40, 0xF7, 0xF7, 0x17, 0xB8, 0x00, 0x28, 0xF7, 0xD1, 0x05, 0x49, 0x05, 0x48, 0xCB, 0x22, 0xF9, 0xF7, 0xC2, 0xF8, +0xF1, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA8, 0xAB, 0x15, 0x00, +0x2D, 0xE9, 0xF8, 0x4F, 0x44, 0x4B, 0xDF, 0xF8, 0x1C, 0xB1, 0x1C, 0x68, 0x07, 0x22, 0x08, 0x23, 0x00, 0x21, 0x18, 0x20, +0x94, 0xF8, 0x33, 0x90, 0xF6, 0xF7, 0xC8, 0xFF, 0x08, 0x23, 0x07, 0x22, 0x00, 0x21, 0x06, 0x46, 0x16, 0x20, 0xF6, 0xF7, +0xC1, 0xFF, 0x04, 0x23, 0x07, 0x22, 0x00, 0x21, 0x05, 0x46, 0x14, 0x20, 0xF6, 0xF7, 0xBA, 0xFF, 0x02, 0x23, 0x07, 0x22, +0x05, 0x21, 0x80, 0x46, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0xB2, 0xFF, 0x4F, 0xF4, 0xA4, 0x6A, 0x0A, 0xFB, 0x09, 0xBA, +0x07, 0x46, 0xFF, 0xF7, 0x0B, 0xFF, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0x49, 0xD0, 0x2F, 0x4A, 0x13, 0x68, 0x23, 0xF0, +0x04, 0x03, 0x13, 0x60, 0xDA, 0xF8, 0x04, 0x30, 0x43, 0xF0, 0x20, 0x03, 0xCA, 0xF8, 0x04, 0x30, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x09, 0xB9, 0xA6, 0xF1, 0x0C, 0x01, 0xD9, 0xF8, 0x5C, 0x00, 0xB9, 0xF8, 0x60, 0x30, 0xB3, 0x80, 0x30, 0x60, +0x94, 0xF8, 0x33, 0x30, 0xB3, 0x71, 0x23, 0x48, 0xF7, 0xF7, 0x18, 0xFC, 0x23, 0x7C, 0x6B, 0x71, 0x01, 0x21, 0x20, 0x46, +0xFB, 0xF7, 0x80, 0xFE, 0x28, 0x60, 0x94, 0xF8, 0x33, 0x30, 0x2B, 0x71, 0xA5, 0xF1, 0x0C, 0x01, 0x1B, 0x48, 0xF7, 0xF7, +0x09, 0xFC, 0x23, 0x8D, 0xA8, 0xF8, 0x00, 0x30, 0x94, 0xF8, 0x33, 0x30, 0x88, 0xF8, 0x02, 0x30, 0xA8, 0xF1, 0x0C, 0x01, +0x01, 0x25, 0x15, 0x48, 0xF7, 0xF7, 0xFC, 0xFB, 0x3D, 0x70, 0x94, 0xF8, 0x33, 0x30, 0x12, 0x48, 0x7B, 0x70, 0xA7, 0xF1, +0x0C, 0x01, 0xF7, 0xF7, 0xF3, 0xFB, 0xFF, 0xF7, 0x6B, 0xFF, 0x29, 0x46, 0x07, 0x20, 0xBD, 0xE8, 0xF8, 0x4F, 0xF7, 0xF7, +0x57, 0xB9, 0x02, 0x23, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x56, 0xFF, 0x01, 0x23, 0x03, 0x70, +0x9A, 0xF8, 0x63, 0x30, 0x43, 0x70, 0x03, 0x4B, 0x01, 0x46, 0x0C, 0x39, 0x18, 0x1D, 0xF7, 0xF7, 0xD9, 0xFB, 0xAD, 0xE7, +0x94, 0xBA, 0x17, 0x00, 0x4C, 0x00, 0x32, 0x40, 0x98, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x38, 0xB5, 0x0E, 0x4C, +0x0C, 0x23, 0x07, 0x22, 0x00, 0x21, 0x3F, 0x20, 0x24, 0x68, 0xF6, 0xF7, 0x39, 0xFF, 0xA1, 0x8C, 0xE2, 0x8C, 0x25, 0x6A, +0x05, 0x60, 0x81, 0x80, 0xC2, 0x80, 0x94, 0xF8, 0x32, 0x20, 0x02, 0x72, 0x94, 0xF8, 0x33, 0x20, 0x42, 0x72, 0xF6, 0xF7, +0x5B, 0xFF, 0xBD, 0xE8, 0x38, 0x40, 0x02, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0x1F, 0xB9, 0x00, 0xBF, 0x94, 0xBA, 0x17, 0x00, +0xF8, 0xB5, 0x07, 0x22, 0x04, 0x46, 0x02, 0x23, 0x05, 0x21, 0x41, 0xF2, 0x19, 0x40, 0xF6, 0xF7, 0x19, 0xFF, 0x02, 0x23, +0x06, 0x46, 0x07, 0x22, 0x05, 0x21, 0x41, 0xF2, 0x17, 0x40, 0xF6, 0xF7, 0x11, 0xFF, 0x00, 0x27, 0x05, 0x46, 0xFF, 0xF7, +0x6D, 0xFE, 0x37, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x73, 0x70, 0x1D, 0x48, 0xA6, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x92, 0xFB, +0x94, 0xF8, 0x64, 0x30, 0x0B, 0xBB, 0x23, 0x6C, 0x6B, 0xB1, 0x01, 0x23, 0x00, 0x21, 0x07, 0x22, 0x39, 0x20, 0xF6, 0xF7, +0xF9, 0xFE, 0x01, 0x46, 0x94, 0xF8, 0x63, 0x30, 0x01, 0xF8, 0x0C, 0x39, 0x12, 0x48, 0xF7, 0xF7, 0x7F, 0xFB, 0x00, 0x23, +0x2B, 0x70, 0x94, 0xF8, 0x63, 0x30, 0x0F, 0x48, 0x6B, 0x70, 0xA5, 0xF1, 0x0C, 0x01, 0xF7, 0xF7, 0x75, 0xFB, 0xFF, 0xF7, +0xED, 0xFE, 0xBD, 0xE8, 0xF8, 0x40, 0x03, 0x21, 0x07, 0x20, 0xF7, 0xF7, 0xD9, 0xB8, 0x39, 0x46, 0x04, 0x23, 0x07, 0x22, +0x1E, 0x20, 0xF6, 0xF7, 0xD9, 0xFE, 0x87, 0x70, 0x94, 0xF8, 0x63, 0x30, 0xC3, 0x70, 0xA0, 0xF1, 0x0C, 0x01, 0x02, 0x48, +0xF7, 0xF7, 0x5E, 0xFB, 0xCD, 0xE7, 0x00, 0xBF, 0x98, 0xBA, 0x17, 0x00, 0x15, 0x4A, 0x03, 0x7F, 0x4F, 0xF4, 0xA4, 0x61, +0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x13, 0xD1, 0x43, 0x7F, 0x0D, 0x2B, 0x10, 0xD8, 0x82, 0x88, +0x2A, 0xB9, 0x82, 0x6C, 0xB2, 0xF8, 0x68, 0x20, 0xB2, 0xF5, 0x12, 0x7F, 0x08, 0xD0, 0x0C, 0x4A, 0x4F, 0xF4, 0x1E, 0x71, +0x01, 0xFB, 0x03, 0x22, 0x92, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x02, 0xD0, 0x01, 0x23, 0x18, 0x46, 0x70, 0x47, 0x92, 0xF8, +0x32, 0x20, 0x12, 0xF0, 0x03, 0x02, 0xF8, 0xD1, 0xC1, 0x8B, 0x41, 0xF4, 0x80, 0x51, 0x13, 0x46, 0xC1, 0x83, 0xF2, 0xE7, +0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xC3, 0x8B, 0xDB, 0x04, 0x00, 0xD4, 0x70, 0x47, 0x10, 0xB5, 0x0C, 0x46, +0xC2, 0x7E, 0x15, 0x49, 0x94, 0xF8, 0x2E, 0x31, 0x8A, 0x5C, 0x13, 0x42, 0x1A, 0xD0, 0x94, 0xF8, 0x31, 0x20, 0x11, 0x07, +0x1A, 0xD4, 0x42, 0xF0, 0x08, 0x02, 0x0F, 0x2B, 0x84, 0xF8, 0x31, 0x20, 0x14, 0xD1, 0x05, 0x22, 0x04, 0x23, 0x00, 0x21, +0x41, 0x20, 0xF6, 0xF7, 0x7F, 0xFE, 0x22, 0x8C, 0x02, 0x80, 0x94, 0xF8, 0x22, 0x20, 0xC2, 0x70, 0x01, 0x22, 0x82, 0x70, +0xBD, 0xE8, 0x10, 0x40, 0xF6, 0xF7, 0xA4, 0xBE, 0x94, 0xF8, 0x31, 0x30, 0x9A, 0x07, 0x00, 0xD5, 0x10, 0xBD, 0x43, 0xF0, +0x02, 0x03, 0x84, 0xF8, 0x31, 0x30, 0xE4, 0xE7, 0xA4, 0xB2, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x90, 0xF8, 0x62, 0x70, +0x02, 0x2F, 0x91, 0x46, 0x5A, 0xD1, 0x91, 0xF8, 0x32, 0x20, 0x0E, 0x46, 0x00, 0x2A, 0x55, 0xD0, 0x12, 0xF0, 0x01, 0x08, +0x91, 0xF8, 0x31, 0x30, 0x04, 0xBF, 0x08, 0x27, 0x4F, 0xF0, 0x04, 0x08, 0x1F, 0x42, 0x78, 0xD0, 0xD1, 0xF8, 0xFC, 0x41, +0x00, 0x2C, 0x68, 0xD0, 0xA2, 0xF1, 0x02, 0x02, 0xB2, 0xFA, 0x82, 0xF2, 0x91, 0xF8, 0x2E, 0x11, 0x3C, 0x4D, 0x52, 0x09, +0x4F, 0xF0, 0x00, 0x0A, 0x04, 0xE0, 0x23, 0x68, 0xA2, 0x46, 0x00, 0x2B, 0x59, 0xD0, 0x1C, 0x46, 0xE3, 0x7E, 0xEB, 0x5C, +0x19, 0x42, 0x0C, 0xBF, 0x01, 0x23, 0x00, 0x23, 0x93, 0x42, 0xF2, 0xD0, 0x51, 0x46, 0x22, 0x46, 0x06, 0xF5, 0xFE, 0x70, +0xF7, 0xF7, 0xC8, 0xFB, 0x96, 0xF8, 0x32, 0x10, 0x11, 0xF0, 0x08, 0x0F, 0x0C, 0xBF, 0x03, 0x23, 0x04, 0x23, 0xE3, 0x76, +0xBA, 0xF1, 0x00, 0x0F, 0x52, 0xD0, 0xDA, 0xF8, 0x00, 0x30, 0x0B, 0xB3, 0xA1, 0xF1, 0x02, 0x01, 0xB1, 0xFA, 0x81, 0xF1, +0x96, 0xF8, 0x2E, 0x01, 0x49, 0x09, 0x01, 0xE0, 0x1B, 0x68, 0xBB, 0xB1, 0xDA, 0x7E, 0xAA, 0x5C, 0x10, 0x42, 0x0C, 0xBF, +0x01, 0x22, 0x00, 0x22, 0x8A, 0x42, 0xF5, 0xD0, 0xA2, 0x6C, 0xB2, 0xF8, 0x68, 0x30, 0x43, 0xF4, 0x00, 0x53, 0xA2, 0xF8, +0x68, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x00, 0x24, 0xC9, 0xF8, 0x00, 0x40, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, +0x96, 0xF8, 0x31, 0x10, 0x21, 0xEA, 0x07, 0x07, 0x17, 0xEA, 0x08, 0x01, 0x86, 0xF8, 0x31, 0x70, 0x07, 0xEA, 0x08, 0x05, +0xE4, 0xD1, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, 0xF0, 0xFD, 0x32, 0x8C, 0x02, 0x80, 0x96, 0xF8, 0x22, 0x20, +0xC2, 0x70, 0x85, 0x70, 0xF6, 0xF7, 0x18, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x0C, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x05, 0xDA, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x91, 0x12, 0xF8, 0xF7, 0xD3, 0xFE, 0x01, 0x23, +0x00, 0x24, 0xC9, 0xF8, 0x00, 0x30, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xD6, 0xF8, 0xFC, 0x31, 0xAB, 0xE7, 0x00, 0xBF, +0xA4, 0xB2, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x38, 0xB5, 0x90, 0xF8, +0x62, 0x30, 0x02, 0x2B, 0x14, 0xD1, 0x13, 0x4C, 0x13, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x01, 0x44, 0x21, 0x46, +0xD3, 0xF8, 0x20, 0x33, 0x00, 0x22, 0x98, 0x47, 0x94, 0xF8, 0x31, 0x10, 0x11, 0xF0, 0x0A, 0x0F, 0x04, 0xD0, 0x01, 0xF0, +0xF5, 0x05, 0x84, 0xF8, 0x31, 0x50, 0x05, 0xB1, 0x38, 0xBD, 0x29, 0x46, 0x04, 0x23, 0x05, 0x22, 0x41, 0x20, 0xF6, 0xF7, +0xA5, 0xFD, 0x94, 0xF8, 0x22, 0x20, 0x21, 0x8C, 0xC2, 0x70, 0x85, 0x70, 0xBD, 0xE8, 0x38, 0x40, 0x01, 0x80, 0xF6, 0xF7, +0xCB, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x03, 0x6C, 0x2D, 0xE9, 0xF0, 0x41, 0x04, 0x46, +0x88, 0x46, 0x00, 0x2B, 0x6C, 0xD0, 0x3A, 0x4A, 0x1B, 0x79, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x53, 0xDB, +0x94, 0xF8, 0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE4, 0xF7, 0x4C, 0xF8, +0x05, 0x46, 0x00, 0x28, 0x56, 0xD0, 0x01, 0x46, 0x20, 0x46, 0xF6, 0xF7, 0x43, 0xF9, 0xAE, 0x6C, 0x00, 0x27, 0x6F, 0xF0, +0x3F, 0x03, 0x41, 0x46, 0x86, 0xF8, 0x68, 0x30, 0x86, 0xF8, 0x69, 0x70, 0x86, 0xF8, 0x6A, 0x70, 0x86, 0xF8, 0x6B, 0x70, +0x06, 0xF1, 0x6C, 0x00, 0x06, 0x22, 0x0B, 0xF0, 0xED, 0xF8, 0x26, 0x4A, 0xE0, 0x6D, 0xB2, 0xF8, 0xFC, 0x31, 0xB4, 0xF8, +0x60, 0x10, 0xB4, 0xF8, 0x60, 0xC0, 0xC6, 0xF8, 0x72, 0x00, 0x01, 0x33, 0x9B, 0xB2, 0xE0, 0x6D, 0xA6, 0xF8, 0x76, 0x10, +0x19, 0x01, 0xB0, 0x67, 0xA6, 0xF8, 0x7C, 0xC0, 0xA2, 0xF8, 0xFC, 0x31, 0xA6, 0xF8, 0x7E, 0x10, 0xC5, 0xE9, 0x15, 0x74, +0x94, 0xF8, 0x63, 0x30, 0x2B, 0x77, 0xFF, 0x23, 0x6B, 0x77, 0x06, 0xF1, 0x80, 0x00, 0x07, 0x21, 0xF9, 0xF7, 0xCE, 0xFD, +0xE9, 0x6C, 0x4B, 0x6A, 0x17, 0x33, 0x1A, 0x18, 0x00, 0xF1, 0x1C, 0x03, 0xC1, 0xE9, 0x0A, 0x23, 0x28, 0x46, 0x05, 0x21, +0xBD, 0xE8, 0xF0, 0x41, 0xE4, 0xF7, 0x12, 0xB8, 0x02, 0x2B, 0xA9, 0xD1, 0x0D, 0x49, 0x0E, 0x48, 0x4F, 0xF4, 0x09, 0x72, +0xF8, 0xF7, 0x0E, 0xFE, 0x01, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xE3, 0xF7, 0xF5, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xA8, 0xD1, +0xBD, 0xE8, 0xF0, 0x81, 0x03, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xEF, 0xDA, 0xE8, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xF8, 0xB5, 0x14, 0x4A, +0x14, 0x4D, 0x41, 0xF2, 0x0A, 0x00, 0x41, 0xF2, 0x08, 0x07, 0x00, 0x26, 0x16, 0x52, 0x0C, 0x46, 0xD3, 0x53, 0x41, 0xF2, +0x0C, 0x06, 0xD1, 0xF8, 0x64, 0x11, 0xD4, 0xF8, 0x60, 0x01, 0x90, 0x51, 0x0B, 0x2B, 0x14, 0x60, 0xA9, 0x80, 0x0D, 0xD0, +0x19, 0x46, 0x04, 0x22, 0x02, 0x23, 0x41, 0xF2, 0x09, 0x00, 0xF6, 0xF7, 0xF5, 0xFC, 0x01, 0x22, 0x42, 0x70, 0x94, 0xF8, +0x6E, 0x21, 0x02, 0x70, 0xF6, 0xF7, 0x1E, 0xFD, 0x04, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, +0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xCA, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x1A, 0x46, 0x70, 0xB5, 0x40, 0x23, 0x14, 0x4C, +0x0D, 0x46, 0x41, 0xF2, 0x06, 0x00, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xD7, 0xFC, 0xA3, 0x88, 0x06, 0x46, 0x13, 0xB1, +0x2A, 0x78, 0x93, 0x42, 0x06, 0xD8, 0x00, 0x23, 0x30, 0x46, 0x33, 0x70, 0xF6, 0xF7, 0xFC, 0xFC, 0x00, 0x20, 0x70, 0xBD, +0x04, 0xEB, 0x82, 0x14, 0x08, 0x34, 0x0F, 0xCC, 0x35, 0x46, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, 0x0F, 0xCC, 0x0F, 0xC5, +0x94, 0xE8, 0x0F, 0x00, 0x85, 0xE8, 0x0F, 0x00, 0x30, 0x46, 0xF6, 0xF7, 0xE9, 0xFC, 0x00, 0x20, 0x70, 0xBD, 0x00, 0xBF, +0xA8, 0xBA, 0x17, 0x00, 0x08, 0xB5, 0x04, 0x22, 0x01, 0x23, 0x02, 0x21, 0x40, 0xF6, 0x03, 0x00, 0xF6, 0xF7, 0xAC, 0xFC, +0xF6, 0xF7, 0xDA, 0xFC, 0x04, 0x20, 0xF6, 0xF7, 0x49, 0xFF, 0x03, 0x49, 0x02, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x5A, 0xFB, +0x00, 0x20, 0x08, 0xBD, 0x6C, 0xBE, 0x15, 0x00, 0x08, 0xB5, 0x19, 0x46, 0x04, 0x22, 0x01, 0x23, 0x41, 0xF2, 0x0B, 0x00, +0xF6, 0xF7, 0x96, 0xFC, 0xF6, 0xF7, 0xC4, 0xFC, 0x02, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x48, 0xFB, 0x00, 0x20, 0x08, 0xBD, +0x80, 0xBE, 0x15, 0x00, 0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, +0xF6, 0xF7, 0x82, 0xFC, 0x06, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x35, 0xFB, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, +0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xA6, 0xFC, 0x00, 0x20, 0x38, 0xBD, 0x98, 0xBE, 0x15, 0x00, 0x10, 0xB5, 0x41, 0xF2, +0x08, 0x00, 0x04, 0x4C, 0x04, 0x49, 0x1A, 0x46, 0x23, 0x5A, 0x08, 0x20, 0xF8, 0xF7, 0x20, 0xFB, 0x02, 0x20, 0x10, 0xBD, +0xA8, 0xBA, 0x17, 0x00, 0xB4, 0xBE, 0x15, 0x00, 0xF8, 0xB5, 0x36, 0x4C, 0x91, 0xF8, 0x6E, 0x21, 0x35, 0x4E, 0x21, 0x60, +0x0D, 0x46, 0x41, 0xF2, 0x08, 0x00, 0x4F, 0xF4, 0xA4, 0x67, 0x41, 0xF2, 0x0A, 0x01, 0x07, 0xFB, 0x02, 0x62, 0x01, 0x26, +0x23, 0x52, 0x66, 0x52, 0x00, 0x23, 0xC2, 0xF8, 0xCC, 0x31, 0x05, 0xF5, 0xB0, 0x77, 0x97, 0xE8, 0x03, 0x00, 0xDF, 0xF8, +0xC4, 0xC0, 0x41, 0xF2, 0x0C, 0x02, 0xAC, 0xF8, 0x04, 0x10, 0x41, 0xF2, 0x3B, 0x01, 0xA0, 0x50, 0x63, 0x54, 0x38, 0x46, +0x1A, 0x46, 0x19, 0x46, 0x00, 0xF0, 0x4A, 0xF9, 0x18, 0xB1, 0x90, 0xF8, 0x3D, 0x10, 0x03, 0x46, 0x91, 0xB9, 0x97, 0xE8, +0x03, 0x00, 0x21, 0x4B, 0x41, 0xF2, 0x34, 0x02, 0x99, 0x80, 0x20, 0x4B, 0xA0, 0x50, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x28, 0xDB, 0x1D, 0x4B, 0xD3, 0xF8, 0xF4, 0x32, 0x98, 0x47, 0x01, 0x20, 0xF8, 0xBD, 0x02, 0x46, 0x41, 0xF2, +0x34, 0x0C, 0x52, 0xF8, 0x02, 0x0F, 0x93, 0xF8, 0x3E, 0x70, 0x44, 0xF8, 0x0C, 0x00, 0x14, 0x48, 0x92, 0x88, 0x82, 0x80, +0xBE, 0x40, 0x41, 0xF2, 0x38, 0x00, 0x01, 0x3E, 0x22, 0x5A, 0x36, 0x02, 0x36, 0xB2, 0x22, 0xEA, 0x06, 0x02, 0x12, 0xB2, +0x22, 0x52, 0xDB, 0x88, 0xA3, 0xEB, 0x01, 0x21, 0x0E, 0x40, 0x0C, 0x4B, 0x16, 0x43, 0x26, 0x52, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xD6, 0xDA, 0x95, 0xF8, 0x60, 0x31, 0xDB, 0x07, 0xD2, 0xD5, 0x08, 0x49, 0x08, 0x48, 0xA1, 0x22, +0xF8, 0xF7, 0xD8, 0xFC, 0xCC, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xDC, 0xCA, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xBE, 0x15, 0x00, 0xB4, 0xCA, 0x17, 0x00, +0x1A, 0x46, 0x38, 0xB5, 0x41, 0xF2, 0x08, 0x00, 0x0D, 0x46, 0x02, 0x23, 0x11, 0x46, 0x04, 0x22, 0xF6, 0xF7, 0xDA, 0xFB, +0x0A, 0x49, 0x04, 0x46, 0x08, 0x20, 0xF8, 0xF7, 0x8D, 0xFA, 0x29, 0x46, 0x08, 0x48, 0x31, 0xF8, 0x03, 0x2B, 0x20, 0xF8, +0x03, 0x2B, 0x0A, 0xF0, 0x55, 0xFF, 0x01, 0x23, 0x23, 0x70, 0xAB, 0x78, 0x63, 0x70, 0x20, 0x46, 0xF6, 0xF7, 0xF6, 0xFB, +0x00, 0x20, 0x38, 0xBD, 0xF0, 0xBE, 0x15, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x08, 0x78, 0x08, 0xB9, 0x00, 0x20, 0x70, 0x47, +0x08, 0xB5, 0x00, 0xF0, 0x31, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x70, 0xB5, 0x0B, 0x4E, 0x41, 0xF2, 0x08, 0x05, +0x01, 0x23, 0x0C, 0x46, 0x04, 0x22, 0x71, 0x5B, 0x41, 0xF2, 0x0B, 0x00, 0xF6, 0xF7, 0xAA, 0xFB, 0xF6, 0xF7, 0xD8, 0xFB, +0x72, 0x5B, 0x05, 0x49, 0x08, 0x20, 0xF8, 0xF7, 0x5B, 0xFA, 0x20, 0x78, 0x00, 0xF0, 0x18, 0xF8, 0x00, 0x20, 0x70, 0xBD, +0xA8, 0xBA, 0x17, 0x00, 0x00, 0xBF, 0x15, 0x00, 0x08, 0xB5, 0x05, 0x49, 0x41, 0xF2, 0x0B, 0x02, 0x8B, 0x5C, 0x01, 0x33, +0x8B, 0x54, 0x00, 0xF0, 0x65, 0xFD, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x08, 0x46, 0x00, 0xF0, +0x19, 0xB9, 0x00, 0xBF, 0xF0, 0xB5, 0x39, 0x4C, 0x41, 0xF2, 0x0A, 0x05, 0x83, 0xB0, 0x63, 0x5D, 0x06, 0x46, 0x00, 0x2B, +0x43, 0xD0, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x03, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x76, 0xFB, +0x05, 0x46, 0x23, 0x68, 0x30, 0x49, 0x93, 0xF8, 0x6E, 0x21, 0x00, 0x96, 0x41, 0xF2, 0x0A, 0x07, 0x08, 0x20, 0xE3, 0x5D, +0xF8, 0xF7, 0x22, 0xFA, 0xE3, 0x5D, 0x63, 0xB9, 0x2B, 0x49, 0x2C, 0x4A, 0x0B, 0x68, 0x2C, 0x48, 0x23, 0xF0, 0x04, 0x03, +0x0B, 0x60, 0x13, 0x68, 0x01, 0x88, 0x1B, 0x0C, 0x1B, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x20, 0x68, 0x27, 0x4B, 0x90, 0xF8, +0x6E, 0x21, 0x2A, 0x70, 0x6E, 0x70, 0xA2, 0x88, 0xAA, 0x70, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x20, 0xD0, 0x0C, 0x38, +0xF6, 0xF7, 0xC8, 0xFB, 0x00, 0x26, 0x28, 0x46, 0x26, 0x60, 0xF6, 0xF7, 0x77, 0xFB, 0x1F, 0x4A, 0x53, 0x68, 0x31, 0x46, +0x23, 0xF0, 0x20, 0x03, 0x04, 0x20, 0x53, 0x60, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xF6, 0xF7, 0x35, 0xBD, 0xA3, 0x88, +0xF3, 0xB1, 0x41, 0xF2, 0x08, 0x02, 0x03, 0x23, 0xA1, 0x5A, 0x41, 0xF2, 0x01, 0x00, 0x04, 0x22, 0xF6, 0xF7, 0x30, 0xFB, +0x05, 0x46, 0xB8, 0xE7, 0x13, 0x4B, 0x93, 0xF8, 0xB5, 0x30, 0x00, 0x2B, 0xD9, 0xD0, 0x12, 0x49, 0x12, 0x4B, 0x0A, 0x68, +0x22, 0xF0, 0x7C, 0x72, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF4, 0x00, 0x12, +0x1A, 0x60, 0xCA, 0xE7, 0xD6, 0xF7, 0xCC, 0xFB, 0x63, 0x5D, 0x00, 0x2B, 0xDB, 0xD0, 0x94, 0xE7, 0xA8, 0xBA, 0x17, 0x00, +0x30, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, 0x28, 0x25, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, +0x1C, 0x9E, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x74, 0x00, 0x32, 0x40, 0x6C, 0x00, 0x32, 0x40, 0x08, 0xB5, 0x00, 0x21, +0x04, 0x20, 0xF6, 0xF7, 0xF5, 0xFC, 0xBD, 0xE8, 0x08, 0x40, 0x03, 0x48, 0x4F, 0xF4, 0x86, 0x52, 0x00, 0x21, 0xD3, 0xF7, +0xED, 0xBE, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x3C, 0x4D, 0x83, 0xB0, 0xA8, 0x46, 0x2B, 0x46, +0x00, 0x22, 0x08, 0xE0, 0x5F, 0x89, 0x04, 0x88, 0xA7, 0x42, 0x14, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, +0x1C, 0xD0, 0x1C, 0x7A, 0x03, 0xF1, 0x08, 0x06, 0x00, 0x2C, 0xF1, 0xD1, 0x00, 0x29, 0xF3, 0xD0, 0x08, 0xEB, 0x82, 0x12, +0x80, 0x23, 0x82, 0xF8, 0x44, 0x30, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9F, 0x89, 0x44, 0x88, 0xA7, 0x42, +0xE6, 0xD1, 0xDF, 0x89, 0x84, 0x88, 0xA7, 0x42, 0xF3, 0xD0, 0x01, 0x32, 0x40, 0x2A, 0x03, 0xF1, 0x40, 0x03, 0xE2, 0xD1, +0x00, 0x29, 0x46, 0xD0, 0x26, 0x4F, 0x4F, 0xF0, 0x00, 0x0B, 0x4F, 0xF0, 0x21, 0x0A, 0x06, 0xE0, 0x0B, 0xF1, 0x01, 0x0B, +0xBB, 0xF1, 0x40, 0x0F, 0x05, 0xF1, 0x40, 0x05, 0x39, 0xD0, 0x2B, 0x7A, 0x05, 0xF1, 0x08, 0x06, 0x00, 0x2B, 0xF3, 0xD0, +0x95, 0xF8, 0x45, 0x40, 0x00, 0x2C, 0xEF, 0xD1, 0x38, 0x68, 0x30, 0xB3, 0x90, 0xF8, 0x70, 0x31, 0x1B, 0xB3, 0x05, 0xF1, +0x11, 0x01, 0x4F, 0xF0, 0xFD, 0x09, 0x06, 0xE0, 0x38, 0x68, 0x01, 0x34, 0x90, 0xF8, 0x70, 0x31, 0xE4, 0xB2, 0xA3, 0x42, +0x15, 0xD9, 0x04, 0xEB, 0x44, 0x13, 0x03, 0x44, 0x93, 0xF8, 0xFC, 0x30, 0x00, 0x2B, 0xF1, 0xD0, 0x2A, 0x7C, 0x9A, 0x42, +0xEE, 0xD1, 0x1A, 0xFB, 0x04, 0x93, 0x18, 0x44, 0x01, 0x91, 0x0A, 0xF0, 0xE1, 0xFD, 0x01, 0x99, 0x00, 0x28, 0xE5, 0xD1, +0x3B, 0x68, 0x93, 0xF8, 0x70, 0x31, 0x9C, 0x42, 0xC6, 0xD1, 0x08, 0xEB, 0x8B, 0x11, 0x80, 0x20, 0x00, 0x23, 0x81, 0xF8, +0x44, 0x00, 0x0B, 0x72, 0xA5, 0xE7, 0x00, 0x26, 0x30, 0x46, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA8, 0xBA, 0x17, 0x00, +0xF4, 0x9F, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x2D, 0xED, 0x02, 0x8B, 0x61, 0x4B, 0x99, 0xB0, 0x1C, 0x68, 0x03, 0x46, +0x04, 0x93, 0x04, 0x20, 0x94, 0xF8, 0x6E, 0x31, 0x07, 0x93, 0xF6, 0xF7, 0x03, 0xFD, 0x01, 0x28, 0x05, 0xD0, 0x00, 0x20, +0x19, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0x58, 0x49, 0x41, 0xF2, 0x0C, 0x03, 0xCA, 0x5C, 0xD2, 0x07, +0x19, 0xD4, 0xCA, 0x5A, 0x04, 0x9B, 0x9B, 0x8B, 0x9A, 0x42, 0x00, 0xF0, 0x85, 0x80, 0x52, 0x49, 0x41, 0xF2, 0x34, 0x02, +0x8A, 0x5A, 0x9A, 0x42, 0xE7, 0xD1, 0x04, 0x9A, 0x41, 0xF2, 0x36, 0x03, 0xD2, 0x8B, 0xCB, 0x5A, 0x9A, 0x42, 0xE0, 0xD1, +0x04, 0x9A, 0x41, 0xF2, 0x38, 0x03, 0x12, 0x8C, 0xCB, 0x5A, 0x9A, 0x42, 0xD9, 0xD1, 0x04, 0x98, 0x30, 0xF8, 0x30, 0x3B, +0x0B, 0x90, 0x24, 0x3B, 0x9B, 0xB2, 0x0D, 0xF1, 0x37, 0x02, 0x19, 0x46, 0x08, 0xEE, 0x10, 0x3A, 0xF7, 0xF7, 0xE4, 0xF8, +0x00, 0x28, 0x73, 0xD0, 0x9D, 0xF8, 0x37, 0x60, 0x10, 0xAD, 0x4E, 0xB1, 0xAF, 0x19, 0x2B, 0x46, 0xC5, 0xF1, 0x02, 0x01, +0xC2, 0x18, 0x52, 0x5C, 0x03, 0xF8, 0x01, 0x2B, 0xBB, 0x42, 0xF9, 0xD1, 0x04, 0x9F, 0x38, 0x46, 0x01, 0x21, 0x2B, 0x46, +0x32, 0x46, 0x1C, 0x30, 0xFF, 0xF7, 0x24, 0xFF, 0x01, 0x46, 0x0A, 0x90, 0x00, 0x28, 0xB0, 0xD0, 0xBB, 0x8B, 0x43, 0x80, +0xFB, 0x8B, 0x83, 0x80, 0x3B, 0x8C, 0xC3, 0x80, 0x97, 0xF8, 0x2C, 0x30, 0x97, 0xF8, 0x2D, 0x20, 0x43, 0xEA, 0x02, 0x23, +0x03, 0x86, 0xFB, 0x8D, 0x43, 0x86, 0x03, 0xF0, 0x01, 0x03, 0xC3, 0xF1, 0x02, 0x03, 0x43, 0x85, 0x00, 0x2E, 0x46, 0xD1, +0x0A, 0x9B, 0x1E, 0x72, 0x27, 0x4A, 0x41, 0xF2, 0x3A, 0x03, 0xD3, 0x5C, 0x00, 0x2B, 0x40, 0xF0, 0xA5, 0x82, 0x24, 0x4A, +0x41, 0xF2, 0x0A, 0x03, 0xD5, 0x5C, 0x00, 0x2D, 0x48, 0xD1, 0x94, 0xF8, 0x70, 0x11, 0x00, 0x29, 0x44, 0xD0, 0x0A, 0x9B, +0x26, 0x46, 0x03, 0xF1, 0x09, 0x07, 0x98, 0x46, 0x08, 0x46, 0x05, 0xE0, 0x01, 0x35, 0xA8, 0x42, 0x06, 0xF1, 0x21, 0x06, +0x03, 0x46, 0x34, 0xDD, 0x96, 0xF8, 0xFC, 0x30, 0x83, 0xB3, 0x98, 0xF8, 0x08, 0x20, 0x9A, 0x42, 0xF2, 0xD1, 0x39, 0x46, +0x06, 0xF1, 0xFD, 0x00, 0x0A, 0xF0, 0x26, 0xFD, 0x00, 0x28, 0x00, 0xF0, 0x2C, 0x83, 0x94, 0xF8, 0x70, 0x01, 0xE7, 0xE7, +0x04, 0x99, 0x0F, 0x48, 0xC9, 0x8B, 0x41, 0xF2, 0x0E, 0x02, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x72, 0xAF, 0x04, 0x99, +0x41, 0xF2, 0x10, 0x02, 0x09, 0x8C, 0x82, 0x5A, 0x91, 0x42, 0x7F, 0xF4, 0x6A, 0xAF, 0x7C, 0xE7, 0x06, 0x46, 0x10, 0xAD, +0x96, 0xE7, 0x0B, 0x46, 0x03, 0xF8, 0x08, 0x6F, 0x2E, 0x44, 0x15, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xAE, 0x42, +0xF9, 0xD1, 0xAF, 0xE7, 0xA8, 0xBA, 0x17, 0x00, 0x03, 0x46, 0x9D, 0x42, 0x3F, 0xF4, 0x43, 0xAF, 0x18, 0xEE, 0x10, 0x1A, +0x0B, 0x98, 0xF7, 0xF7, 0x45, 0xF9, 0x00, 0x28, 0x00, 0xF0, 0x3A, 0x82, 0x04, 0x9B, 0x9A, 0x79, 0x83, 0x78, 0x00, 0x2A, +0x40, 0xF0, 0x56, 0x82, 0x59, 0x1E, 0x0D, 0x29, 0x00, 0xF2, 0x4F, 0x82, 0x0E, 0x2B, 0x00, 0xF0, 0xEB, 0x82, 0x03, 0xEB, +0x83, 0x03, 0x03, 0xF6, 0x67, 0x11, 0x10, 0x46, 0xFA, 0xF7, 0x98, 0xFE, 0x0A, 0x99, 0x04, 0x9B, 0xC8, 0x62, 0x91, 0xF9, +0x3C, 0x20, 0x93, 0xF9, 0x09, 0x30, 0x9A, 0x42, 0xB8, 0xBF, 0x81, 0xF8, 0x3C, 0x30, 0x04, 0x99, 0x03, 0x88, 0x8A, 0x88, +0x9A, 0x42, 0x00, 0xD0, 0x8B, 0x80, 0x41, 0xF2, 0xBD, 0x03, 0xB4, 0x4A, 0x00, 0x25, 0xD5, 0x54, 0x18, 0xEE, 0x10, 0x3A, +0x00, 0x2B, 0x6C, 0xD0, 0x0B, 0x9B, 0x8D, 0xED, 0x05, 0x8A, 0x2C, 0x46, 0xA8, 0x46, 0x06, 0x93, 0xDD, 0xE9, 0x05, 0x10, +0xF7, 0xF7, 0xFC, 0xF9, 0x08, 0x90, 0x00, 0x28, 0x5F, 0xD0, 0x43, 0x78, 0xAA, 0x4A, 0x81, 0x78, 0x11, 0x70, 0x5E, 0x1E, +0x02, 0x33, 0xB6, 0xB2, 0x09, 0x93, 0x00, 0xF1, 0x03, 0x0A, 0x00, 0x2E, 0x44, 0xD0, 0x31, 0x46, 0x50, 0x46, 0xF7, 0xF7, +0x09, 0xFA, 0x07, 0x46, 0x00, 0x28, 0x3D, 0xD0, 0x90, 0xF8, 0x01, 0x90, 0x00, 0xF1, 0x02, 0x0B, 0x09, 0xF1, 0x02, 0x03, +0xF6, 0x1A, 0x58, 0x46, 0x04, 0x21, 0xB6, 0xB2, 0x9A, 0x44, 0xF7, 0xF7, 0x1D, 0xFA, 0x00, 0x28, 0x00, 0xF0, 0x81, 0x81, +0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0x36, 0xFA, 0x07, 0xF1, 0x04, 0x08, 0x04, 0x46, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, +0xF6, 0xF7, 0xE8, 0xFF, 0x05, 0x46, 0x00, 0x2C, 0xD7, 0xD0, 0x00, 0x2D, 0xD5, 0xD0, 0x92, 0x4B, 0x98, 0xF8, 0x00, 0xC0, +0x1A, 0x78, 0xA7, 0x78, 0xA3, 0xF1, 0x81, 0x00, 0x81, 0x1D, 0x98, 0xF8, 0x01, 0x30, 0x01, 0xF8, 0x32, 0x70, 0x4C, 0xEA, +0x03, 0x21, 0x53, 0x1C, 0xDB, 0xB2, 0x07, 0x1D, 0x10, 0x2B, 0x40, 0xF8, 0x32, 0x50, 0x80, 0xF8, 0x81, 0x30, 0x27, 0xF8, +0x32, 0x10, 0x12, 0xD0, 0x4F, 0xF0, 0x00, 0x08, 0x00, 0x2E, 0xBA, 0xD1, 0x06, 0x9B, 0x08, 0x9A, 0x05, 0x99, 0x9B, 0x1A, +0x19, 0x44, 0x09, 0x9B, 0xA1, 0xEB, 0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xF1, 0xD3, 0x18, 0x05, 0x91, 0x06, 0x93, 0x00, 0x29, +0x98, 0xD1, 0x0A, 0x99, 0x00, 0x23, 0x4B, 0x63, 0x8B, 0x63, 0x41, 0xF2, 0x0A, 0x02, 0x77, 0x4B, 0x9B, 0x5C, 0x00, 0x2B, +0x00, 0xF0, 0xB4, 0x80, 0x0A, 0x9A, 0x07, 0x9F, 0x76, 0x4C, 0x56, 0x8D, 0x51, 0x8E, 0x13, 0x46, 0x4F, 0xF4, 0xA4, 0x65, +0x53, 0xF8, 0x02, 0x0F, 0x12, 0x8E, 0x9B, 0x88, 0x05, 0xFB, 0x07, 0xF5, 0x67, 0x19, 0xA7, 0xF8, 0x68, 0x31, 0xA7, 0xF8, +0x98, 0x21, 0xFF, 0x23, 0x0A, 0x9A, 0xA7, 0xF8, 0x8E, 0x61, 0xC7, 0xF8, 0x64, 0x01, 0xA7, 0xF8, 0x9A, 0x11, 0x87, 0xF8, +0x61, 0x31, 0x87, 0xF8, 0xBE, 0x31, 0x13, 0x7A, 0x05, 0xF1, 0xEC, 0x06, 0x26, 0x44, 0x00, 0x2B, 0x40, 0xF0, 0xA2, 0x81, +0x0A, 0x9A, 0xD2, 0x6A, 0xC7, 0xF8, 0x90, 0x21, 0xA7, 0xF8, 0xC2, 0x31, 0x07, 0x9B, 0x0A, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, +0xA4, 0x67, 0x07, 0xFB, 0x03, 0x47, 0x92, 0xF8, 0x3D, 0x30, 0x87, 0xF8, 0x8B, 0x31, 0x92, 0xF8, 0x3E, 0x30, 0x87, 0xF8, +0x8C, 0x31, 0x05, 0xF5, 0xCE, 0x78, 0x00, 0x23, 0xA0, 0x44, 0xC7, 0xF8, 0xCC, 0x31, 0x18, 0xEE, 0x10, 0x1A, 0x42, 0x46, +0xF9, 0xF7, 0xA4, 0xFB, 0x0A, 0x9B, 0xDB, 0x6A, 0x9B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0xB3, 0x81, 0x05, 0xF5, 0xD6, 0x72, +0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0x0E, 0xAB, 0xF9, 0xF7, 0x6D, 0xFD, 0x80, 0xB1, 0x07, 0x9A, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, 0xB3, 0xF8, 0x9A, 0x11, 0xD3, 0xF8, 0xCC, 0x21, 0x41, 0xF4, 0x00, 0x71, 0x42, 0xF0, +0x01, 0x02, 0xA3, 0xF8, 0x9A, 0x11, 0xC3, 0xF8, 0xCC, 0x21, 0x45, 0x4F, 0x97, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x09, 0xD5, +0x07, 0x9B, 0x4F, 0xF4, 0xA4, 0x69, 0x09, 0xFB, 0x03, 0x49, 0xD9, 0xF8, 0xCC, 0x31, 0xD8, 0x07, 0x00, 0xF1, 0x98, 0x81, +0x00, 0x21, 0x88, 0x46, 0x40, 0x46, 0x32, 0x46, 0xFB, 0xF7, 0x52, 0xFA, 0x0B, 0x9D, 0x18, 0xEE, 0x10, 0x1A, 0x28, 0x46, +0x32, 0x46, 0xF9, 0xF7, 0xAD, 0xFB, 0x28, 0x46, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0xB1, 0xFB, 0x28, 0x46, +0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, 0xF9, 0xF7, 0x13, 0xFC, 0x07, 0x9A, 0x31, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, +0x02, 0x44, 0x29, 0x6D, 0xD4, 0xF8, 0xCC, 0x31, 0x43, 0xF0, 0x00, 0x43, 0x41, 0xF2, 0x3B, 0x02, 0xC4, 0xF8, 0xCC, 0x31, +0x25, 0x4B, 0x01, 0x20, 0x98, 0x54, 0x2A, 0x6A, 0x00, 0x29, 0x00, 0xF0, 0x1C, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x19, 0x81, +0x0B, 0x7E, 0x03, 0x2B, 0x08, 0xD1, 0x25, 0x4B, 0x05, 0xF1, 0x40, 0x00, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0xD5, 0xE9, +0x11, 0x30, 0x98, 0x47, 0x0A, 0x9A, 0x14, 0x78, 0xDC, 0xB9, 0x19, 0x48, 0x1F, 0x4B, 0x81, 0x88, 0x1B, 0x68, 0x01, 0x31, +0x89, 0xB2, 0x81, 0x80, 0x1B, 0x88, 0x5B, 0x07, 0x11, 0xD5, 0x13, 0x7A, 0x00, 0x2B, 0x40, 0xF0, 0x7A, 0x81, 0x1A, 0x4D, +0x0A, 0x9A, 0x04, 0x9C, 0xD2, 0x6A, 0x94, 0xF9, 0x09, 0x00, 0x12, 0x88, 0x00, 0x90, 0xCD, 0xE9, 0x01, 0x35, 0x16, 0x48, +0x23, 0x7B, 0xF7, 0xF7, 0x89, 0xFE, 0x0A, 0x99, 0x00, 0x25, 0x01, 0x22, 0x0A, 0x70, 0x81, 0xF8, 0x3D, 0x50, 0x81, 0xF8, +0x3E, 0x50, 0x41, 0xF2, 0xBD, 0x03, 0x08, 0x46, 0x05, 0x49, 0xCB, 0x5C, 0x00, 0x2B, 0x4D, 0xD0, 0x0D, 0x4C, 0x83, 0x46, +0x04, 0xF1, 0x80, 0x0A, 0x04, 0xF1, 0x81, 0x09, 0x43, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x64, 0xCB, 0x17, 0x00, +0x65, 0xCB, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x30, 0x9D, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x84, 0xBF, 0x15, 0x00, 0xE4, 0xCA, 0x17, 0x00, 0x9A, 0xF8, 0x00, 0x70, +0x08, 0x2F, 0x2B, 0xD8, 0x5A, 0x46, 0x21, 0x68, 0x52, 0xF8, 0x02, 0x0F, 0x4E, 0x78, 0x0E, 0x90, 0x92, 0x88, 0xAD, 0xF8, +0x3C, 0x20, 0xBB, 0xF8, 0x06, 0x20, 0xBD, 0xF9, 0x3C, 0x10, 0x4F, 0xF0, 0x01, 0x08, 0x02, 0xEB, 0x03, 0x22, 0x08, 0xFA, +0x07, 0xF3, 0x4A, 0x40, 0x01, 0x3B, 0x02, 0xEA, 0x03, 0x22, 0x00, 0x23, 0x81, 0xEA, 0x02, 0x0C, 0x0E, 0xA8, 0x1A, 0x46, +0x19, 0x46, 0xAD, 0xF8, 0x3C, 0xC0, 0xFF, 0xF7, 0xDF, 0xFC, 0x68, 0xB3, 0x99, 0xF8, 0x00, 0x30, 0x01, 0x35, 0x9D, 0x42, +0x04, 0xF1, 0x08, 0x04, 0x02, 0xDA, 0xA3, 0x79, 0x00, 0x2B, 0xCF, 0xD1, 0x04, 0x98, 0x04, 0x23, 0x0C, 0x22, 0x41, 0xF2, +0x04, 0x01, 0xF6, 0xF7, 0x2D, 0xF8, 0x01, 0x20, 0x5C, 0xE5, 0xB8, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x62, 0xAE, 0x4C, 0xB1, +0x00, 0x2D, 0x7F, 0xF4, 0x88, 0xAE, 0x49, 0x46, 0x58, 0x46, 0x0E, 0xAA, 0xF6, 0xF7, 0x66, 0xFE, 0x05, 0x46, 0x7E, 0xE6, +0x49, 0x46, 0x58, 0x46, 0xF7, 0xF7, 0xA6, 0xF8, 0x04, 0x46, 0x00, 0x2D, 0x3F, 0xF4, 0x6F, 0xAE, 0x00, 0x28, 0x3F, 0xF4, +0x4C, 0xAE, 0x74, 0xE6, 0x23, 0x68, 0x41, 0x46, 0x02, 0x33, 0x32, 0x46, 0x0E, 0xA8, 0xFF, 0xF7, 0xA9, 0xFC, 0x86, 0x46, +0x00, 0x28, 0xD1, 0xD0, 0xD8, 0x46, 0xB8, 0xE8, 0x0F, 0x00, 0xF4, 0x46, 0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, +0xAC, 0xE8, 0x0F, 0x00, 0xB8, 0xE8, 0x0F, 0x00, 0xAC, 0xE8, 0x0F, 0x00, 0x98, 0xE8, 0x0F, 0x00, 0x8C, 0xE8, 0x0F, 0x00, +0x0E, 0x98, 0xCE, 0xF8, 0x02, 0x00, 0xBD, 0xF8, 0x3C, 0x30, 0x8E, 0xF8, 0x08, 0x60, 0x21, 0x68, 0xAE, 0xF8, 0x06, 0x30, +0x5E, 0xB1, 0x08, 0x36, 0x06, 0x39, 0x76, 0x44, 0xA1, 0xEB, 0x0E, 0x01, 0x0E, 0xF1, 0x08, 0x03, 0xCA, 0x5C, 0x03, 0xF8, +0x01, 0x2F, 0x9E, 0x42, 0xFA, 0xD1, 0x7E, 0x49, 0x8E, 0xF8, 0x3E, 0x70, 0x8B, 0x88, 0xA2, 0x79, 0x8E, 0xF8, 0x3D, 0x20, +0x01, 0x33, 0x01, 0x22, 0x8B, 0x80, 0x8E, 0xF8, 0x00, 0x20, 0x91, 0xE7, 0x04, 0x9B, 0x93, 0xF9, 0x09, 0x20, 0x0A, 0x9B, +0x93, 0xF9, 0x3C, 0x30, 0x9A, 0x42, 0x7F, 0xF7, 0xE2, 0xAD, 0x04, 0x9C, 0xA1, 0x88, 0xA0, 0x79, 0xFA, 0xF7, 0x64, 0xFC, +0x0A, 0x9A, 0xD0, 0x62, 0x63, 0x7A, 0x82, 0xF8, 0x3C, 0x30, 0xD6, 0xE5, 0x0A, 0x9B, 0x6E, 0x49, 0x07, 0x22, 0x03, 0xF1, +0x09, 0x00, 0x0A, 0xF0, 0x9D, 0xFA, 0x00, 0x28, 0x7F, 0xF4, 0xE3, 0xAC, 0x9E, 0xE5, 0x4F, 0xF6, 0xFF, 0x71, 0xB4, 0xE5, +0x01, 0x2A, 0xFA, 0xD1, 0x59, 0x1E, 0xA4, 0x29, 0xF7, 0xD8, 0x03, 0xEB, 0x83, 0x03, 0x03, 0xF5, 0x9C, 0x51, 0x08, 0x31, +0xA9, 0xE5, 0xB2, 0xFA, 0x82, 0xF2, 0x62, 0x48, 0x52, 0x09, 0xF7, 0xF7, 0x95, 0xFD, 0xEB, 0xE6, 0x02, 0xF1, 0x09, 0x00, +0x0A, 0xF0, 0xAC, 0xFC, 0xA8, 0xB1, 0x0A, 0x9B, 0x07, 0xF5, 0xB5, 0x77, 0x03, 0xF1, 0x08, 0x08, 0x03, 0xF1, 0x28, 0x0E, +0xC4, 0x46, 0xBC, 0xE8, 0x0F, 0x00, 0xF4, 0x45, 0x38, 0x60, 0x79, 0x60, 0xBA, 0x60, 0xFB, 0x60, 0xE0, 0x46, 0x07, 0xF1, +0x10, 0x07, 0xF3, 0xD1, 0x9C, 0xF8, 0x00, 0x30, 0x3B, 0x70, 0x0A, 0x9B, 0x07, 0x98, 0x19, 0x7A, 0x0A, 0x9B, 0xDA, 0x6A, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0x43, 0x00, 0x27, 0xC3, 0xF8, 0x90, 0x21, 0xA3, 0xF8, 0xC2, 0x71, 0x00, 0x29, +0x3F, 0xF4, 0x38, 0xAE, 0x0B, 0x44, 0x05, 0xF2, 0x6B, 0x11, 0x12, 0x88, 0x48, 0x48, 0x83, 0xF8, 0x6B, 0x71, 0x21, 0x44, +0xF7, 0xF7, 0x5E, 0xFD, 0x2C, 0xE6, 0x40, 0x46, 0x01, 0x21, 0xFA, 0xF7, 0xED, 0xFD, 0x10, 0xF0, 0x0F, 0x00, 0x1A, 0xBF, +0xB0, 0xFA, 0x80, 0xF0, 0xC0, 0xF1, 0x1F, 0x03, 0x01, 0x23, 0x87, 0xF8, 0xC1, 0x31, 0x3D, 0xE6, 0x18, 0xEE, 0x10, 0x1A, +0x0B, 0x98, 0x32, 0x46, 0xF9, 0xF7, 0x0C, 0xFC, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAE, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, +0x43, 0xF0, 0x02, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0xC9, 0xF8, 0xCC, 0x31, 0xF7, 0xF7, 0x24, 0xF8, 0x97, 0xF8, 0x76, 0x31, +0x59, 0x07, 0x80, 0x46, 0x30, 0xD4, 0x9A, 0x07, 0x0A, 0xD4, 0x07, 0x9A, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, +0xD3, 0xF8, 0xCC, 0x11, 0x11, 0xF0, 0x08, 0x01, 0x3F, 0xF4, 0x44, 0xAE, 0x05, 0xF5, 0x86, 0x72, 0x18, 0xEE, 0x10, 0x1A, +0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x08, 0xFC, 0x30, 0xBB, 0x01, 0x46, 0x38, 0xE6, 0x02, 0xF1, 0x09, 0x05, 0x28, 0x46, +0x16, 0x46, 0x0A, 0xF0, 0x33, 0xFC, 0x20, 0xB9, 0x1E, 0x4B, 0x22, 0x4D, 0x99, 0x88, 0x33, 0x7A, 0x7A, 0xE6, 0x0A, 0x9A, +0x1B, 0x49, 0x13, 0x7A, 0x89, 0x88, 0x1A, 0x44, 0x54, 0x72, 0x73, 0xE6, 0x40, 0xF6, 0xB4, 0x11, 0x15, 0xE5, 0x94, 0xF8, +0x70, 0x31, 0xF6, 0xE4, 0x05, 0xF5, 0x8C, 0x72, 0x18, 0xEE, 0x10, 0x1A, 0x0B, 0x98, 0x22, 0x44, 0xF9, 0xF7, 0x02, 0xFC, +0xA0, 0xB9, 0x97, 0xF8, 0x76, 0x31, 0xC2, 0xE7, 0x07, 0x9A, 0x0B, 0x98, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x43, +0x18, 0xEE, 0x10, 0x1A, 0xD3, 0xF8, 0xCC, 0x21, 0x42, 0xF0, 0x04, 0x02, 0xC3, 0xF8, 0xCC, 0x21, 0xF6, 0xF7, 0xF2, 0xFF, +0x01, 0x46, 0x01, 0xE6, 0xD9, 0xF8, 0xCC, 0x31, 0x0B, 0x98, 0x43, 0xF0, 0x08, 0x03, 0x18, 0xEE, 0x10, 0x1A, 0x32, 0x46, +0xC9, 0xF8, 0xCC, 0x31, 0xF9, 0xF7, 0x36, 0xFC, 0xDD, 0xE7, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x54, 0xBF, 0x15, 0x00, +0x68, 0xBF, 0x15, 0x00, 0x5C, 0xBF, 0x15, 0x00, 0x48, 0xBF, 0x15, 0x00, 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0xFF, 0xF7, +0x71, 0xBB, 0x00, 0xBF, 0x2D, 0xE9, 0xF8, 0x43, 0x03, 0x78, 0x43, 0xB3, 0x16, 0x4C, 0x07, 0x46, 0x4F, 0xF0, 0x00, 0x08, +0x04, 0xF5, 0x80, 0x56, 0x6F, 0xF0, 0x7F, 0x05, 0x00, 0xF1, 0x01, 0x09, 0x02, 0xE0, 0x40, 0x34, 0xB4, 0x42, 0x17, 0xD0, +0x23, 0x7A, 0xAB, 0xB1, 0x94, 0xF9, 0x44, 0x30, 0xAB, 0x42, 0xF6, 0xDD, 0x23, 0x7C, 0x3A, 0x78, 0x9A, 0x42, 0xF2, 0xD1, +0x49, 0x46, 0x04, 0xF1, 0x11, 0x00, 0x0A, 0xF0, 0x97, 0xF9, 0x00, 0x28, 0xEB, 0xD1, 0x94, 0xF9, 0x44, 0x50, 0x04, 0xF1, +0x08, 0x08, 0x40, 0x34, 0xB4, 0x42, 0xE7, 0xD1, 0x40, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x98, 0x46, 0x40, 0x46, 0xBD, 0xE8, +0xF8, 0x83, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x41, 0xF2, 0x0B, 0x03, 0xC2, 0x4D, 0xE9, 0x5C, +0x2E, 0x68, 0x01, 0x29, 0x82, 0xB0, 0x00, 0xF2, 0xB8, 0x81, 0x96, 0xF8, 0x6F, 0x01, 0x00, 0x27, 0x00, 0x28, 0x00, 0xF0, +0x57, 0x81, 0x33, 0x46, 0x00, 0x24, 0x03, 0xE0, 0x01, 0x34, 0x84, 0x42, 0x00, 0xF0, 0x50, 0x81, 0x9A, 0x78, 0x8A, 0x42, +0x03, 0xF1, 0x06, 0x03, 0xF6, 0xD1, 0x17, 0xB1, 0x41, 0xF2, 0x0B, 0x03, 0xE9, 0x54, 0x4F, 0xF4, 0xBA, 0x73, 0x02, 0x21, +0x04, 0x22, 0x4F, 0xF4, 0x00, 0x60, 0xF5, 0xF7, 0x03, 0xFE, 0x96, 0xF8, 0x6E, 0x31, 0x80, 0xF8, 0x6E, 0x31, 0x07, 0x46, +0xD6, 0xE9, 0x58, 0x01, 0xC7, 0xF8, 0x60, 0x01, 0xA7, 0xF8, 0x64, 0x11, 0x96, 0xF8, 0x70, 0x01, 0x87, 0xF8, 0x70, 0x01, +0x96, 0xF8, 0x71, 0x31, 0x87, 0xF8, 0x71, 0x31, 0x96, 0xF8, 0x6F, 0x31, 0x9C, 0x42, 0x80, 0xF2, 0x79, 0x81, 0x41, 0xF2, +0x0B, 0x02, 0x04, 0xEB, 0x44, 0x04, 0x06, 0x21, 0x15, 0xF8, 0x02, 0x80, 0x06, 0xEB, 0x44, 0x04, 0x11, 0xFB, 0x03, 0x61, +0xA3, 0x78, 0x43, 0x45, 0x10, 0xD1, 0x97, 0xF8, 0x6F, 0x31, 0xD4, 0xF8, 0x00, 0xC0, 0x03, 0xEB, 0x43, 0x02, 0x01, 0x33, +0x47, 0xF8, 0x12, 0xC0, 0x07, 0xEB, 0x42, 0x02, 0xB4, 0xF8, 0x04, 0xC0, 0xA2, 0xF8, 0x04, 0xC0, 0x87, 0xF8, 0x6F, 0x31, +0x06, 0x34, 0xA1, 0x42, 0xE8, 0xD1, 0xF0, 0xB1, 0x4F, 0xF0, 0x21, 0x0A, 0xFC, 0x21, 0x1A, 0xFB, 0x00, 0x1A, 0x73, 0x18, +0x03, 0xF1, 0x20, 0x09, 0x7A, 0x18, 0xD3, 0xF8, 0x00, 0xC0, 0x5C, 0x68, 0x98, 0x68, 0xD3, 0xF8, 0x0C, 0xE0, 0xC2, 0xF8, +0x0C, 0xE0, 0x10, 0x33, 0x4B, 0x45, 0xC2, 0xF8, 0x00, 0xC0, 0x54, 0x60, 0x90, 0x60, 0x02, 0xF1, 0x10, 0x02, 0xEE, 0xD1, +0x21, 0x31, 0x1B, 0x78, 0x13, 0x70, 0x51, 0x45, 0xE5, 0xD1, 0x2B, 0x68, 0xDF, 0xF8, 0x2C, 0xC2, 0xB3, 0xF8, 0x6C, 0x91, +0x81, 0x4C, 0xB9, 0xF1, 0xC9, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, 0x00, 0x09, 0xB8, 0xF1, 0x01, 0x0F, 0x66, 0x46, 0x00, 0xF0, +0xE5, 0x80, 0x93, 0xF8, 0x71, 0x21, 0x7C, 0x4B, 0x00, 0x2A, 0xA3, 0xF1, 0x04, 0x02, 0x0A, 0xBF, 0x13, 0x46, 0x4F, 0xF0, +0x08, 0x0E, 0x4F, 0xF0, 0x0C, 0x0E, 0x78, 0x4A, 0x01, 0x20, 0x08, 0x21, 0x10, 0x75, 0x15, 0x32, 0x61, 0x70, 0x58, 0x18, +0x13, 0xF8, 0x01, 0x1B, 0x02, 0xF8, 0x01, 0x1F, 0x98, 0x42, 0xF9, 0xD1, 0x72, 0x4B, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, +0x40, 0xF0, 0x99, 0x80, 0xBE, 0xF1, 0x08, 0x0F, 0x19, 0xD0, 0x01, 0x9B, 0x6E, 0x4A, 0x58, 0x1C, 0x32, 0x21, 0x01, 0x90, +0x19, 0x70, 0x01, 0x9B, 0xAE, 0xF1, 0x08, 0x0E, 0x59, 0x1C, 0x5F, 0xFA, 0x8E, 0xFE, 0x01, 0x91, 0x83, 0xF8, 0x00, 0xE0, +0x01, 0x9B, 0x18, 0x1D, 0x12, 0xF8, 0x01, 0x1B, 0x03, 0xF8, 0x01, 0x1B, 0x98, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x73, 0x44, +0x01, 0x93, 0x41, 0xF2, 0x0B, 0x03, 0xEB, 0x5C, 0x63, 0xB9, 0x01, 0x9B, 0x03, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, +0x01, 0x9B, 0x01, 0x22, 0x59, 0x1C, 0x01, 0x91, 0x1A, 0x70, 0x01, 0x9B, 0x13, 0x44, 0x01, 0x93, 0xB9, 0xF1, 0x00, 0x0F, +0x36, 0xD1, 0xDF, 0xF8, 0x7C, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD8, 0x07, 0x06, 0xD5, 0x56, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, +0x48, 0x31, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0x41, 0xF2, 0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0x4A, 0xD0, 0x5D, 0x07, +0x04, 0xD5, 0x4F, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x44, 0x31, 0x98, 0x47, 0x4D, 0x4D, 0x01, 0x98, 0x29, 0x46, 0x31, 0xF8, +0x03, 0x2B, 0x0A, 0xF0, 0xB1, 0xF8, 0x4B, 0x4A, 0x01, 0x99, 0x12, 0x68, 0x2B, 0x88, 0xB2, 0xF9, 0x00, 0x20, 0x0B, 0x44, +0x00, 0x2A, 0x01, 0x93, 0xA3, 0xEB, 0x04, 0x03, 0x5D, 0xDB, 0x00, 0x22, 0xA7, 0xF8, 0x6C, 0x31, 0xC7, 0xF8, 0x68, 0x21, +0x38, 0x46, 0xF5, 0xF7, 0x45, 0xFD, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x32, 0x78, 0x3B, 0x2A, 0x60, 0xD0, 0xDF, 0xF8, +0x08, 0x81, 0x98, 0xF8, 0x76, 0x31, 0xD9, 0x07, 0x58, 0xD5, 0x39, 0x4B, 0x01, 0xA8, 0xD3, 0xF8, 0x48, 0x31, 0x98, 0x47, +0xB9, 0xF1, 0x00, 0x0F, 0xC2, 0xD0, 0x01, 0x99, 0x32, 0x78, 0x0B, 0x46, 0x76, 0x1A, 0x49, 0x44, 0x00, 0xE0, 0xF2, 0x5C, +0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xFA, 0xD1, 0x01, 0x9A, 0x98, 0xF8, 0x76, 0x31, 0x4A, 0x44, 0x01, 0x92, 0x41, 0xF2, +0x0B, 0x02, 0xAA, 0x5C, 0x01, 0x2A, 0xB4, 0xD1, 0x9E, 0x07, 0xB2, 0xD5, 0x29, 0x4B, 0x00, 0x21, 0xD3, 0xF8, 0x50, 0x31, +0x01, 0xA8, 0x98, 0x47, 0x98, 0xF8, 0x76, 0x31, 0xA9, 0xE7, 0x9C, 0xF8, 0x00, 0x20, 0x0A, 0x2A, 0x7F, 0xF4, 0x62, 0xAF, +0x9C, 0xF8, 0x01, 0x60, 0x02, 0x36, 0x16, 0xF0, 0xFF, 0x06, 0x09, 0xD0, 0x22, 0x49, 0x98, 0x19, 0x01, 0xE0, 0x11, 0xF8, +0x01, 0x2F, 0x03, 0xF8, 0x01, 0x2B, 0x83, 0x42, 0xF9, 0xD1, 0x01, 0x9B, 0x33, 0x44, 0xA9, 0xEB, 0x06, 0x09, 0x01, 0x93, +0x1F, 0xFA, 0x89, 0xF9, 0x66, 0x44, 0x49, 0xE7, 0x01, 0x27, 0xB9, 0x42, 0x53, 0xD0, 0x39, 0x46, 0xA0, 0xE6, 0xB3, 0xF5, +0x96, 0x7F, 0x9E, 0xD9, 0x16, 0x49, 0x17, 0x48, 0xB4, 0x22, 0xF7, 0xF7, 0x99, 0xFD, 0x01, 0x9B, 0x1B, 0x1B, 0x96, 0xE7, +0x0A, 0x4B, 0x4F, 0xF0, 0x08, 0x0E, 0x22, 0xE7, 0x01, 0x99, 0xAE, 0xE7, 0x70, 0x78, 0x01, 0x99, 0x02, 0x30, 0x10, 0xF0, +0xFF, 0x00, 0x42, 0xD0, 0x0B, 0x46, 0xA6, 0xEB, 0x03, 0x0C, 0x01, 0x44, 0x1C, 0xE0, 0x00, 0xBF, 0xA8, 0xBA, 0x17, 0x00, +0xE8, 0x61, 0x18, 0x00, 0xB8, 0xB2, 0x15, 0x00, 0xD4, 0x61, 0x18, 0x00, 0xF2, 0x61, 0x18, 0x00, 0xBC, 0xB2, 0x15, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x68, 0xCB, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x18, 0x63, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, +0x9C, 0xBF, 0x15, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x1C, 0xF8, 0x03, 0x20, 0x03, 0xF8, 0x01, 0x2B, 0x99, 0x42, 0xF9, 0xD1, +0xDF, 0xF8, 0x48, 0x80, 0x01, 0x9B, 0x98, 0xF8, 0x76, 0x21, 0x03, 0x44, 0xA9, 0xEB, 0x00, 0x09, 0x01, 0x93, 0xD3, 0x07, +0x1F, 0xFA, 0x89, 0xF9, 0x06, 0x44, 0x7F, 0xF5, 0x6F, 0xAF, 0x68, 0xE7, 0x41, 0xF2, 0x0B, 0x03, 0x15, 0xF8, 0x03, 0x80, +0xA3, 0xE6, 0x41, 0xF2, 0x0B, 0x03, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0xFF, 0xF7, 0xDE, 0xF8, 0x4F, 0xE7, 0xDF, 0xF8, +0x10, 0x80, 0x98, 0xF8, 0x76, 0x31, 0xDB, 0x07, 0x3F, 0xF5, 0x55, 0xAF, 0x5D, 0xE7, 0x00, 0xBF, 0xE4, 0xB8, 0x17, 0x00, +0xF0, 0xB5, 0x4C, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x83, 0xB0, 0x04, 0xD1, 0x4A, 0x4A, 0x13, 0x68, 0x23, 0xF4, +0x00, 0x13, 0x13, 0x60, 0x48, 0x4C, 0x49, 0x4D, 0x23, 0x68, 0x5B, 0x07, 0x4E, 0xD4, 0x48, 0x4E, 0x41, 0xF2, 0x0A, 0x03, +0xEB, 0x5C, 0x5B, 0xB9, 0x44, 0x4A, 0x19, 0x46, 0x02, 0xF5, 0x80, 0x54, 0x80, 0x20, 0x11, 0x72, 0x82, 0xF8, 0x44, 0x00, +0x40, 0x32, 0x94, 0x42, 0xF9, 0xD1, 0xA9, 0x80, 0x29, 0x68, 0x91, 0xF8, 0x70, 0x21, 0x01, 0x2A, 0x5F, 0xD0, 0x00, 0x24, +0x20, 0x46, 0x41, 0xF2, 0x3A, 0x02, 0xA8, 0x54, 0x91, 0xF8, 0x6E, 0x21, 0x91, 0xF8, 0x6F, 0x11, 0x08, 0x20, 0xCD, 0xE9, +0x00, 0x41, 0x38, 0x49, 0xF7, 0xF7, 0xDC, 0xFA, 0x41, 0xF2, 0x0A, 0x03, 0xEB, 0x5C, 0x83, 0xB9, 0x35, 0x49, 0x36, 0x4A, +0x0B, 0x68, 0x36, 0x48, 0x43, 0xF0, 0x04, 0x03, 0x0B, 0x60, 0x13, 0x68, 0x03, 0x80, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, +0x43, 0xF4, 0xBB, 0x63, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x73, 0x68, 0x01, 0x21, 0x43, 0xF0, 0x20, 0x03, 0x04, 0x20, +0x73, 0x60, 0xF5, 0xF7, 0x01, 0xFE, 0x2B, 0x68, 0xD3, 0xF8, 0x68, 0x11, 0x19, 0xB1, 0xB3, 0xF8, 0x6C, 0x21, 0xC8, 0x2A, +0x23, 0xD9, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xCE, 0xBD, 0x2B, 0x68, 0x25, 0x4A, 0x93, 0xF8, 0x6E, 0x31, +0x24, 0x49, 0x1E, 0x4E, 0x10, 0x68, 0x24, 0x4A, 0xC0, 0x8E, 0x4F, 0xF4, 0xA4, 0x67, 0x07, 0xFB, 0x03, 0x13, 0x03, 0x21, +0x71, 0x77, 0x11, 0x69, 0x20, 0x4A, 0x73, 0x61, 0x01, 0x44, 0xD2, 0xF8, 0xE0, 0x31, 0x06, 0xF1, 0x0C, 0x00, 0x98, 0x47, +0x01, 0x23, 0x33, 0x77, 0x23, 0x68, 0x23, 0xF0, 0x04, 0x03, 0x23, 0x60, 0x92, 0xE7, 0x1A, 0x48, 0x09, 0xF0, 0x60, 0xFF, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0xFF, 0xF7, 0xA7, 0xBD, 0x91, 0xF8, 0xFC, 0x20, 0x07, 0x2A, 0x9B, 0xD1, 0x01, 0xF1, +0xFD, 0x00, 0x14, 0x49, 0x09, 0xF0, 0x22, 0xFF, 0x41, 0xF2, 0x0A, 0x03, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0xEB, 0x5C, +0x29, 0x68, 0x04, 0x46, 0x8F, 0xE7, 0x00, 0xBF, 0x74, 0x36, 0x17, 0x00, 0x6C, 0x00, 0x32, 0x40, 0x4C, 0x00, 0x32, 0x40, +0xA8, 0xBA, 0x17, 0x00, 0x1C, 0x9E, 0x17, 0x00, 0xCC, 0xBF, 0x15, 0x00, 0x94, 0x40, 0x04, 0x40, 0x20, 0x04, 0x32, 0x40, +0x28, 0x25, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, +0x18, 0x63, 0x18, 0x00, 0x54, 0xBF, 0x15, 0x00, 0x00, 0x22, 0x02, 0x81, 0xE7, 0xF7, 0xE0, 0xBA, 0x2D, 0xE9, 0xF0, 0x41, +0x14, 0x46, 0x52, 0x78, 0x00, 0x2B, 0x18, 0xBF, 0x02, 0x23, 0x52, 0x06, 0x44, 0xBF, 0x08, 0x33, 0xDB, 0xB2, 0x23, 0x44, +0x06, 0x46, 0x9A, 0x7F, 0x08, 0x2A, 0x0D, 0x46, 0x03, 0xD0, 0x00, 0x27, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0xDA, 0x7F, +0x06, 0x2A, 0xF8, 0xD1, 0x93, 0xF8, 0x26, 0x70, 0x00, 0x2F, 0xF4, 0xD1, 0x93, 0xF8, 0x27, 0x80, 0xB8, 0xF1, 0x01, 0x0F, +0x07, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0xED, 0xD1, 0x13, 0x49, 0x80, 0x20, 0xF7, 0xF7, 0x2E, 0xFA, 0xE8, 0xE7, 0x93, 0xF8, +0x3A, 0x70, 0x93, 0xF8, 0x3B, 0xC0, 0x93, 0xF8, 0x38, 0x00, 0x93, 0xF8, 0x39, 0x20, 0x0B, 0x68, 0x0D, 0x49, 0x3F, 0x04, +0x47, 0xEA, 0x0C, 0x67, 0x07, 0x43, 0x47, 0xEA, 0x02, 0x27, 0x3A, 0x46, 0x80, 0x20, 0xF7, 0xF7, 0x19, 0xFA, 0x2B, 0x68, +0x9F, 0x42, 0x01, 0xD0, 0x47, 0x46, 0xCF, 0xE7, 0x06, 0x4B, 0x30, 0x78, 0x9B, 0x69, 0x22, 0x46, 0x04, 0xF1, 0x10, 0x01, +0x47, 0x46, 0x98, 0x47, 0xC6, 0xE7, 0x00, 0xBF, 0x08, 0xC0, 0x15, 0x00, 0xE8, 0xBF, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4D, 0x1E, 0x68, 0x95, 0xF8, 0x44, 0x40, 0xB6, 0xF9, 0x00, 0x70, 0x1F, 0x4B, 0x04, 0xEB, +0x84, 0x06, 0x00, 0x2F, 0x8E, 0x46, 0x03, 0xEB, 0x06, 0x16, 0x23, 0xDB, 0xA7, 0x00, 0x07, 0xEB, 0x04, 0x0C, 0x03, 0xEB, +0x0C, 0x1C, 0xCC, 0xF8, 0x0C, 0x00, 0x10, 0xB1, 0x01, 0x7C, 0x8C, 0xF8, 0x10, 0x10, 0x3C, 0x44, 0x03, 0xEB, 0x04, 0x13, +0x31, 0x46, 0x5A, 0x64, 0xA3, 0xF8, 0x4C, 0xE0, 0x13, 0x48, 0xF5, 0xF7, 0xB5, 0xFF, 0x95, 0xF8, 0x44, 0x20, 0x12, 0x4B, +0x01, 0x32, 0xA3, 0xFB, 0x02, 0x13, 0xDB, 0x09, 0x03, 0xEB, 0x43, 0x03, 0xA2, 0xEB, 0x83, 0x13, 0x85, 0xF8, 0x44, 0x30, +0x30, 0x46, 0xF8, 0xBD, 0x04, 0xEB, 0x84, 0x01, 0x03, 0xEB, 0x01, 0x11, 0xA7, 0x00, 0xB1, 0xF8, 0x4C, 0x10, 0x00, 0x29, +0xD3, 0xD0, 0x08, 0x49, 0x08, 0x48, 0xC6, 0x22, 0xF7, 0xF7, 0xBA, 0xFB, 0x00, 0x26, 0xED, 0xE7, 0x38, 0x36, 0x17, 0x00, +0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0xAB, 0xAA, 0xAA, 0xAA, 0x70, 0x79, 0x15, 0x00, +0x14, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x0C, 0x4D, 0x42, 0x69, 0x04, 0x46, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, +0x21, 0x46, 0x28, 0x46, 0xF5, 0xF7, 0xCC, 0xFF, 0xA5, 0xF1, 0x08, 0x00, 0x21, 0x46, 0xF5, 0xF7, 0x77, 0xFF, 0x05, 0x4B, +0xA5, 0xF1, 0x20, 0x00, 0xD3, 0xF8, 0x38, 0x31, 0xBD, 0xE8, 0x70, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x08, 0xDF, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0xB3, 0x4B, 0x01, 0xF0, 0x7C, 0x04, 0x1A, 0x7A, 0x04, 0x3C, 0x00, 0xEB, +0x02, 0x0C, 0x01, 0xF4, 0x80, 0x6E, 0x18, 0x2C, 0x0E, 0xD8, 0xDF, 0xE8, 0x04, 0xF0, 0x54, 0x0D, 0x0D, 0x0D, 0x58, 0x0D, +0x0D, 0x0D, 0x8D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0xB5, 0x00, +0x00, 0x24, 0xA7, 0x4D, 0x2D, 0x68, 0x2D, 0x78, 0xAD, 0x07, 0x03, 0xD5, 0x01, 0xF0, 0x3C, 0x01, 0x3C, 0x29, 0x02, 0xD0, +0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xD1, 0x80, 0xBC, 0xF8, 0x02, 0x10, 0x9E, 0x7A, +0x9E, 0x4C, 0x8D, 0x0B, 0x4F, 0xF4, 0xA4, 0x61, 0xC5, 0xEB, 0x05, 0x17, 0x01, 0xFB, 0x06, 0xF1, 0x01, 0xEB, 0xC7, 0x01, +0x21, 0x44, 0x2F, 0x01, 0x91, 0xF8, 0x3B, 0xE2, 0xBE, 0xF1, 0x00, 0x0F, 0x00, 0xF0, 0xCC, 0x80, 0x91, 0xF8, 0x38, 0x12, +0x01, 0x29, 0x00, 0xF0, 0xEB, 0x80, 0x02, 0x29, 0x00, 0xF0, 0xC1, 0x80, 0x0A, 0x1F, 0x01, 0x2A, 0x40, 0xF2, 0xBD, 0x80, +0x1A, 0x7A, 0x04, 0x32, 0x1A, 0x72, 0xDC, 0xF8, 0x00, 0x00, 0xC1, 0x17, 0xC3, 0xE9, 0x04, 0x01, 0x4F, 0xF4, 0xA4, 0x62, +0x02, 0xFB, 0x06, 0xF2, 0x79, 0x1B, 0x02, 0xF5, 0xEC, 0x72, 0x02, 0xEB, 0xC1, 0x02, 0x22, 0x44, 0x1A, 0x62, 0x01, 0x24, +0xC2, 0xE7, 0x14, 0x1D, 0x1C, 0x72, 0x01, 0x24, 0xB5, 0xE7, 0x02, 0xF1, 0x08, 0x04, 0x1C, 0x72, 0x30, 0xF8, 0x02, 0x80, +0xBC, 0xF8, 0x06, 0x40, 0x9C, 0xF8, 0x02, 0xA0, 0x93, 0xF8, 0x30, 0x90, 0x4F, 0xEA, 0x08, 0x28, 0x1F, 0xFA, 0x88, 0xF8, +0x46, 0x46, 0xF7, 0x17, 0x44, 0xEA, 0x07, 0x06, 0xBC, 0xF8, 0x04, 0x40, 0x4A, 0xEA, 0x04, 0x44, 0x44, 0xEA, 0x08, 0x04, +0x49, 0xF0, 0x03, 0x09, 0xC3, 0xE9, 0x04, 0x46, 0x83, 0xF8, 0x30, 0x90, 0xBE, 0xF1, 0x00, 0x0F, 0x5F, 0xD0, 0x9E, 0x7A, +0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x6E, 0x4E, 0x04, 0xF5, 0xEC, 0x74, +0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x1C, 0x62, 0x01, 0x24, 0x80, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, +0x50, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x63, 0x4E, +0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x08, 0x05, 0x1D, 0x72, +0xBC, 0xF8, 0x04, 0x60, 0x93, 0xF8, 0x30, 0x80, 0x1C, 0x62, 0x84, 0x5A, 0xBC, 0xF8, 0x06, 0x50, 0x5D, 0x61, 0x44, 0xEA, +0x06, 0x44, 0x48, 0xF0, 0x02, 0x05, 0x1C, 0x61, 0x83, 0xF8, 0x30, 0x50, 0x01, 0x24, 0x58, 0xE7, 0xBE, 0xF1, 0x00, 0x0F, +0x2F, 0xD0, 0x9E, 0x7A, 0xBC, 0xF8, 0x02, 0x50, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, 0x06, 0xF4, 0xAD, 0x0B, 0x4F, 0x4E, +0x04, 0xF5, 0xEC, 0x74, 0xC5, 0xEB, 0x05, 0x15, 0x04, 0xEB, 0xC5, 0x04, 0x34, 0x44, 0x02, 0xF1, 0x12, 0x05, 0x66, 0x46, +0x1D, 0x72, 0x56, 0xF8, 0x02, 0x7F, 0x93, 0xF8, 0x30, 0x50, 0x76, 0x68, 0x1C, 0x62, 0x45, 0xF0, 0x02, 0x04, 0x83, 0xF8, +0x30, 0x40, 0xC3, 0xE9, 0x04, 0x76, 0x01, 0x24, 0x33, 0xE7, 0x5C, 0x7A, 0x42, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, +0x04, 0x54, 0xA8, 0xE7, 0x5C, 0x7A, 0x3F, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xB7, 0xE7, 0x5C, 0x7A, +0x3B, 0x4D, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x04, 0x54, 0xD8, 0xE7, 0x59, 0x7A, 0x39, 0x4D, 0x4F, 0xF4, 0x1E, 0x74, +0x04, 0xFB, 0x01, 0xF4, 0x29, 0x19, 0x91, 0xF8, 0x98, 0x10, 0x01, 0x29, 0x43, 0xD0, 0x02, 0x29, 0x04, 0xD1, 0x34, 0x48, +0xF7, 0xF7, 0x36, 0xF8, 0x00, 0x24, 0x15, 0xE7, 0x0A, 0x1F, 0x01, 0x2A, 0xF7, 0xD9, 0x18, 0x7A, 0xBC, 0xF8, 0x02, 0x10, +0x9D, 0x7A, 0x2B, 0x4E, 0x04, 0x30, 0x18, 0x72, 0xDC, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x05, 0xF2, +0x89, 0x0B, 0xE5, 0x17, 0xC1, 0xEB, 0x01, 0x11, 0x02, 0xF5, 0xEC, 0x72, 0xC3, 0xE9, 0x04, 0x45, 0x02, 0xEB, 0xC1, 0x02, +0x32, 0x44, 0x92, 0xF8, 0x63, 0x10, 0x00, 0x29, 0xDE, 0xD0, 0x1A, 0x62, 0x01, 0x24, 0xF3, 0xE6, 0x19, 0x7A, 0x93, 0xF8, +0x30, 0xE0, 0x08, 0x31, 0x19, 0x72, 0x82, 0x5A, 0x9C, 0xF8, 0x02, 0x80, 0xBC, 0xF8, 0x04, 0x00, 0xBC, 0xF8, 0x06, 0x90, +0x12, 0x02, 0x92, 0xB2, 0xD1, 0x17, 0x48, 0xEA, 0x00, 0x40, 0x49, 0xEA, 0x01, 0x09, 0x02, 0x43, 0x4E, 0xF0, 0x03, 0x0E, +0xC3, 0xE9, 0x04, 0x29, 0x83, 0xF8, 0x30, 0xE0, 0x08, 0xE7, 0x19, 0x7A, 0x93, 0xF8, 0x30, 0x70, 0x08, 0x31, 0x19, 0x72, +0x81, 0x5A, 0xBC, 0xF8, 0x04, 0x80, 0x9C, 0xF8, 0x02, 0x00, 0xBC, 0xF8, 0x06, 0x60, 0x09, 0x02, 0x89, 0xB2, 0x04, 0xF1, +0x38, 0x02, 0x40, 0xEA, 0x08, 0x44, 0x0C, 0x43, 0xC9, 0x17, 0x47, 0xF0, 0x03, 0x07, 0x0E, 0x43, 0xC3, 0xE9, 0x04, 0x46, +0x2A, 0x44, 0x83, 0xF8, 0x30, 0x70, 0xC0, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, +0xA0, 0x65, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x34, 0xC0, 0x15, 0x00, 0x70, 0xB5, 0x18, 0x4E, 0x18, 0x4A, 0xB3, 0x7A, +0x75, 0x7A, 0x12, 0x7C, 0x1B, 0x02, 0x43, 0xEA, 0x05, 0x43, 0xF5, 0x7A, 0x04, 0x46, 0x00, 0x6E, 0x43, 0xEA, 0x05, 0x63, +0xFF, 0x2A, 0x0D, 0x46, 0x43, 0xEA, 0x00, 0x03, 0x17, 0xD0, 0x41, 0xF0, 0x80, 0x05, 0x43, 0xF0, 0x80, 0x03, 0xEA, 0x07, +0x48, 0xBF, 0x43, 0xF0, 0x40, 0x03, 0x0D, 0x4A, 0x58, 0xBF, 0x23, 0xF0, 0x40, 0x03, 0x23, 0x66, 0x20, 0x46, 0xD2, 0xF8, +0xA8, 0x32, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xEF, 0xBD, 0x29, 0x06, +0x58, 0xBF, 0x23, 0xF0, 0x80, 0x03, 0xE6, 0xD5, 0xE3, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0xF8, 0xB5, 0x21, 0x4B, 0x21, 0x4E, 0x1B, 0x7C, 0xFF, 0x2B, 0x04, 0x46, 0x0D, 0x46, 0x21, 0xD0, +0xB2, 0x7A, 0xFF, 0x2A, 0x32, 0xD0, 0x01, 0xF0, 0x01, 0x01, 0x45, 0xF0, 0x80, 0x05, 0x77, 0x7A, 0x20, 0x6E, 0x13, 0x02, +0x43, 0xEA, 0x07, 0x43, 0x03, 0x43, 0x43, 0xF0, 0x82, 0x03, 0x11, 0xB3, 0x43, 0xF0, 0x40, 0x03, 0x16, 0x49, 0x23, 0x66, +0x00, 0x22, 0xD1, 0xF8, 0xA8, 0x32, 0x86, 0xF8, 0x32, 0x20, 0x20, 0x46, 0x98, 0x47, 0x32, 0x6C, 0x29, 0x46, 0x20, 0x46, +0xBD, 0xE8, 0xF8, 0x40, 0xFF, 0xF7, 0xB8, 0xBD, 0xB3, 0x7A, 0x71, 0x7A, 0x02, 0x6E, 0x1B, 0x02, 0x43, 0xEA, 0x01, 0x43, +0x13, 0x43, 0x2A, 0x06, 0x0D, 0xD4, 0x23, 0xF0, 0x80, 0x03, 0x05, 0xF0, 0x01, 0x01, 0x43, 0xF0, 0x02, 0x03, 0x00, 0x29, +0xDC, 0xD1, 0x23, 0xF0, 0x40, 0x03, 0xDB, 0xE7, 0x00, 0x21, 0x80, 0x25, 0xCD, 0xE7, 0x05, 0xF0, 0x01, 0x01, 0xD0, 0xE7, +0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x32, 0x4B, 0x01, 0x88, 0x70, 0xB4, 0x19, 0x80, +0xC2, 0x8A, 0x5A, 0x80, 0x01, 0xF0, 0x88, 0x06, 0xC2, 0xF3, 0x0B, 0x14, 0x00, 0x25, 0x02, 0xF0, 0x0F, 0x02, 0x88, 0x2E, +0x9C, 0x80, 0x9A, 0x71, 0x8C, 0xB2, 0x83, 0xF8, 0x30, 0x50, 0x45, 0xD0, 0xDD, 0x71, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, +0x40, 0x7F, 0x04, 0xF0, 0xFC, 0x05, 0x0C, 0xBF, 0x1E, 0x22, 0x18, 0x22, 0x88, 0x2D, 0x08, 0xBF, 0x02, 0x32, 0x0E, 0x04, +0x44, 0xBF, 0x04, 0x32, 0xD2, 0xB2, 0x1A, 0x72, 0x02, 0x79, 0xD5, 0x07, 0x44, 0xBF, 0x08, 0x22, 0x83, 0xF8, 0x30, 0x20, +0xE4, 0x05, 0x12, 0xD5, 0x02, 0x8A, 0x9A, 0x84, 0x42, 0x8A, 0xDA, 0x84, 0x82, 0x8A, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, +0x12, 0xD5, 0xD2, 0x05, 0x18, 0xD5, 0x02, 0x8B, 0x5A, 0x85, 0x42, 0x8B, 0x9A, 0x85, 0x82, 0x8B, 0xDA, 0x85, 0x70, 0xBC, +0x70, 0x47, 0x82, 0x88, 0x9A, 0x84, 0xC2, 0x88, 0xDA, 0x84, 0x02, 0x89, 0x1A, 0x85, 0x02, 0x88, 0x91, 0x05, 0xEC, 0xD4, +0x42, 0x89, 0x5A, 0x85, 0x82, 0x89, 0x9A, 0x85, 0xC2, 0x89, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x02, 0x8A, 0x5A, 0x85, +0x42, 0x8A, 0x9A, 0x85, 0x82, 0x8A, 0xDA, 0x85, 0x70, 0xBC, 0x70, 0x47, 0x04, 0xF4, 0x40, 0x72, 0xB2, 0xF5, 0x40, 0x7F, +0x0C, 0xBF, 0xC5, 0x8B, 0x05, 0x8B, 0x05, 0xF0, 0x07, 0x05, 0xDD, 0x71, 0xB1, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, +0xF8, 0xB5, 0x05, 0x22, 0x18, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x06, 0x40, 0xF5, 0xF7, 0x74, 0xF8, 0x0F, 0x4A, 0x03, 0x46, +0x51, 0x7A, 0x0F, 0x48, 0x94, 0x69, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x01, 0x01, 0xD2, 0xE9, 0x04, 0x67, 0x51, 0xF8, +0x26, 0x0F, 0x89, 0x88, 0x99, 0x80, 0xC3, 0xE9, 0x02, 0x67, 0x18, 0x60, 0x91, 0x7A, 0x99, 0x74, 0xC4, 0xF3, 0x80, 0x24, +0x1C, 0x74, 0x12, 0x6A, 0x92, 0xF8, 0x61, 0x20, 0x5A, 0x74, 0x18, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xF5, 0xF7, 0x84, 0xB8, +0xB0, 0xDE, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0x3C, 0x82, 0xD8, 0xF8, 0x00, 0x40, +0x27, 0x78, 0x87, 0xB0, 0x17, 0xF0, 0x01, 0x07, 0x04, 0x46, 0x03, 0x93, 0x08, 0xD0, 0x43, 0x6D, 0x03, 0xF0, 0x07, 0x03, +0x02, 0x2B, 0x7F, 0xD0, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x80, 0x4D, 0x89, 0x46, 0x00, 0x2A, 0x40, 0xF0, +0xA2, 0x80, 0x02, 0x8E, 0x2B, 0x7A, 0xC6, 0x69, 0xD4, 0x1A, 0x03, 0x9A, 0xA4, 0xB2, 0x10, 0x31, 0x12, 0xB1, 0x07, 0x2C, +0x40, 0xF2, 0xA9, 0x80, 0x08, 0x22, 0x48, 0x46, 0xFA, 0xF7, 0x92, 0xFF, 0x29, 0x7A, 0x8A, 0xB2, 0xD6, 0xE9, 0x02, 0x03, +0x08, 0x3C, 0x01, 0x33, 0xA5, 0xB2, 0x1C, 0x1A, 0xA4, 0xB2, 0x4B, 0x19, 0x9C, 0x42, 0x01, 0x44, 0x80, 0xF2, 0x82, 0x80, +0xDF, 0xF8, 0xD4, 0xA1, 0x13, 0x1B, 0x1D, 0x44, 0xA2, 0x1A, 0x92, 0xB2, 0x48, 0x46, 0xAD, 0xB2, 0xFA, 0xF7, 0x7A, 0xFF, +0x00, 0x22, 0x95, 0xB1, 0xDA, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x93, 0x42, 0x4D, 0xDB, 0xD6, 0xE9, +0x02, 0x14, 0x01, 0x34, 0x64, 0x1A, 0xA4, 0xB2, 0xAC, 0x42, 0xE7, 0xD3, 0x2C, 0x46, 0x2A, 0x46, 0x48, 0x46, 0xFA, 0xF7, +0x65, 0xFF, 0xDF, 0xF8, 0x98, 0xE1, 0x0D, 0xF1, 0x10, 0x0C, 0x08, 0x25, 0xD6, 0xE9, 0x02, 0x32, 0x01, 0x32, 0x98, 0xB2, +0x92, 0xB2, 0xA2, 0xEB, 0x00, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x29, 0x19, 0x51, 0x45, 0x23, 0x44, 0x3B, 0xDD, 0xAA, 0xEB, +0x04, 0x0A, 0x1F, 0xFA, 0x8A, 0xFA, 0x0A, 0xF1, 0xFF, 0x3B, 0xBA, 0xF1, 0x00, 0x0F, 0x37, 0xD0, 0x82, 0x1A, 0x14, 0x44, +0x25, 0x44, 0xAD, 0xB2, 0x59, 0x1C, 0x59, 0x44, 0xAC, 0xEB, 0x03, 0x00, 0x1A, 0x78, 0xC2, 0x54, 0x01, 0x33, 0x8B, 0x42, +0xFA, 0xD1, 0xD4, 0x44, 0x65, 0xB3, 0xDE, 0xF8, 0x00, 0x30, 0x76, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x24, 0xA3, 0x42, +0xD2, 0xDA, 0x00, 0x2E, 0xD0, 0xD1, 0x47, 0x49, 0x47, 0x48, 0x40, 0xF2, 0x66, 0x42, 0xF7, 0xF7, 0x6F, 0xF8, 0x7F, 0xE7, +0xFF, 0xF7, 0x40, 0xFF, 0x00, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x2E, 0xAF, 0xD1, 0x3F, 0x49, +0x3F, 0x48, 0x40, 0xF2, 0x3C, 0x42, 0xF7, 0xF7, 0x5F, 0xF8, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xAA, 0x46, +0x05, 0xF1, 0xFF, 0x3B, 0x00, 0x25, 0xCB, 0xE7, 0x01, 0x44, 0x8A, 0x1A, 0x95, 0xB2, 0xD2, 0xE7, 0x03, 0x9B, 0x00, 0x2B, +0x3C, 0xD1, 0xDD, 0xE9, 0x04, 0x23, 0xC9, 0xE9, 0x04, 0x23, 0x01, 0x27, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x2A, 0x44, 0x94, 0xB2, 0x95, 0xE7, 0x29, 0x6A, 0xEB, 0x79, 0x00, 0x93, 0x58, 0x31, 0x05, 0xF1, 0x2A, 0x03, 0x05, 0xF1, +0x24, 0x02, 0x48, 0x46, 0xFA, 0xF7, 0xCE, 0xFE, 0x29, 0x7A, 0x23, 0x8E, 0xE6, 0x69, 0x5C, 0x1A, 0xA4, 0xB2, 0x8A, 0xB2, +0x5C, 0xE7, 0xB5, 0x68, 0x03, 0x91, 0x22, 0x46, 0x48, 0x46, 0x1D, 0x44, 0xFA, 0xF7, 0xE6, 0xFE, 0x03, 0x99, 0xC4, 0xF1, +0x08, 0x06, 0x04, 0xAB, 0xF6, 0xB2, 0x21, 0x44, 0xF2, 0x18, 0xC9, 0x1A, 0xC8, 0x5C, 0x03, 0xF8, 0x01, 0x0B, 0x9A, 0x42, +0xFA, 0xD1, 0xD6, 0xF1, 0x08, 0x06, 0x07, 0xD0, 0x2B, 0x46, 0xD2, 0x1A, 0x35, 0x44, 0x19, 0x78, 0xD1, 0x54, 0x01, 0x33, +0x9D, 0x42, 0xFA, 0xD1, 0x48, 0x46, 0xFA, 0xF7, 0x69, 0xFF, 0x04, 0x9A, 0xD9, 0xF8, 0x00, 0x30, 0x9A, 0x42, 0x0D, 0xD0, +0xD8, 0xF8, 0x00, 0x30, 0x1B, 0x78, 0x9B, 0x07, 0x05, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xCE, 0xF9, 0x0F, 0x4B, 0x98, 0x42, +0x12, 0xD1, 0xFF, 0xF7, 0xD1, 0xFE, 0x0D, 0xE7, 0xD9, 0xF8, 0x04, 0x30, 0x05, 0x9A, 0x9A, 0x42, 0xEC, 0xD1, 0xD8, 0xF8, +0x00, 0x30, 0x1B, 0x78, 0x9A, 0x07, 0xA6, 0xD5, 0x03, 0x20, 0xD8, 0xF7, 0xBB, 0xF9, 0x06, 0x4B, 0x98, 0x42, 0xA0, 0xD0, +0x05, 0x48, 0xF6, 0xF7, 0xA1, 0xFD, 0xF9, 0xE6, 0xB0, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xA0, 0x96, 0x15, 0x00, +0x1C, 0xDF, 0x44, 0x21, 0x44, 0xC0, 0x15, 0x00, 0x34, 0x36, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x10, 0xB5, 0x10, 0x48, +0xF5, 0xF7, 0xF8, 0xFB, 0x10, 0xB1, 0x04, 0x46, 0x20, 0x46, 0x10, 0xBD, 0x0D, 0x48, 0xF5, 0xF7, 0xF1, 0xFB, 0x0D, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0x46, 0x06, 0xDB, 0x62, 0x69, 0x04, 0x21, 0x00, 0x20, 0xFF, 0xF7, +0xC7, 0xFB, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x28, 0xF6, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF2, 0xEA, 0x42, 0xF6, 0xF7, +0xEB, 0xFF, 0xEF, 0xE7, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x54, 0xC0, 0x15, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x00, 0x20, 0x63, 0x79, 0x62, 0x69, 0x83, 0x42, 0x14, 0xBF, 0x18, 0x21, +0x08, 0x21, 0xFF, 0xF7, 0xA7, 0xFB, 0x08, 0xB1, 0xA3, 0x89, 0x83, 0x64, 0x10, 0xBD, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x47, +0xA3, 0x4F, 0x8A, 0xB0, 0x05, 0x46, 0x14, 0x46, 0x1A, 0xB3, 0x3E, 0x88, 0x97, 0xF8, 0x07, 0x80, 0x16, 0xF4, 0x80, 0x66, +0x22, 0xD1, 0x97, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, 0x00, 0x0F, 0x6A, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x14, 0xB9, 0x31, 0xE1, +0x24, 0x68, 0xEC, 0xB1, 0xA3, 0x79, 0x8B, 0x42, 0xFA, 0xD1, 0xE3, 0x79, 0x43, 0x45, 0xF7, 0xD1, 0x63, 0x89, 0x93, 0x42, +0xF4, 0xD1, 0x23, 0x7A, 0x53, 0x45, 0x00, 0xF0, 0x90, 0x80, 0x4F, 0xF0, 0x00, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, +0xF0, 0x87, 0x3E, 0x88, 0x16, 0xF4, 0x80, 0x66, 0x90, 0x46, 0xDC, 0xD0, 0xBC, 0x6D, 0xBA, 0x88, 0x97, 0xF8, 0x06, 0xA0, +0x00, 0x2C, 0xE1, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0xEB, 0xD1, 0x03, 0x91, 0xFF, 0xF7, 0x88, 0xFF, 0x01, 0x26, 0x03, 0x99, +0x81, 0x71, 0x80, 0xF8, 0x07, 0x80, 0x06, 0x72, 0xBA, 0x88, 0x80, 0xF8, 0x04, 0xA0, 0x39, 0x7A, 0x82, 0x4B, 0xC0, 0xF8, +0x10, 0xA0, 0x41, 0x72, 0x19, 0x69, 0xDF, 0xF8, 0x0C, 0x92, 0x80, 0x4B, 0x42, 0x81, 0x01, 0xF5, 0xC3, 0x31, 0x83, 0x63, +0xC0, 0x63, 0xD9, 0xF8, 0xE0, 0x31, 0x04, 0x46, 0xA0, 0x31, 0x34, 0x30, 0x98, 0x47, 0x97, 0xF8, 0x30, 0x30, 0xDA, 0x07, +0x00, 0xF1, 0xC9, 0x80, 0x2B, 0x6E, 0x23, 0xF0, 0x20, 0x03, 0x2B, 0x66, 0xD9, 0xF8, 0xE8, 0x32, 0x01, 0x21, 0x28, 0x46, +0x98, 0x47, 0x3B, 0x6C, 0xFA, 0x69, 0x73, 0x48, 0xC4, 0xE9, 0x04, 0x23, 0x97, 0xF8, 0x31, 0x30, 0x63, 0x71, 0x2B, 0x8E, +0xA3, 0x81, 0x21, 0x46, 0xF5, 0xF7, 0x08, 0xFB, 0x6B, 0x4B, 0x4F, 0xF0, 0x01, 0x0A, 0x1B, 0x69, 0xA3, 0x61, 0x50, 0x46, +0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x97, 0xF8, 0x30, 0x30, 0xD8, 0x07, 0x1D, 0xD5, 0x68, 0x4A, 0x01, 0x23, 0xD2, 0xF8, +0xCC, 0x62, 0x04, 0xA9, 0x1A, 0x46, 0x28, 0x46, 0xB0, 0x47, 0x00, 0x28, 0x9B, 0xD0, 0x2B, 0x8E, 0x63, 0x4A, 0x08, 0x3B, +0x12, 0x68, 0x2B, 0x86, 0x13, 0x78, 0x99, 0x07, 0x0B, 0xD5, 0x6B, 0x6D, 0x03, 0xF0, 0x3C, 0x02, 0x3C, 0x2A, 0x06, 0xD1, +0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x08, 0x03, 0x6B, 0x65, 0x5B, 0x4B, 0xB8, 0x7A, 0x4F, 0xF4, +0xA4, 0x62, 0x02, 0xFB, 0x00, 0x30, 0x90, 0xF8, 0xC3, 0x34, 0x00, 0x2B, 0x6D, 0xD1, 0x54, 0x4B, 0x28, 0x46, 0xD3, 0xF8, +0xE8, 0x32, 0x03, 0x21, 0x98, 0x47, 0x4F, 0xF0, 0x01, 0x0A, 0x50, 0x46, 0x0A, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x29, 0x8E, +0x94, 0xF8, 0x09, 0x80, 0xA3, 0x89, 0xDF, 0xF8, 0x30, 0x91, 0xA1, 0xEB, 0x08, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x43, 0x44, +0x0A, 0xF1, 0x01, 0x0A, 0x84, 0xF8, 0x08, 0xA0, 0xA3, 0x81, 0x97, 0xF8, 0x30, 0x30, 0xDB, 0x07, 0x22, 0xD5, 0xB6, 0xFA, +0x86, 0xF3, 0xD9, 0xF8, 0xCC, 0x72, 0x5B, 0x09, 0x00, 0x22, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, 0xB8, 0x47, 0x00, 0x28, +0x4C, 0xD0, 0x2B, 0x6E, 0x00, 0x2E, 0x57, 0xD0, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, +0x2B, 0x66, 0x41, 0x44, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0xD9, 0xF8, 0xA4, 0x62, 0x89, 0xB2, 0x28, 0x46, 0xB0, 0x47, +0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x87, 0xE7, 0x01, 0x27, 0x2B, 0x6E, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, +0x40, 0x03, 0x2B, 0x66, 0x00, 0x23, 0xCD, 0xE9, 0x00, 0x33, 0x28, 0x46, 0xD9, 0xF8, 0xA4, 0x52, 0xA8, 0x47, 0x23, 0x69, +0x43, 0x44, 0x23, 0x61, 0x00, 0x2E, 0x7F, 0xF4, 0x73, 0xAF, 0x20, 0x46, 0xFF, 0xF7, 0xEC, 0xFE, 0x62, 0x69, 0x39, 0x46, +0x00, 0x20, 0xFF, 0xF7, 0x99, 0xFA, 0xD9, 0xF8, 0xD8, 0x31, 0x04, 0xF1, 0x34, 0x00, 0x98, 0x47, 0x21, 0x46, 0x20, 0x48, +0xF5, 0xF7, 0xBA, 0xFA, 0x22, 0x48, 0x21, 0x46, 0xF5, 0xF7, 0x66, 0xFA, 0x5C, 0xE7, 0xEA, 0x69, 0x00, 0xF2, 0xC4, 0x41, +0x92, 0x68, 0x23, 0x46, 0x63, 0x30, 0xFF, 0xF7, 0x31, 0xFA, 0x01, 0x28, 0x87, 0xD1, 0x04, 0xE7, 0x61, 0x7A, 0x41, 0x44, +0x89, 0xB2, 0x04, 0x27, 0xC5, 0xE7, 0x32, 0x46, 0x53, 0x46, 0xD9, 0xF8, 0xCC, 0x62, 0x04, 0xF1, 0x1C, 0x01, 0x28, 0x46, +0xB0, 0x47, 0x2D, 0xE7, 0xA0, 0x89, 0x61, 0x7A, 0x22, 0x69, 0x23, 0xF0, 0x20, 0x03, 0x43, 0xF0, 0x40, 0x03, 0x08, 0x38, +0xA0, 0x81, 0x41, 0x44, 0x2B, 0x66, 0x28, 0x46, 0x33, 0x46, 0xCD, 0xE9, 0x00, 0x66, 0xD9, 0xF8, 0xA4, 0x52, 0x89, 0xB2, +0xA8, 0x47, 0x23, 0x69, 0x43, 0x44, 0x23, 0x61, 0x01, 0x27, 0xB8, 0xE7, 0xA2, 0x46, 0xDC, 0xE6, 0xB0, 0xDE, 0x17, 0x00, +0x00, 0x10, 0x50, 0x40, 0xC5, 0xD3, 0x14, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0xF8, 0xB5, 0x03, 0x88, 0x13, 0x4D, 0x13, 0xF4, 0x00, 0x6F, 0x04, 0x46, +0xC3, 0x8A, 0x0B, 0xD1, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x30, 0x68, 0xB2, 0x88, 0xBA, 0x80, 0x28, 0x66, +0xA5, 0xF8, 0x66, 0x30, 0x01, 0x20, 0xF8, 0xBD, 0xB5, 0xF8, 0x66, 0x20, 0x9A, 0x42, 0x04, 0xD0, 0x00, 0xF1, 0x0A, 0x06, +0x05, 0xF1, 0x60, 0x07, 0xEE, 0xE7, 0x05, 0xF1, 0x60, 0x07, 0x00, 0xF1, 0x0A, 0x06, 0x39, 0x46, 0x30, 0x46, 0x06, 0x22, +0x09, 0xF0, 0xC6, 0xF8, 0x00, 0x28, 0xEA, 0xD0, 0xE3, 0x8A, 0xE1, 0xE7, 0xB0, 0xDE, 0x17, 0x00, 0xF0, 0xB4, 0x01, 0xB3, +0x00, 0x22, 0x87, 0x7A, 0x94, 0x46, 0x07, 0xE0, 0x1E, 0x69, 0x1E, 0xB1, 0x01, 0x3C, 0xC3, 0xF8, 0x10, 0xC0, 0xC4, 0x72, +0x8D, 0x42, 0x09, 0xD2, 0xBB, 0x18, 0xC4, 0x7A, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x32, 0x00, 0xEB, 0x83, 0x03, 0x95, 0xB2, +0x00, 0x2C, 0xED, 0xD1, 0x03, 0x89, 0x0F, 0x44, 0x19, 0x44, 0x07, 0xF0, 0x3F, 0x07, 0xC1, 0xF3, 0x0B, 0x01, 0x87, 0x72, +0x01, 0x81, 0xF0, 0xBC, 0x70, 0x47, 0x87, 0x7A, 0xF2, 0xE7, 0x00, 0xBF, 0xF8, 0xB5, 0x83, 0x7A, 0x04, 0x33, 0x50, 0xF8, +0x23, 0x30, 0x53, 0xB3, 0xC1, 0x7A, 0x15, 0x4D, 0x15, 0x4F, 0x16, 0x4E, 0x04, 0x46, 0x15, 0xE0, 0xA3, 0x7A, 0x22, 0x89, +0x18, 0x1D, 0x01, 0x33, 0x03, 0xF0, 0x3F, 0x03, 0x01, 0x39, 0x4F, 0xF0, 0x00, 0x0C, 0x44, 0xF8, 0x20, 0xC0, 0xC9, 0xB2, +0x18, 0x1D, 0xA3, 0x72, 0xE1, 0x72, 0x54, 0xF8, 0x20, 0x00, 0x53, 0x1C, 0xC3, 0xF3, 0x0B, 0x03, 0x23, 0x81, 0x70, 0xB1, +0x2B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE4, 0xDA, 0x00, 0x29, 0xE2, 0xD1, 0x39, 0x46, 0x4F, 0xF4, 0xD6, 0x62, +0x30, 0x46, 0xF6, 0xF7, 0xF5, 0xFD, 0xE1, 0x7A, 0xDA, 0xE7, 0xF8, 0xBD, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x9E, 0x23, 0x0C, 0x8A, 0x38, 0x4A, 0x03, 0xFB, 0x00, 0xF0, 0x00, 0xEB, +0x14, 0x30, 0x02, 0xEB, 0x80, 0x00, 0xD0, 0xF8, 0x7C, 0x41, 0x4C, 0xB3, 0x94, 0xF8, 0x21, 0x31, 0x49, 0x8A, 0xC3, 0xB1, +0xEF, 0xF3, 0x10, 0x83, 0xDA, 0x07, 0x30, 0xD5, 0x30, 0x48, 0x31, 0x4D, 0x03, 0x68, 0x2E, 0x68, 0x03, 0xF0, 0x60, 0x42, +0x77, 0x1C, 0xB2, 0xF1, 0xC0, 0x4F, 0x2F, 0x60, 0x31, 0xD0, 0x2D, 0x4B, 0x80, 0x22, 0x1A, 0x60, 0x2F, 0xB1, 0x2C, 0x4B, +0x2E, 0x60, 0x1B, 0x68, 0x0E, 0xB9, 0x03, 0xB1, 0x62, 0xB6, 0x22, 0x89, 0xB2, 0xEB, 0x11, 0x1F, 0x4F, 0xEA, 0x11, 0x13, +0x06, 0xD0, 0x9B, 0x1A, 0x99, 0xB2, 0x1B, 0x05, 0x04, 0xD5, 0x94, 0xF8, 0x21, 0x31, 0x9B, 0xB1, 0xBD, 0xE8, 0xF0, 0x81, +0x22, 0x4D, 0x20, 0x46, 0xD5, 0xF8, 0xD8, 0x32, 0xC1, 0xF3, 0x0B, 0x01, 0x98, 0x47, 0xD5, 0xF8, 0x38, 0x31, 0x1F, 0x48, +0xBD, 0xE8, 0xF0, 0x41, 0x18, 0x47, 0x72, 0xB6, 0x1A, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0xC9, 0xE7, 0x1B, 0x48, 0xF6, 0xF7, +0x23, 0xFB, 0x01, 0x23, 0x84, 0xF8, 0x21, 0x31, 0xE4, 0xE7, 0x19, 0x4A, 0x03, 0xF4, 0xF0, 0x33, 0xD2, 0xF8, 0x00, 0xC0, +0xB3, 0xF5, 0xF0, 0x3F, 0x0C, 0xF1, 0x10, 0x0C, 0xC3, 0xD0, 0x96, 0x46, 0x03, 0x68, 0x03, 0xF0, 0x60, 0x42, 0xB2, 0xF1, +0xC0, 0x4F, 0x02, 0xD0, 0x10, 0x4B, 0x1B, 0x68, 0xB9, 0xE7, 0x03, 0xF4, 0xF0, 0x33, 0xB3, 0xF5, 0xF0, 0x3F, 0xF7, 0xD0, +0xDE, 0xF8, 0x00, 0x30, 0xA3, 0xEB, 0x0C, 0x03, 0x00, 0x2B, 0xEB, 0xDB, 0x00, 0x2F, 0xB6, 0xD0, 0xAF, 0xE7, 0x00, 0xBF, +0x68, 0x65, 0x17, 0x00, 0x04, 0x05, 0x32, 0x40, 0x6C, 0x28, 0x17, 0x00, 0x54, 0x00, 0x32, 0x40, 0x38, 0x61, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x7C, 0xC0, 0x15, 0x00, 0x20, 0x01, 0x32, 0x40, 0x2D, 0xE9, 0xF8, 0x43, +0x8D, 0x4F, 0x8E, 0x4B, 0xBC, 0x7A, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x04, 0x34, 0x80, 0x46, 0x94, 0xF8, 0xC3, 0x54, +0x89, 0x46, 0x00, 0x2D, 0x40, 0xF0, 0x90, 0x80, 0xF8, 0x79, 0x88, 0x49, 0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, +0x01, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, 0x9A, 0x42, 0x00, 0xF0, 0xA5, 0x80, 0xD2, 0x1A, 0x12, 0xF4, +0x7C, 0x6F, 0xC2, 0xF3, 0x0B, 0x03, 0x38, 0xD1, 0xA6, 0x7A, 0x1E, 0x44, 0x06, 0xF0, 0x3F, 0x06, 0x01, 0x23, 0x04, 0xEB, +0x86, 0x06, 0x84, 0xF8, 0x20, 0x31, 0x33, 0x69, 0x00, 0x2B, 0x6B, 0xD1, 0x8D, 0xB9, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, +0x32, 0x30, 0x77, 0x49, 0x42, 0xF0, 0x20, 0x02, 0xC8, 0xF8, 0x60, 0x20, 0x23, 0xF0, 0xFF, 0x03, 0xD1, 0xF8, 0xE8, 0x22, +0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0x71, 0x4B, 0x33, 0x61, 0xE3, 0x7A, 0x70, 0x4A, 0x01, 0x33, +0x12, 0x68, 0xDB, 0xB2, 0xE3, 0x72, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0xB1, 0x80, 0x01, 0x2B, 0x00, 0xF0, +0xB9, 0x80, 0xC5, 0xF1, 0x01, 0x05, 0xED, 0xB2, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xFE, 0xFE, 0x28, 0x46, 0xBD, 0xE8, +0xF8, 0x83, 0x40, 0xF2, 0xFE, 0x72, 0x93, 0x42, 0x40, 0xF2, 0x91, 0x80, 0x94, 0xF8, 0x20, 0x31, 0x13, 0xB1, 0x94, 0xF8, +0x21, 0x31, 0x9B, 0xB3, 0x3B, 0x88, 0x1B, 0x05, 0x21, 0xD4, 0x7A, 0x88, 0x4F, 0xF4, 0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, +0x01, 0xEB, 0x43, 0x03, 0xA3, 0xF8, 0xEA, 0x21, 0x15, 0xBB, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x55, 0x49, +0x42, 0xF0, 0x20, 0x02, 0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, +0x40, 0x46, 0x03, 0x21, 0x90, 0x47, 0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xCD, 0xFE, 0x01, 0x25, 0xCC, 0xE7, 0x4F, 0xF4, +0x9E, 0x73, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x43, 0x03, 0x7A, 0x88, 0xB3, 0xF8, 0xEA, 0x31, 0x93, 0x42, 0xD3, 0xD1, +0xF9, 0x79, 0x48, 0x46, 0x02, 0xF0, 0xBC, 0xFE, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0xC2, 0x69, 0x04, 0xF2, +0xC4, 0x41, 0x92, 0x68, 0x01, 0x23, 0x04, 0xF1, 0x63, 0x00, 0xFF, 0xF7, 0x3B, 0xF8, 0x05, 0x46, 0xF8, 0x79, 0x3B, 0x49, +0xBA, 0x88, 0x9E, 0x23, 0x03, 0xFB, 0x09, 0x03, 0x01, 0xEB, 0x83, 0x03, 0x01, 0x2D, 0xD3, 0xF8, 0x7C, 0x41, 0x23, 0x89, +0x60, 0xD0, 0x9A, 0x42, 0x09, 0xD0, 0xD2, 0x1A, 0x12, 0xF4, 0x7C, 0x6F, 0x4F, 0xF0, 0x00, 0x05, 0xC2, 0xF3, 0x0B, 0x03, +0x3F, 0xF4, 0x62, 0xAF, 0x99, 0xE7, 0xD8, 0xF8, 0x60, 0x20, 0xB8, 0xF8, 0x32, 0x30, 0x2E, 0x49, 0x42, 0xF0, 0x20, 0x02, +0x23, 0xF0, 0xFF, 0x03, 0xC8, 0xF8, 0x60, 0x20, 0xD1, 0xF8, 0xE8, 0x22, 0xA8, 0xF8, 0x32, 0x30, 0x40, 0x46, 0x03, 0x21, +0x90, 0x47, 0x23, 0x89, 0x01, 0x25, 0x01, 0x20, 0x28, 0x4A, 0xA1, 0x7A, 0x84, 0xF8, 0x20, 0x01, 0x12, 0x69, 0x62, 0x60, +0x04, 0xEB, 0x81, 0x00, 0x02, 0x69, 0x12, 0xB1, 0xE2, 0x7A, 0x01, 0x3A, 0xE2, 0x72, 0x5A, 0x1C, 0x01, 0x31, 0xC2, 0xF3, +0x0B, 0x02, 0x01, 0xF0, 0x3F, 0x01, 0x00, 0x23, 0x03, 0x61, 0x20, 0x46, 0x22, 0x81, 0xA1, 0x72, 0xFF, 0xF7, 0x4E, 0xFE, +0x62, 0xE7, 0x18, 0x4A, 0xA3, 0xF1, 0x3F, 0x01, 0x89, 0xB2, 0xD2, 0xF8, 0xD8, 0x32, 0x20, 0x46, 0x98, 0x47, 0xBB, 0x88, +0x21, 0x89, 0x5B, 0x1A, 0xC3, 0xF3, 0x0B, 0x03, 0x22, 0xE7, 0x40, 0x2B, 0x7F, 0xF6, 0x4C, 0xAF, 0x13, 0x49, 0x14, 0x48, +0x40, 0xF2, 0xDB, 0x72, 0xF6, 0xF7, 0x5A, 0xFC, 0xE3, 0x7A, 0x43, 0xE7, 0x0E, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, +0xE0, 0x31, 0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x3A, 0xE7, 0x9A, 0x42, 0x7F, 0xF4, +0x03, 0xAF, 0x00, 0x25, 0xB9, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x87, 0xA9, 0xDC, 0xFE, 0x38, 0x36, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, +0x90, 0xC0, 0x15, 0x00, 0xC3, 0x7A, 0x03, 0xB9, 0x70, 0x47, 0x1A, 0x4B, 0x42, 0x68, 0x1B, 0x69, 0xC3, 0xF5, 0x43, 0x43, +0x50, 0x33, 0xD3, 0x42, 0x10, 0xB5, 0x04, 0x46, 0x00, 0xD4, 0x10, 0xBD, 0x83, 0x7A, 0x1A, 0x1D, 0x50, 0xF8, 0x22, 0x20, +0x42, 0xB9, 0x02, 0x89, 0x01, 0x33, 0x01, 0x32, 0x03, 0xF0, 0x3F, 0x03, 0xC2, 0xF3, 0x0B, 0x02, 0x83, 0x72, 0x02, 0x81, +0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFD, 0xE3, 0x7A, 0x53, 0xB9, 0x0B, 0x4A, 0x0B, 0x4B, 0x11, 0x69, 0xD3, 0xF8, 0xE0, 0x31, +0x01, 0xF5, 0x43, 0x41, 0x04, 0xF5, 0x88, 0x70, 0x50, 0x31, 0x98, 0x47, 0x07, 0x48, 0x83, 0x6B, 0x00, 0x2B, 0xDC, 0xD0, +0x04, 0x4B, 0xBD, 0xE8, 0x10, 0x40, 0xD3, 0xF8, 0x38, 0x31, 0x38, 0x30, 0x18, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, +0x88, 0x1A, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x05, 0x46, +0x04, 0xD0, 0x03, 0x88, 0x03, 0xF0, 0xEC, 0x03, 0xC4, 0x2B, 0x11, 0xD0, 0x15, 0x4F, 0x05, 0xF1, 0x04, 0x08, 0x07, 0xF5, +0xA4, 0x56, 0xB9, 0x46, 0x3C, 0x46, 0x94, 0xF8, 0x64, 0x30, 0x1B, 0xB1, 0x94, 0xF8, 0x62, 0x30, 0x02, 0x2B, 0x06, 0xD0, +0x04, 0xF5, 0xA4, 0x64, 0xA6, 0x42, 0xF4, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x06, 0x22, 0x04, 0xF1, 0x5C, 0x01, +0x40, 0x46, 0x08, 0xF0, 0x45, 0xFE, 0xA4, 0xEB, 0x07, 0x0A, 0x00, 0x28, 0xEE, 0xD1, 0x07, 0x49, 0x07, 0x48, 0xF6, 0xF7, +0x4D, 0xF9, 0x05, 0xF1, 0x0A, 0x01, 0x09, 0xEB, 0x0A, 0x00, 0xFD, 0xF7, 0x49, 0xFD, 0xE7, 0xE7, 0x00, 0x88, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x20, 0xC1, 0x15, 0x00, 0xA8, 0xC0, 0x15, 0x00, 0x13, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x12, 0xB1, +0x11, 0xF4, 0x00, 0x71, 0x00, 0xD0, 0x70, 0x47, 0x10, 0xB4, 0x42, 0x89, 0xB3, 0xF8, 0x6C, 0x40, 0x94, 0x42, 0x02, 0xD0, +0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xB3, 0xF8, 0x6E, 0x40, 0x82, 0x89, 0x94, 0x42, 0xF7, 0xD1, 0xB3, 0xF8, 0x70, 0x40, +0xC2, 0x89, 0x94, 0x42, 0xF2, 0xD1, 0x02, 0x88, 0x02, 0xF4, 0xA0, 0x52, 0xB2, 0xF5, 0x80, 0x5F, 0x06, 0xBF, 0x01, 0x22, +0x83, 0xF8, 0x72, 0x20, 0x83, 0xF8, 0x72, 0x10, 0xE6, 0xE7, 0x00, 0xBF, 0xB0, 0xDE, 0x17, 0x00, 0xF8, 0xB5, 0xBD, 0xF8, +0x1C, 0x60, 0x06, 0x9D, 0xFF, 0x2A, 0x00, 0xEB, 0x06, 0x07, 0x2E, 0xD0, 0x14, 0x46, 0x82, 0x5D, 0x03, 0x3A, 0x12, 0x2A, +0x18, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x2B, 0x17, 0x0A, 0x17, 0x30, 0x49, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, +0x17, 0x17, 0x17, 0x17, 0x5C, 0x00, 0x1B, 0x78, 0x4B, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, +0x62, 0x30, 0x02, 0x2B, 0x02, 0xD0, 0x7B, 0x78, 0x00, 0x2B, 0x6A, 0xD0, 0x01, 0x26, 0x2B, 0x88, 0xFF, 0x2B, 0x0A, 0xD0, +0x44, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x57, 0xDB, 0x6F, 0xF0, 0xFF, 0x03, 0x2A, 0x88, 0x13, 0x43, +0x2B, 0x80, 0x30, 0x46, 0xF8, 0xBD, 0x01, 0x26, 0x30, 0x46, 0xF8, 0xBD, 0x08, 0x23, 0x2B, 0x80, 0x00, 0x26, 0x00, 0x23, +0xF2, 0xE7, 0x7E, 0x78, 0x00, 0x2E, 0x52, 0xD0, 0x01, 0x2E, 0xE1, 0xD1, 0x38, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x02, 0x06, 0xD9, 0xD0, 0xBE, 0x78, 0x16, 0xF0, 0x01, 0x06, 0x5A, 0xD0, 0x20, 0x46, +0x00, 0x22, 0xFF, 0x21, 0xF9, 0xF7, 0xDC, 0xFC, 0x00, 0x26, 0xCE, 0xE7, 0x89, 0x1B, 0x03, 0x29, 0x2A, 0xDD, 0x1B, 0x78, +0xFF, 0x2B, 0xC7, 0xD0, 0x29, 0x4A, 0x7E, 0x78, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x93, 0xF8, 0x62, 0x30, +0x1E, 0x43, 0xBD, 0xD1, 0x06, 0x23, 0x2B, 0x80, 0xD1, 0xE7, 0x7B, 0x78, 0x01, 0x2B, 0x36, 0xD0, 0x02, 0x2B, 0xB5, 0xD1, +0x22, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x23, 0x5E, 0x68, 0x16, 0xF0, 0x24, 0x06, 0xAD, 0xD0, 0x97, 0xF9, +0x02, 0x30, 0xB9, 0x78, 0x00, 0x2B, 0x07, 0xDB, 0x0A, 0x09, 0x20, 0x46, 0x01, 0xF0, 0x03, 0x01, 0xF9, 0xF7, 0xAE, 0xFC, +0x00, 0x26, 0xA0, 0xE7, 0x00, 0x26, 0x9E, 0xE7, 0x17, 0x49, 0x18, 0x48, 0x40, 0xF6, 0x78, 0x12, 0xF6, 0xF7, 0x00, 0xFB, +0x6F, 0xF0, 0xFF, 0x03, 0xA0, 0xE7, 0x0B, 0x23, 0x2B, 0x80, 0x01, 0x26, 0xA7, 0xE7, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x04, 0x23, 0x5B, 0x68, 0x9B, 0x07, 0x89, 0xD5, 0xB9, 0x78, 0x01, 0x29, 0x86, 0xD8, 0x20, 0x46, 0xFF, 0x22, +0xF9, 0xF7, 0x8E, 0xFC, 0x81, 0xE7, 0x07, 0xF1, 0x0A, 0x01, 0xB8, 0x1C, 0xD2, 0xF7, 0xB6, 0xFE, 0x00, 0x26, 0x7A, 0xE7, +0xFF, 0x22, 0x20, 0x46, 0x11, 0x46, 0xF9, 0xF7, 0x81, 0xFC, 0x74, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xBC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x89, 0xB0, 0x1F, 0x46, +0x10, 0x9E, 0x34, 0x78, 0xFF, 0x2C, 0x47, 0xD0, 0x69, 0x4D, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0x00, 0xF0, +0xFC, 0x04, 0x80, 0x2C, 0x95, 0xF8, 0x62, 0x80, 0x46, 0xD0, 0x0F, 0xD8, 0x40, 0x2C, 0x6B, 0xD0, 0x2C, 0xD9, 0x50, 0x2C, +0x4F, 0xF0, 0x01, 0x04, 0x04, 0xD1, 0x13, 0x9A, 0x14, 0x70, 0x12, 0x9A, 0x04, 0x23, 0x13, 0x80, 0x20, 0x46, 0x09, 0xB0, +0xBD, 0xE8, 0xF0, 0x83, 0xC0, 0x2C, 0x21, 0xD0, 0x10, 0xD9, 0xD0, 0x2C, 0x15, 0xD1, 0x13, 0x9B, 0x11, 0x98, 0xCD, 0xE9, +0x01, 0x23, 0x12, 0x9B, 0x00, 0x93, 0x3A, 0x46, 0x33, 0x46, 0xFF, 0xF7, 0x11, 0xFF, 0x04, 0x46, 0x20, 0x46, 0x09, 0xB0, +0xBD, 0xE8, 0xF0, 0x83, 0xA0, 0x2C, 0x0D, 0xD0, 0xB0, 0x2C, 0x02, 0xD1, 0xFC, 0xF7, 0xBA, 0xFA, 0x40, 0xB1, 0x01, 0x24, +0x20, 0x46, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x00, 0xF0, 0xDC, 0x00, 0x10, 0x28, 0xF6, 0xD1, 0xB8, 0xF1, 0x00, 0x0F, +0xF3, 0xD1, 0x12, 0x9A, 0x06, 0x23, 0x13, 0x80, 0x01, 0x24, 0xCF, 0xE7, 0x00, 0xF0, 0xFC, 0x00, 0xB0, 0x28, 0x72, 0xD0, +0x28, 0xD8, 0x40, 0x28, 0x2A, 0xD0, 0x80, 0x28, 0xE5, 0xD1, 0x00, 0x25, 0x04, 0x20, 0x05, 0x91, 0xF4, 0xF7, 0x34, 0xFC, +0x01, 0x28, 0x05, 0x99, 0x0E, 0xD1, 0x13, 0x9A, 0x3D, 0x4B, 0x10, 0x70, 0x12, 0x98, 0x1B, 0x68, 0x3A, 0x4D, 0x04, 0x22, +0x02, 0x80, 0x93, 0xF8, 0x6E, 0x41, 0x34, 0x70, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x04, 0x55, 0xFF, 0x2F, 0xCC, 0xD0, +0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xC8, 0xD0, 0x34, 0x4B, 0x30, 0x78, 0xD3, 0xF8, 0x54, 0x31, 0x11, 0x9A, 0x98, 0x47, +0x01, 0x24, 0xA1, 0xE7, 0xD0, 0x28, 0xA8, 0xD0, 0x01, 0x24, 0xBD, 0xE7, 0x2F, 0x4B, 0x9A, 0x7C, 0x00, 0x2A, 0xB8, 0xD0, +0x2E, 0x4A, 0x12, 0x68, 0x12, 0x78, 0x01, 0x3A, 0x01, 0x2A, 0xB2, 0xD8, 0x9D, 0x68, 0x00, 0x2D, 0xAF, 0xD0, 0x18, 0x39, +0x2A, 0x4F, 0x1F, 0xFA, 0x81, 0xF8, 0x01, 0x24, 0x02, 0xE0, 0x2D, 0x68, 0x00, 0x2D, 0x87, 0xD0, 0x95, 0xF8, 0x62, 0x30, +0x02, 0x2B, 0xF8, 0xD1, 0x95, 0xF8, 0x64, 0x30, 0x00, 0x2B, 0xF4, 0xD0, 0x95, 0xF8, 0xC0, 0x34, 0x00, 0x2B, 0xF0, 0xD1, +0x11, 0x9B, 0xB7, 0xF8, 0x00, 0x90, 0x03, 0xF1, 0x18, 0x00, 0x0D, 0xF1, 0x1E, 0x02, 0x41, 0x46, 0xF4, 0xF7, 0xFA, 0xFF, +0xA9, 0xF1, 0x24, 0x01, 0x06, 0x46, 0x89, 0xB2, 0x0D, 0xF1, 0x1F, 0x02, 0x19, 0x48, 0xF4, 0xF7, 0xF1, 0xFF, 0x9D, 0xF8, +0x1E, 0x30, 0x18, 0x49, 0x02, 0x36, 0x81, 0x46, 0x07, 0x22, 0x30, 0x46, 0x53, 0xB9, 0x11, 0x9B, 0x28, 0x46, 0x03, 0xF1, +0x0A, 0x01, 0xE1, 0xF7, 0xED, 0xFE, 0x00, 0x24, 0xCD, 0xE7, 0xFC, 0xF7, 0x2F, 0xFA, 0x74, 0xE7, 0x08, 0xF0, 0x7C, 0xFC, +0x00, 0x28, 0xC6, 0xD0, 0x9D, 0xF8, 0x1F, 0x30, 0x9D, 0xF8, 0x1E, 0x20, 0x9A, 0x42, 0xC0, 0xD1, 0x09, 0xF1, 0x02, 0x01, +0x30, 0x46, 0x08, 0xF0, 0x6F, 0xFC, 0x00, 0x28, 0xE3, 0xD0, 0xB8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0xA8, 0xBA, 0x17, 0x00, +0x88, 0x1A, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0x78, 0x36, 0x17, 0x00, 0x14, 0x2C, 0x17, 0x00, 0x38, 0x2A, 0x17, 0x00, +0x54, 0xBF, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xC6, 0x69, 0x8D, 0xB0, 0xD6, 0xF8, 0x08, 0x90, 0x01, 0x23, 0x8D, 0xF8, +0x24, 0x30, 0x04, 0x46, 0xB9, 0xF8, 0x00, 0x00, 0x10, 0xF4, 0x80, 0x60, 0x40, 0xF0, 0x8B, 0x80, 0xB9, 0xF8, 0x16, 0x70, +0x17, 0xF0, 0x0F, 0x07, 0x00, 0xF0, 0x89, 0x80, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xB9, 0xF8, 0x00, 0x30, 0x98, 0xF8, +0x08, 0x20, 0x04, 0x92, 0xDF, 0xF8, 0x08, 0xE2, 0xB4, 0xF8, 0x30, 0xA0, 0xBD, 0xF8, 0x10, 0x10, 0xAD, 0xF8, 0x16, 0x30, +0x4F, 0xF0, 0xFF, 0x0C, 0x18, 0x46, 0xAD, 0xF8, 0x26, 0xC0, 0xB3, 0x68, 0xDE, 0xF8, 0xE0, 0x92, 0x07, 0x93, 0x0D, 0xF1, +0x25, 0x0C, 0x01, 0x93, 0xCD, 0xF8, 0x0C, 0xC0, 0x72, 0x4B, 0x06, 0x91, 0x0D, 0xF1, 0x26, 0x0C, 0x0A, 0x46, 0x00, 0x93, +0x51, 0x46, 0x8D, 0xF8, 0x25, 0xB0, 0x80, 0xB2, 0xCD, 0xF8, 0x08, 0xC0, 0x2B, 0x46, 0xC8, 0x47, 0xBD, 0xF8, 0x26, 0x10, +0xFF, 0x29, 0x00, 0xF0, 0x90, 0x80, 0x0A, 0xF1, 0x0C, 0x03, 0x9B, 0xB2, 0x0A, 0x22, 0x4F, 0xF4, 0x20, 0x50, 0xF4, 0xF7, +0xB5, 0xF8, 0x59, 0x46, 0x81, 0x46, 0x0A, 0xA8, 0xD2, 0xF7, 0xFA, 0xFC, 0x9D, 0xF8, 0x25, 0x30, 0xD3, 0x46, 0x63, 0xB9, +0x61, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x04, 0x9B, 0x06, 0x9F, 0xAA, 0xEB, +0x03, 0x0B, 0x1F, 0xFA, 0x8B, 0xFA, 0x4B, 0x46, 0x3A, 0x46, 0x51, 0x46, 0x23, 0xF8, 0x0C, 0xAB, 0x30, 0x46, 0xE6, 0xF7, +0x35, 0xFD, 0x98, 0xF8, 0x0A, 0x30, 0x89, 0xF8, 0x08, 0x30, 0xBD, 0xF8, 0x16, 0x30, 0x89, 0xF8, 0x07, 0x50, 0xA9, 0xF8, +0x02, 0x30, 0x94, 0xF9, 0x41, 0x50, 0xD2, 0xF7, 0x75, 0xFD, 0x0A, 0x9B, 0x89, 0xF8, 0x06, 0x30, 0x1A, 0x0C, 0x89, 0xF8, +0x09, 0x50, 0xA9, 0xF8, 0x04, 0x20, 0x48, 0x46, 0xF4, 0xF7, 0xAE, 0xF8, 0xBD, 0xF8, 0x26, 0x30, 0x04, 0x2B, 0x10, 0xD1, +0xE1, 0x6B, 0xB9, 0xF8, 0x04, 0x30, 0x62, 0x6B, 0x07, 0x98, 0xC1, 0xF3, 0x03, 0x11, 0x02, 0x91, 0x99, 0xF9, 0x09, 0x10, +0x01, 0x91, 0x99, 0xF8, 0x06, 0x10, 0x00, 0x91, 0x59, 0x46, 0x07, 0xF0, 0x15, 0xFB, 0x00, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x0D, 0x46, 0xD2, 0xF7, 0x4E, 0xFD, 0xFF, 0x2D, 0x38, 0xD0, 0x3C, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x31, 0xD0, +0x99, 0xF8, 0x04, 0x30, 0xDF, 0xF8, 0xEC, 0x80, 0xDA, 0x07, 0x10, 0xD4, 0x98, 0xF8, 0x0A, 0x00, 0x37, 0x4A, 0xB9, 0xF8, +0x04, 0x10, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x00, 0xF3, 0x5C, 0x33, 0x98, 0x18, 0x9B, 0x5A, 0x8B, 0x42, 0x45, 0xD0, +0xFF, 0x23, 0x88, 0xF8, 0x0A, 0x30, 0x22, 0x8E, 0x30, 0x48, 0x09, 0xAB, 0x49, 0x46, 0x02, 0xF0, 0x81, 0xFB, 0x83, 0x46, +0x00, 0x28, 0x3F, 0xF4, 0x50, 0xAF, 0x9D, 0xF8, 0x24, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0x48, 0xAF, 0x2A, 0x4B, 0x20, 0x46, +0xD3, 0xF8, 0xE4, 0x32, 0x03, 0x21, 0x98, 0x47, 0x9D, 0xF8, 0x24, 0x00, 0x3E, 0xE7, 0x8D, 0xF8, 0x24, 0x00, 0xF0, 0xE7, +0xDF, 0xF8, 0x8C, 0x80, 0xE1, 0xE7, 0x63, 0x6D, 0x13, 0xF4, 0xC0, 0x6F, 0x1E, 0xD1, 0x1E, 0x4B, 0x9B, 0x68, 0x9B, 0xB3, +0xB9, 0xF8, 0x04, 0x10, 0x01, 0xE0, 0x1B, 0x68, 0xB3, 0xB1, 0xB3, 0xF8, 0x5C, 0x20, 0x8A, 0x42, 0xF9, 0xD1, 0xB3, 0xF8, +0x5E, 0x00, 0xB9, 0xF8, 0x06, 0x20, 0x90, 0x42, 0xF3, 0xD1, 0xB3, 0xF8, 0x60, 0x00, 0xB9, 0xF8, 0x08, 0x20, 0x90, 0x42, +0xED, 0xD1, 0x93, 0xF8, 0x63, 0x30, 0xDF, 0xF8, 0x4C, 0x80, 0x88, 0xF8, 0x0A, 0x30, 0xBE, 0xE7, 0xFF, 0x23, 0xF8, 0xE7, +0x42, 0x88, 0xB9, 0xF8, 0x06, 0x30, 0x9A, 0x42, 0xB4, 0xD1, 0x82, 0x88, 0xB9, 0xF8, 0x08, 0x30, 0x9A, 0x42, 0xAF, 0xD1, +0xB1, 0xE7, 0x04, 0x9A, 0x93, 0x07, 0x3F, 0xF4, 0x4E, 0xAF, 0x0A, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0x97, 0x22, 0xF6, 0xF7, +0xE7, 0xF8, 0x46, 0xE7, 0x2B, 0x46, 0xE0, 0xE7, 0xBA, 0xDE, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xD0, 0xC0, 0x15, 0x00, +0x1D, 0x48, 0x70, 0xB5, 0x00, 0xF1, 0x10, 0x06, 0xF4, 0xF7, 0x5E, 0xFC, 0x30, 0x46, 0x1B, 0x4C, 0xF4, 0xF7, 0x5A, 0xFC, +0x04, 0xF5, 0x92, 0x55, 0x21, 0x46, 0x30, 0x46, 0x04, 0xF5, 0x92, 0x74, 0xF4, 0xF7, 0x56, 0xFC, 0xAC, 0x42, 0xF7, 0xD1, +0x15, 0x48, 0xF4, 0xF7, 0x4D, 0xFC, 0x15, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, 0x14, 0x49, 0x12, 0x48, 0xF4, 0xF7, 0x4A, 0xFC, +0x13, 0x49, 0x10, 0x48, 0xF4, 0xF7, 0x46, 0xFC, 0x12, 0x49, 0x0E, 0x48, 0xF4, 0xF7, 0x42, 0xFC, 0x11, 0x4A, 0x12, 0x4B, +0x12, 0x48, 0x4F, 0xF6, 0xFF, 0x71, 0xA2, 0xF8, 0x66, 0x10, 0x03, 0xF5, 0x70, 0x51, 0x00, 0x22, 0x03, 0xF8, 0x34, 0x2C, +0x1A, 0x81, 0x43, 0xE9, 0x10, 0x03, 0x43, 0xF8, 0x30, 0x3C, 0x50, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0x70, 0xBD, 0x00, 0xBF, +0xE8, 0xDE, 0x17, 0x00, 0x70, 0xCC, 0x17, 0x00, 0x00, 0xDF, 0x17, 0x00, 0x08, 0xDF, 0x17, 0x00, 0x28, 0xDF, 0x17, 0x00, +0x6C, 0xDF, 0x17, 0x00, 0xB0, 0xDF, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x24, 0x64, 0x18, 0x00, 0x75, 0xD2, 0x14, 0x00, +0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, 0x00, 0x2B, 0x01, 0xF0, 0x78, 0x02, 0x05, 0x46, 0xB8, 0xBF, 0x1A, 0x23, +0x4F, 0xF0, 0x00, 0x00, 0xA8, 0xBF, 0x18, 0x23, 0x08, 0x2A, 0xAD, 0xF8, 0x06, 0x00, 0x19, 0xD0, 0x01, 0xF0, 0x7C, 0x01, +0x04, 0x29, 0x1F, 0xD0, 0x06, 0x33, 0xDC, 0xB2, 0x2E, 0x19, 0x31, 0x46, 0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, +0xF3, 0xFA, 0x28, 0x79, 0x10, 0xF0, 0x01, 0x00, 0x0B, 0xD0, 0xBD, 0xF8, 0x06, 0x00, 0xA0, 0xF5, 0xC1, 0x60, 0xB0, 0xFA, +0x80, 0xF0, 0x40, 0x09, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xE6, 0xE7, 0xBD, 0xF8, 0x06, 0x30, 0x08, 0x2B, +0x04, 0xD0, 0x01, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x04, 0x33, 0xDD, 0xE7, 0xF3, 0x7A, 0x02, 0x2B, 0xEE, 0xD0, 0x11, 0x2B, +0xF5, 0xD1, 0xB2, 0x78, 0xA3, 0x1C, 0x02, 0xF0, 0x0F, 0x04, 0x03, 0xEB, 0x84, 0x04, 0x2C, 0x44, 0x14, 0xF8, 0x04, 0x3C, +0xEF, 0x2B, 0xEA, 0xD1, 0x14, 0xF8, 0x03, 0x3C, 0xFF, 0x2B, 0xE6, 0xD1, 0x14, 0xF8, 0x02, 0x3C, 0xFF, 0x2B, 0xE2, 0xD1, +0x14, 0xF8, 0x01, 0x0C, 0xFA, 0x38, 0x18, 0xBF, 0x01, 0x20, 0xD3, 0xE7, 0x70, 0xB5, 0x90, 0xF9, 0x00, 0x30, 0x82, 0xB0, +0x00, 0x2B, 0x01, 0xF0, 0x78, 0x05, 0x4F, 0xF0, 0x00, 0x06, 0xB4, 0xBF, 0x1A, 0x23, 0x18, 0x23, 0x08, 0x2D, 0x14, 0x46, +0xAD, 0xF8, 0x06, 0x60, 0x13, 0xD0, 0x01, 0xF0, 0x7C, 0x01, 0x04, 0x29, 0x12, 0xD0, 0x99, 0x1D, 0x50, 0xFA, 0x81, 0xF1, +0x02, 0x22, 0x0D, 0xF1, 0x06, 0x00, 0x08, 0xF0, 0x9F, 0xFA, 0xBD, 0xF8, 0x06, 0x10, 0x48, 0xF6, 0x88, 0x63, 0x99, 0x42, +0x06, 0xD0, 0x02, 0xB0, 0x70, 0xBD, 0x08, 0x33, 0xDB, 0xB2, 0xEC, 0xE7, 0x04, 0x33, 0xEA, 0xE7, 0x02, 0x48, 0x22, 0x46, +0xF5, 0xF7, 0x6E, 0xFD, 0x02, 0xB0, 0x70, 0xBD, 0xEC, 0xC0, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x45, 0x6D, 0x2D, 0xED, +0x02, 0x8B, 0xAF, 0x04, 0x87, 0xB0, 0x04, 0x46, 0x1F, 0xD4, 0xC1, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9E, 0x07, 0x03, 0xD5, +0x05, 0xF0, 0x3C, 0x03, 0x3C, 0x2B, 0x16, 0xD0, 0xBD, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x71, 0xD0, 0xBC, 0x4E, 0xBD, 0x4D, +0xB3, 0x72, 0x20, 0x46, 0xD5, 0xF8, 0xE4, 0x32, 0x80, 0x21, 0x98, 0x47, 0x01, 0x27, 0xD5, 0xF8, 0x38, 0x31, 0xB9, 0x48, +0x98, 0x47, 0x38, 0x46, 0x07, 0xB0, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xD4, 0xF8, 0x1C, 0xA0, 0xB2, 0x4E, +0xDA, 0xF8, 0x08, 0x80, 0x00, 0x23, 0xB8, 0xF8, 0x00, 0x90, 0x23, 0x66, 0x40, 0x46, 0xFF, 0x23, 0x73, 0x72, 0xB3, 0x72, +0xFE, 0xF7, 0xE6, 0xFD, 0xA8, 0x01, 0x50, 0xD5, 0xC5, 0xF3, 0xC9, 0x37, 0xDF, 0xF8, 0xBC, 0xB2, 0x10, 0x3F, 0xFF, 0xB2, +0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x93, 0xF8, 0x25, 0x20, 0x00, 0x2A, 0x39, 0xD0, 0x93, 0xF8, 0x22, 0x10, +0xA5, 0x48, 0xD3, 0xF8, 0xB0, 0x30, 0x77, 0x72, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x02, 0xB5, 0x61, 0x92, 0xF8, +0x62, 0x20, 0xB1, 0x72, 0x02, 0x2A, 0x00, 0x93, 0x52, 0xD0, 0x09, 0xF4, 0x40, 0x73, 0xB3, 0xF5, 0x40, 0x7F, 0x03, 0xD1, +0x23, 0x6E, 0x43, 0xF0, 0x04, 0x03, 0x23, 0x66, 0x33, 0x88, 0x5B, 0x04, 0x00, 0xF1, 0x90, 0x80, 0x98, 0x4B, 0x1B, 0x68, +0x1B, 0x78, 0x01, 0x2B, 0x09, 0xF0, 0x0C, 0x03, 0x00, 0xF0, 0x90, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x4F, 0xF4, +0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x92, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0x40, 0xF2, 0xE7, 0x80, 0x04, 0x2B, 0x00, 0xF0, +0xFA, 0x80, 0x08, 0x2B, 0x00, 0xF0, 0x97, 0x80, 0x00, 0x2B, 0x33, 0xD0, 0x85, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x01, 0xD0, +0x85, 0x4D, 0x8F, 0xE7, 0x84, 0x4D, 0x00, 0x27, 0x93, 0xE7, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x9D, 0xFB, 0x19, 0xF0, +0x0C, 0x0F, 0x0B, 0xD1, 0xFF, 0xF7, 0xDA, 0xF8, 0x00, 0x28, 0xEB, 0xD0, 0x33, 0x88, 0x59, 0x04, 0x55, 0xD5, 0x05, 0xF0, +0x7C, 0x03, 0x04, 0x2B, 0x4B, 0xD0, 0x40, 0x46, 0x21, 0x46, 0xFF, 0xF7, 0x4D, 0xFB, 0x78, 0x4D, 0x07, 0x46, 0x75, 0x4B, +0x1B, 0x7C, 0xFF, 0x2B, 0x3F, 0xF4, 0x77, 0xAF, 0x00, 0x2F, 0x7F, 0xF4, 0x74, 0xAF, 0x6B, 0xE7, 0x96, 0xF8, 0x24, 0x30, +0xDA, 0x07, 0xA8, 0xD4, 0x06, 0xF1, 0x24, 0x00, 0xF2, 0xF7, 0xB8, 0xFE, 0xF0, 0x72, 0xA2, 0xE7, 0x19, 0xF4, 0x00, 0x6F, +0x00, 0xF0, 0xCF, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x72, 0x88, 0xB3, 0xF8, 0xE8, 0x31, 0x93, 0x42, +0xBE, 0xD0, 0x96, 0xF8, 0x30, 0x10, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB7, 0x8D, 0x07, 0xA7, 0xF8, 0xE8, 0x21, +0x0A, 0xD5, 0x35, 0x6A, 0xD6, 0xE9, 0x04, 0x01, 0xD5, 0xE9, 0x10, 0x23, 0x8B, 0x42, 0x08, 0xBF, 0x82, 0x42, 0xAB, 0xD2, +0xC5, 0xE9, 0x10, 0x01, 0x5F, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD1, 0x98, 0xF8, 0x00, 0x30, 0x80, 0x2B, +0x00, 0xF0, 0xCF, 0x80, 0x71, 0x7A, 0x57, 0x4D, 0x20, 0x46, 0xFF, 0xF7, 0x17, 0xFD, 0x07, 0x46, 0xB9, 0xE7, 0x29, 0x46, +0x40, 0x46, 0xFE, 0xF7, 0x39, 0xFB, 0x00, 0x28, 0xAD, 0xD0, 0xFF, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x0B, 0xFD, 0x4F, 0x4D, +0x07, 0x46, 0xAC, 0xE7, 0xB1, 0x69, 0x40, 0x46, 0xFE, 0xF7, 0x2C, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x69, 0xAF, 0x83, 0xE7, +0x08, 0x2B, 0x7F, 0xF4, 0x70, 0xAF, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x73, 0xFE, 0x00, 0x28, 0x3F, 0xF4, 0x7A, 0xAF, +0x3B, 0x46, 0x22, 0x8E, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xC0, 0xFE, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, +0x93, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x40, 0xF2, 0x87, 0x80, 0x41, 0x4B, 0x93, 0xF8, 0x04, 0x31, 0x73, 0xB1, 0xB3, 0x7A, +0x3C, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x03, 0x13, 0x93, 0xF8, 0x62, 0x20, 0x2A, 0xB9, 0xD3, 0xF8, 0x90, 0x21, +0x92, 0x78, 0x01, 0x2A, 0x00, 0xF0, 0x8D, 0x80, 0x19, 0xF0, 0x40, 0x03, 0x00, 0x93, 0x7F, 0xF4, 0x53, 0xAF, 0x09, 0xF0, +0x80, 0x03, 0x00, 0x2B, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x08, 0x4F, 0xF0, 0x00, 0x08, 0x71, 0xD0, 0x96, 0xF8, 0x30, 0x30, +0x1A, 0x07, 0x40, 0xF1, 0x9A, 0x80, 0xF2, 0x79, 0x4F, 0xF4, 0x9E, 0x73, 0xF5, 0x32, 0x03, 0xFB, 0x07, 0x23, 0x0B, 0xEB, +0x43, 0x03, 0x19, 0xF4, 0x00, 0x6F, 0x72, 0x88, 0x03, 0xD0, 0x19, 0x88, 0x91, 0x42, 0x3F, 0xF4, 0x35, 0xAF, 0x1F, 0x49, +0x1A, 0x80, 0x0B, 0x68, 0x1B, 0x78, 0x9B, 0x07, 0x04, 0xD5, 0x05, 0xF0, 0x3C, 0x05, 0x3C, 0x2D, 0x00, 0xF0, 0x8E, 0x80, +0x1C, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xC4, 0x32, 0x42, 0x46, 0x20, 0x46, 0x98, 0x47, 0x07, 0x46, 0x41, 0xE7, 0x00, 0x9A, +0x00, 0x2A, 0x3F, 0xF4, 0x15, 0xAF, 0x92, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x3F, 0xF6, 0x0F, 0xAF, 0x19, 0xF4, +0x80, 0x4F, 0x3F, 0xF4, 0x0B, 0xAF, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x07, 0xB2, 0x02, 0x21, 0x82, 0xF8, 0x5D, 0x12, +0x02, 0xE7, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, 0x84, 0x0F, 0x7F, 0xF4, 0x05, 0xAF, 0x0A, 0x4D, 0x41, 0x46, 0xD5, 0xF8, +0xD0, 0x32, 0x38, 0x46, 0x98, 0x47, 0x05, 0x4B, 0x1B, 0x7C, 0xFF, 0x2B, 0x7F, 0xF4, 0x90, 0xAE, 0xFF, 0xE6, 0x72, 0x88, +0x37, 0xE7, 0x00, 0xBF, 0x34, 0x36, 0x17, 0x00, 0x00, 0x88, 0x17, 0x00, 0xB0, 0xDE, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0xE8, 0xDE, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x74, 0x36, 0x17, 0x00, 0x2C, 0x19, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x00, 0x9B, 0x00, 0x2B, 0x3F, 0xF4, 0x75, 0xAF, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x3F, 0xF6, 0x6F, 0xAF, +0x08, 0x23, 0xC0, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x07, 0xB3, 0x03, 0xF5, 0xF4, 0x73, 0x93, 0xE7, 0x98, 0xF8, +0x01, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x2C, 0xAF, 0xCA, 0xE6, 0xD3, 0xF8, 0xCC, 0x21, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, +0x6D, 0xAF, 0x98, 0xF8, 0x04, 0x20, 0xD0, 0x07, 0x3F, 0xF5, 0x68, 0xAF, 0xE2, 0x6B, 0x12, 0xF0, 0x0C, 0x0F, 0x3F, 0xF4, +0x63, 0xAF, 0xD3, 0xF8, 0x90, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x90, 0x20, 0x98, 0xF8, 0x01, 0x20, 0x11, 0x07, 0x7F, 0xF5, +0x59, 0xAF, 0xD3, 0xF8, 0x94, 0x20, 0x01, 0x32, 0xC3, 0xF8, 0x94, 0x20, 0x52, 0xE7, 0xF1, 0x79, 0x38, 0x46, 0xE9, 0xF7, +0x33, 0xFB, 0x00, 0x28, 0x3F, 0xF4, 0x5F, 0xAF, 0x61, 0x4D, 0x39, 0x46, 0xD5, 0xF8, 0xD4, 0x32, 0x20, 0x46, 0x98, 0x47, +0x07, 0x46, 0xBC, 0xE6, 0x33, 0x6A, 0x01, 0x93, 0x93, 0xF8, 0x60, 0x10, 0x01, 0x29, 0x03, 0xF1, 0x64, 0x09, 0x64, 0xD0, +0x00, 0x29, 0x40, 0xF0, 0x97, 0x80, 0x08, 0xF1, 0x0E, 0x03, 0x5B, 0x00, 0xDA, 0xE9, 0x01, 0x25, 0x58, 0x19, 0x08, 0xEE, +0x10, 0x0A, 0x00, 0x2A, 0x52, 0xD0, 0xDA, 0xF8, 0x0C, 0x20, 0x20, 0x8E, 0x01, 0x32, 0x52, 0x1B, 0x04, 0x30, 0xD2, 0x1A, +0xC0, 0x1A, 0x93, 0xB2, 0x82, 0xB2, 0x9A, 0x42, 0x00, 0x92, 0x28, 0xBF, 0x1A, 0x46, 0x15, 0x46, 0x01, 0x29, 0x2F, 0xD0, +0x00, 0x29, 0x50, 0xD0, 0x03, 0x29, 0x66, 0xD0, 0x18, 0xEE, 0x10, 0x0A, 0x29, 0x46, 0xF3, 0xF7, 0x2F, 0xFB, 0x4F, 0xF0, +0xFF, 0x33, 0x18, 0xEE, 0x10, 0x0A, 0x03, 0x22, 0x29, 0x46, 0xD6, 0xF7, 0x29, 0xFF, 0xDA, 0xF8, 0x04, 0x30, 0x23, 0xB1, +0x00, 0x9A, 0x55, 0x1B, 0xAD, 0xB2, 0x00, 0x2D, 0x67, 0xD1, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x30, 0x13, 0xB1, 0x03, 0x2B, +0x7F, 0xF4, 0x2C, 0xAF, 0x03, 0x20, 0xD6, 0xF7, 0x4F, 0xFF, 0x3A, 0x4B, 0x98, 0x42, 0x01, 0x46, 0x3F, 0xD1, 0x63, 0x6D, +0x23, 0xF0, 0x7C, 0x03, 0x43, 0xF4, 0x00, 0x53, 0x43, 0xF0, 0x04, 0x03, 0x63, 0x65, 0x1B, 0xE7, 0x4F, 0xF4, 0x1E, 0x72, +0x02, 0xFB, 0x07, 0xB2, 0x02, 0xAB, 0x32, 0x49, 0x26, 0x32, 0x48, 0x46, 0xF3, 0xF7, 0xDA, 0xF8, 0x10, 0x21, 0x02, 0xA8, +0xF3, 0xF7, 0x9A, 0xFA, 0x01, 0x9B, 0x93, 0xF8, 0x60, 0x10, 0xBD, 0xE7, 0x22, 0x8E, 0x04, 0x32, 0xD3, 0x1A, 0x9D, 0xB2, +0xB6, 0xE7, 0xD6, 0xE9, 0x04, 0x53, 0x28, 0x48, 0x2A, 0x0C, 0x42, 0xEA, 0x03, 0x42, 0x08, 0xF1, 0x10, 0x03, 0x02, 0x60, +0x85, 0x80, 0x5B, 0x00, 0x94, 0xE7, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, 0x08, 0x20, 0x49, 0x46, 0x05, 0x22, 0x0D, 0xF1, +0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x1F, 0xF8, 0x08, 0x21, 0x02, 0xA8, 0xF3, 0xF7, 0x75, 0xFA, 0x01, 0x9B, +0x93, 0xF8, 0x60, 0x10, 0x9A, 0xE7, 0x1A, 0x48, 0xF5, 0xF7, 0xF4, 0xFA, 0x0A, 0xE6, 0x32, 0x8A, 0x73, 0x8A, 0xAD, 0xF8, +0x08, 0x20, 0x49, 0x46, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x8D, 0xF8, 0x0A, 0x30, 0x08, 0xF0, 0x07, 0xF8, 0x02, 0xA8, +0x10, 0x21, 0xF3, 0xF7, 0x5D, 0xFA, 0x87, 0xE7, 0x03, 0x29, 0x3F, 0xF4, 0x66, 0xAF, 0x00, 0x23, 0x66, 0xE7, 0xD3, 0xF8, +0x08, 0x90, 0x29, 0x46, 0x48, 0x46, 0xF3, 0xF7, 0xB1, 0xFA, 0x03, 0x20, 0xD6, 0xF7, 0xE8, 0xFE, 0x20, 0x21, 0xC0, 0x43, +0xF3, 0xF7, 0x64, 0xF8, 0x29, 0x46, 0x03, 0x46, 0x03, 0x22, 0x48, 0x46, 0xD6, 0xF7, 0xA6, 0xFE, 0x83, 0xE7, 0x00, 0xBF, +0x88, 0x1A, 0x17, 0x00, 0x1C, 0xDF, 0x44, 0x21, 0x88, 0x34, 0x17, 0x00, 0x00, 0xC1, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x00, 0xEB, 0x81, 0x04, 0xD4, 0xF8, 0x7C, 0x61, 0x16, 0xB1, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x81, 0x15, 0x48, 0x0D, 0x46, +0x17, 0x46, 0xF4, 0xF7, 0x1B, 0xF9, 0x80, 0x46, 0x00, 0x28, 0xF4, 0xD0, 0x31, 0x46, 0x4F, 0xF4, 0x92, 0x72, 0xD1, 0xF7, +0x3B, 0xF8, 0x07, 0xF0, 0x3F, 0x02, 0x0F, 0x4B, 0x88, 0xF8, 0x0C, 0x50, 0x88, 0xF8, 0x0A, 0x20, 0x19, 0x69, 0x0D, 0x4B, +0xC8, 0xF8, 0x04, 0x10, 0xD3, 0xF8, 0xDC, 0x22, 0xA8, 0xF8, 0x08, 0x70, 0xC8, 0xE9, 0x45, 0x28, 0x01, 0xF5, 0x43, 0x41, +0xC4, 0xF8, 0x7C, 0x81, 0x08, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xE0, 0x31, 0x50, 0x31, 0x98, 0x47, 0x01, 0x20, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0xBF, 0xF8, 0xDE, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x10, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0xEB, 0x81, 0x04, 0x00, 0x2B, 0xD4, 0xF8, 0x7C, 0x51, 0x0D, 0xDB, 0x0C, 0x4B, +0x05, 0xF5, 0x88, 0x70, 0xD3, 0xF8, 0xD8, 0x31, 0x98, 0x47, 0x0A, 0x48, 0x29, 0x46, 0xF4, 0xF7, 0x95, 0xF8, 0x00, 0x23, +0xC4, 0xF8, 0x7C, 0x31, 0x38, 0xBD, 0x00, 0x2D, 0xEF, 0xD1, 0x06, 0x49, 0x06, 0x48, 0x40, 0xF6, 0x7F, 0x52, 0xF5, 0xF7, +0xDD, 0xFC, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xF8, 0xDE, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x10, 0xC1, 0x15, 0x00, 0x08, 0x4B, 0x93, 0xF8, 0x73, 0x20, 0x62, 0xB9, 0x02, 0x88, 0xA3, 0xF8, 0x6C, 0x20, 0x42, 0x88, +0xA3, 0xF8, 0x6E, 0x20, 0x82, 0x88, 0xA3, 0xF8, 0x70, 0x20, 0x4F, 0xF4, 0x80, 0x72, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, +0xB0, 0xDE, 0x17, 0x00, 0x03, 0x4B, 0x00, 0x22, 0x93, 0xF8, 0x72, 0x00, 0xA3, 0xF8, 0x72, 0x20, 0x70, 0x47, 0x00, 0xBF, +0xB0, 0xDE, 0x17, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF3, 0xF7, 0xDD, 0xFF, 0x03, 0x4B, 0x03, 0x48, 0xD3, 0xF8, +0x38, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x88, 0x1A, 0x17, 0x00, 0xE8, 0xDE, 0x17, 0x00, 0x06, 0x4B, 0x07, 0x4A, +0x93, 0xF8, 0x44, 0x30, 0x03, 0xEB, 0x83, 0x03, 0x02, 0xEB, 0x03, 0x13, 0xB3, 0xF8, 0x4C, 0x00, 0xB0, 0xFA, 0x80, 0xF0, +0x40, 0x09, 0x70, 0x47, 0xB0, 0xDE, 0x17, 0x00, 0xE0, 0x63, 0x18, 0x00, 0xF8, 0xB5, 0x55, 0x4F, 0x46, 0x7F, 0x05, 0x7F, +0x54, 0x4A, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x06, 0x74, 0xD4, 0xE9, 0x2C, 0xC3, 0x4F, 0xF4, 0xA4, 0x6E, 0x0E, 0xFB, +0x05, 0x25, 0x1B, 0x68, 0xD5, 0xF8, 0xA8, 0xE4, 0x00, 0x22, 0x0A, 0x60, 0x4B, 0xB3, 0xBE, 0xF1, 0x00, 0x0F, 0x26, 0xD0, +0xD5, 0xF8, 0xB0, 0x54, 0xAA, 0x07, 0x06, 0xD5, 0x05, 0x8B, 0xB4, 0xF8, 0x34, 0xE0, 0x6C, 0xBA, 0xA4, 0xB2, 0xA6, 0x45, +0x1B, 0xD0, 0xBC, 0xF1, 0x00, 0x0F, 0x04, 0xD0, 0x9C, 0xF8, 0x60, 0x20, 0x01, 0x3A, 0x01, 0x2A, 0x1C, 0xD9, 0x93, 0xF8, +0x60, 0x20, 0x04, 0x2A, 0x04, 0xD8, 0xDF, 0xE8, 0x02, 0xF0, 0x10, 0x20, 0x27, 0x10, 0x3C, 0x00, 0x3D, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x04, 0xDA, 0x3B, 0x49, 0x3C, 0x48, 0xC4, 0x22, 0xF5, 0xF7, 0x53, 0xFC, 0x00, 0x20, +0xF8, 0xBD, 0xC2, 0x8B, 0x04, 0x24, 0xD5, 0x07, 0x0C, 0x60, 0x54, 0xD5, 0x20, 0x46, 0xF8, 0xBD, 0x4F, 0xF4, 0x1E, 0x72, +0x02, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x5D, 0x22, 0x01, 0x2A, 0xDA, 0xD8, 0xED, 0xE7, 0xC2, 0x8B, 0x0C, 0x24, 0x0C, 0x60, +0xD4, 0x07, 0x35, 0xD5, 0x08, 0x20, 0xF8, 0xBD, 0xC2, 0x8B, 0x08, 0x24, 0x0C, 0x60, 0xD1, 0x07, 0xF8, 0xD4, 0xD3, 0xE9, +0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x67, 0x06, 0x22, +0x38, 0x30, 0x07, 0xF0, 0xCD, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0xC2, 0x8B, 0x10, 0x24, 0xD2, 0x07, 0x0C, 0x60, 0x13, 0xD4, +0x93, 0xF8, 0x62, 0x20, 0x0F, 0x2A, 0xD3, 0xE9, 0x12, 0x21, 0x0F, 0xD9, 0x02, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x14, 0x46, +0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x08, 0x22, 0x38, 0x30, 0x07, 0xF0, 0xB4, 0xFE, 0x12, 0x20, 0xF8, 0xBD, +0x12, 0x20, 0xF8, 0xBD, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0xEE, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, +0x00, 0x01, 0x14, 0x46, 0x0D, 0x46, 0x19, 0x46, 0xE1, 0xE9, 0x12, 0x45, 0x06, 0x22, 0x38, 0x30, 0x07, 0xF0, 0x9E, 0xFE, +0xBA, 0xE7, 0xD3, 0xE9, 0x12, 0x21, 0x01, 0x32, 0x41, 0xF1, 0x00, 0x01, 0x16, 0x46, 0x0F, 0x46, 0x19, 0x46, 0xE1, 0xE9, +0x12, 0x67, 0x22, 0x46, 0x38, 0x30, 0x07, 0xF0, 0x8F, 0xFE, 0x20, 0x46, 0xF8, 0xBD, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF0, 0xB5, 0xC3, 0x8B, +0x04, 0x46, 0xD8, 0x07, 0x83, 0xB0, 0x44, 0xD4, 0xE0, 0x7E, 0x66, 0x7F, 0x22, 0x7F, 0xFF, 0x28, 0x44, 0xD0, 0x4F, 0xF4, +0x9E, 0x71, 0x01, 0xFB, 0x06, 0x01, 0x21, 0x48, 0x98, 0x31, 0x00, 0xEB, 0x41, 0x01, 0x1A, 0x25, 0x8F, 0x88, 0x78, 0x1C, +0xC0, 0xF3, 0x0B, 0x00, 0x88, 0x80, 0x27, 0x84, 0xD9, 0x05, 0x1C, 0x4B, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x02, 0x33, +0x48, 0xBF, 0x06, 0x35, 0x93, 0xF8, 0x62, 0x30, 0x43, 0xB9, 0x16, 0x4B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x06, 0x36, +0x73, 0x68, 0x9B, 0x06, 0x48, 0xBF, 0x04, 0x35, 0x01, 0xA9, 0x84, 0xF8, 0x32, 0x50, 0x20, 0x46, 0xFF, 0xF7, 0x16, 0xFF, +0x23, 0x8B, 0xA2, 0x88, 0x22, 0x86, 0x5B, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, 0xC0, 0x6F, 0x28, 0x44, 0x88, 0xBF, 0x08, 0x30, +0xC0, 0xB2, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x8C, 0xBF, 0x08, 0x21, 0x00, 0x21, 0x84, 0xF8, 0x42, 0x00, 0x84, 0xF8, +0x34, 0x10, 0x84, 0xF8, 0x35, 0x30, 0x00, 0x23, 0xC4, 0xE9, 0x09, 0x33, 0x03, 0xB0, 0xF0, 0xBD, 0x18, 0x25, 0xC7, 0xE7, +0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x1D, 0xA0, 0xDF, 0xF8, 0x58, 0x92, +0x90, 0xF8, 0x1C, 0x80, 0x92, 0x4F, 0x4F, 0xF4, 0x1E, 0x76, 0x06, 0xFB, 0x0A, 0xF6, 0x09, 0xEB, 0x06, 0x02, 0x4F, 0xF4, +0xA4, 0x64, 0x04, 0xFB, 0x08, 0x74, 0xD2, 0xF8, 0xB4, 0x30, 0x94, 0xF8, 0x62, 0xC0, 0xD3, 0xF8, 0x00, 0xB0, 0xD2, 0xF8, +0xB0, 0x30, 0x83, 0xB0, 0x05, 0x46, 0x01, 0x93, 0xD4, 0xF8, 0xA8, 0x34, 0x00, 0x93, 0x0C, 0x46, 0xBC, 0xF1, 0x00, 0x0F, +0x40, 0xF0, 0x8D, 0x80, 0x53, 0x68, 0x13, 0xF0, 0x20, 0x03, 0x40, 0xF0, 0x9F, 0x80, 0xE9, 0x7E, 0xB5, 0xF8, 0x1E, 0xC0, +0xFF, 0x29, 0x0C, 0xBF, 0xA4, 0xF1, 0x18, 0x00, 0xA4, 0xF1, 0x1A, 0x00, 0x1C, 0xF4, 0x80, 0x72, 0x1D, 0xBF, 0x06, 0x38, +0x00, 0xF1, 0x1E, 0x04, 0x02, 0x46, 0x00, 0xF1, 0x18, 0x04, 0xFF, 0x29, 0x00, 0xF0, 0x94, 0x80, 0x6F, 0xF0, 0x7F, 0x0C, +0x4F, 0xF0, 0x00, 0x0E, 0x80, 0xF8, 0x00, 0xC0, 0x80, 0xF8, 0x01, 0xE0, 0x21, 0x80, 0x29, 0x8C, 0xB5, 0xF8, 0x1E, 0xC0, +0x09, 0x01, 0x1C, 0xF4, 0x00, 0x7F, 0xC1, 0x82, 0x63, 0xD1, 0x01, 0x88, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, +0x00, 0x6F, 0x01, 0x80, 0x69, 0xD0, 0x23, 0xF4, 0x40, 0x71, 0x41, 0xF0, 0x08, 0x01, 0x89, 0xB2, 0x01, 0x80, 0x4F, 0xF4, +0xA4, 0x64, 0x1C, 0xF0, 0x04, 0x0F, 0x04, 0xFB, 0x08, 0xF4, 0x18, 0xBF, 0x41, 0xF4, 0x00, 0x51, 0x04, 0xF1, 0x5C, 0x03, +0x18, 0xBF, 0x01, 0x80, 0x07, 0xEB, 0x03, 0x0C, 0xFB, 0x5A, 0x43, 0x81, 0xBC, 0xF8, 0x02, 0x30, 0x83, 0x81, 0x01, 0xF4, +0x40, 0x71, 0xBC, 0xF8, 0x04, 0x30, 0xC3, 0x81, 0xB1, 0xF5, 0x80, 0x7F, 0x5C, 0xD0, 0xB1, 0xF5, 0x00, 0x7F, 0x76, 0xD0, +0x00, 0x29, 0x40, 0xF0, 0x81, 0x80, 0xAB, 0x89, 0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x04, 0xF5, +0xB2, 0x74, 0x3B, 0x5B, 0x03, 0x82, 0x3C, 0x44, 0x63, 0x88, 0x43, 0x82, 0xA3, 0x88, 0x83, 0x82, 0xBB, 0xF1, 0x00, 0x0F, +0x1C, 0xD0, 0x00, 0x9B, 0xD3, 0xB1, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x77, 0xD7, 0xF8, 0xB0, 0x34, 0x9B, 0x07, +0x0A, 0xD5, 0x6A, 0x7F, 0x2B, 0x8B, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x02, 0x92, 0x5B, 0xBA, 0x92, 0x8E, 0x9B, 0xB2, +0x9A, 0x42, 0x07, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x7B, 0xD0, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, 0x01, 0x2B, 0x6E, 0xD9, +0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x23, 0x75, 0xE7, 0x21, 0x88, 0x41, 0xF0, 0x10, 0x01, 0x21, 0x80, 0x01, 0x88, +0xB5, 0xF8, 0x1E, 0xC0, 0x0B, 0x43, 0x43, 0xF0, 0x08, 0x01, 0x1C, 0xF4, 0x00, 0x6F, 0x01, 0x80, 0x95, 0xD1, 0x1C, 0xF4, +0x80, 0x7F, 0x22, 0xD0, 0x43, 0xF4, 0x42, 0x71, 0x01, 0x80, 0x94, 0xE7, 0x32, 0x4B, 0x11, 0x46, 0xD3, 0xF8, 0xB8, 0x33, +0x98, 0x47, 0x4F, 0xF4, 0x00, 0x43, 0x44, 0xF8, 0x04, 0x0D, 0x56, 0xE7, 0x00, 0x21, 0x81, 0x75, 0xC1, 0x75, 0x7A, 0xE7, +0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x20, 0x82, 0x80, 0x5A, 0x88, 0xC2, 0x80, 0x9B, 0x88, 0x03, 0x81, +0xAB, 0x89, 0x03, 0x82, 0xEB, 0x89, 0x43, 0x82, 0x2B, 0x8A, 0x83, 0x82, 0xA6, 0xE7, 0x4F, 0xF4, 0xA4, 0x64, 0x04, 0xFB, +0x08, 0x74, 0x94, 0xF8, 0x62, 0x40, 0x00, 0x2C, 0x27, 0xD1, 0x43, 0xF4, 0x84, 0x71, 0x01, 0x80, 0x69, 0xE7, 0xAB, 0x89, +0x83, 0x80, 0xEB, 0x89, 0xC3, 0x80, 0x2B, 0x8A, 0x03, 0x81, 0x6B, 0x8A, 0x03, 0x82, 0xAB, 0x8A, 0x43, 0x82, 0xEB, 0x8A, +0x83, 0x82, 0x8D, 0xE7, 0x26, 0x36, 0x09, 0xEB, 0x06, 0x03, 0x39, 0xF8, 0x06, 0x10, 0x91, 0x80, 0x59, 0x88, 0xD1, 0x80, +0x9B, 0x88, 0x13, 0x81, 0xAB, 0x89, 0x13, 0x82, 0xEB, 0x89, 0x53, 0x82, 0x2B, 0x8A, 0x93, 0x82, 0x6B, 0x8A, 0x13, 0x83, +0xAB, 0x8A, 0x53, 0x83, 0xEB, 0x8A, 0x93, 0x83, 0x76, 0xE7, 0x02, 0x2C, 0x04, 0xBF, 0x43, 0xF4, 0x02, 0x71, 0x01, 0x80, +0x3F, 0xE7, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x0A, 0x99, 0x99, 0xF8, 0x5D, 0x32, 0x01, 0x2B, 0x88, 0xD9, 0x03, 0x88, +0x43, 0xF4, 0x80, 0x43, 0x03, 0x80, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, +0x68, 0x65, 0x17, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x06, 0x46, 0x54, 0x48, 0x75, 0x7F, 0x34, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x05, 0x03, 0x89, 0x46, 0xD3, 0xF8, 0xB4, 0x70, 0xD7, 0xF8, 0x00, 0x80, 0xB8, 0xF1, 0x00, 0x0F, 0x4C, 0xD0, +0x17, 0x46, 0x4D, 0x4A, 0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x04, 0x24, 0xD4, 0xF8, 0xA8, 0x24, 0x00, 0x2A, 0x42, 0xD0, +0xD4, 0xF8, 0xB0, 0x24, 0x92, 0x07, 0x05, 0xD5, 0x32, 0x8B, 0x99, 0x8E, 0x53, 0xBA, 0x9B, 0xB2, 0x99, 0x42, 0x38, 0xD0, +0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0x05, 0xD5, 0xF8, 0xB0, 0x30, 0x23, 0xB1, 0x93, 0xF8, 0x60, 0x30, 0x01, 0x3B, +0x01, 0x2B, 0x40, 0xD9, 0x98, 0xF8, 0x60, 0x30, 0x04, 0x2B, 0x67, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x2A, 0x03, 0x40, 0x2A, +0x49, 0x00, 0x32, 0x8F, 0x42, 0xF4, 0x00, 0x53, 0x03, 0xF4, 0xFE, 0x43, 0x43, 0xEA, 0x12, 0x23, 0x29, 0xF8, 0x08, 0x3C, +0x96, 0xF8, 0x38, 0x30, 0x98, 0xF8, 0x61, 0x20, 0xA9, 0xF1, 0x08, 0x09, 0x43, 0xEA, 0x82, 0x33, 0x43, 0xF4, 0x00, 0x53, +0xA9, 0xF8, 0x02, 0x30, 0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xC7, 0xB1, 0xF2, 0x6A, +0xD4, 0x68, 0x2B, 0x4B, 0x98, 0xF8, 0x62, 0x00, 0x23, 0x40, 0x03, 0x43, 0xD3, 0x60, 0x48, 0x46, 0xBD, 0xE8, 0xF8, 0x83, +0x33, 0x8F, 0x29, 0xF8, 0x04, 0x3C, 0x98, 0xF8, 0x61, 0x20, 0x73, 0x8F, 0xA9, 0xF1, 0x04, 0x09, 0x43, 0xEA, 0x82, 0x33, +0xA9, 0xF8, 0x02, 0x30, 0x00, 0x2F, 0xE6, 0xD1, 0xB2, 0x6C, 0x28, 0x32, 0xE4, 0xE7, 0x95, 0xF8, 0x5D, 0x32, 0x01, 0x2B, +0xBA, 0xD8, 0xE6, 0xE7, 0x33, 0x8F, 0x29, 0xF8, 0x08, 0x3C, 0x98, 0xF8, 0x61, 0x30, 0xA9, 0xF1, 0x08, 0x09, 0x9B, 0x03, +0xCA, 0xE7, 0x98, 0xF8, 0x61, 0x30, 0x29, 0xF8, 0x12, 0x3C, 0xA9, 0xF1, 0x12, 0x09, 0x33, 0x8F, 0xA9, 0xF8, 0x02, 0x30, +0x73, 0x8F, 0xA9, 0xF8, 0x04, 0x30, 0xB3, 0x8F, 0xA9, 0xF8, 0x06, 0x30, 0xF3, 0x8F, 0xA9, 0xF8, 0x08, 0x30, 0x45, 0xF6, +0x36, 0x43, 0xA9, 0xF8, 0x0A, 0x30, 0xA9, 0xF8, 0x0C, 0x30, 0xA9, 0xF8, 0x0E, 0x30, 0xA9, 0xF8, 0x10, 0x30, 0xB7, 0xE7, +0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xB1, 0xDA, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0xD9, 0x22, +0xF5, 0xF7, 0xA8, 0xF9, 0xAA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x00, 0xFC, 0x0F, 0x00, +0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x70, 0xB5, 0x1A, 0x4D, 0x1A, 0x4E, 0xD5, 0xF8, +0x68, 0x32, 0x04, 0x46, 0x98, 0x47, 0x60, 0x7F, 0xD5, 0xF8, 0x5C, 0x31, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x00, 0x60, +0x98, 0x47, 0xE3, 0x8B, 0xE0, 0x62, 0x99, 0x04, 0x11, 0xD5, 0x63, 0x7F, 0x05, 0xFB, 0x03, 0x66, 0xD6, 0xF8, 0x4C, 0x31, +0xD3, 0xF8, 0x9C, 0x20, 0xA2, 0x62, 0x93, 0xF8, 0xA1, 0x30, 0x2B, 0xB1, 0x94, 0xF8, 0x36, 0x30, 0x43, 0xF0, 0x20, 0x03, +0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x94, 0xF8, 0x36, 0x30, 0x03, 0xF0, 0x03, 0x02, 0x00, 0xEB, 0x82, 0x00, 0x42, 0x6A, +0x41, 0x69, 0xA1, 0x62, 0x52, 0x03, 0x44, 0xBF, 0x43, 0xF0, 0x20, 0x03, 0x84, 0xF8, 0x36, 0x30, 0x70, 0xBD, 0x00, 0xBF, +0x88, 0x1A, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0xC3, 0x7E, 0x00, 0x93, 0x04, 0x46, 0xC3, 0x8B, +0x0F, 0x46, 0x16, 0x46, 0x16, 0x49, 0x02, 0x8C, 0x20, 0x20, 0xF4, 0xF7, 0x29, 0xFF, 0xE3, 0x8B, 0xD9, 0x07, 0x1E, 0xD5, +0x13, 0x48, 0xF4, 0xF7, 0xD3, 0xFE, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x03, 0xD4, 0x72, 0xB6, 0x10, 0x4B, 0x01, 0x22, +0x1A, 0x60, 0x10, 0x4D, 0x2B, 0x68, 0x3A, 0x46, 0x01, 0x33, 0x31, 0x46, 0x20, 0x46, 0x2B, 0x60, 0xDF, 0xF7, 0x4A, 0xFD, +0x2B, 0x68, 0x33, 0xB1, 0x09, 0x4A, 0x01, 0x3B, 0x12, 0x68, 0x2B, 0x60, 0x0B, 0xB9, 0x02, 0xB1, 0x62, 0xB6, 0x03, 0xB0, +0xF0, 0xBD, 0xDF, 0xF7, 0x61, 0xF9, 0xE3, 0x8B, 0xDA, 0x07, 0xDB, 0xD4, 0xDD, 0xE7, 0x00, 0xBF, 0x3C, 0xC1, 0x15, 0x00, +0x58, 0xC1, 0x15, 0x00, 0x38, 0x61, 0x17, 0x00, 0x6C, 0x28, 0x17, 0x00, 0x02, 0x8B, 0x53, 0xBA, 0x9B, 0xB2, 0xB3, 0xF5, +0xC0, 0x6F, 0x10, 0xB5, 0x04, 0x46, 0x08, 0xD3, 0x4A, 0xF6, 0xAA, 0x23, 0x21, 0xF8, 0x08, 0x3D, 0x03, 0x20, 0x00, 0x23, +0xCA, 0x80, 0x48, 0x80, 0x8B, 0x80, 0x20, 0x46, 0x01, 0x22, 0xFF, 0xF7, 0xBB, 0xFE, 0x04, 0x4B, 0x01, 0x46, 0xD3, 0xF8, +0x20, 0x34, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x18, 0x47, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0xC5, 0x8B, 0xDF, 0xF8, 0x7C, 0x82, 0x07, 0x7F, 0x4F, 0xF4, 0xA4, 0x6A, 0x0E, 0x46, 0x29, 0x07, 0x83, 0xB0, 0x04, 0x46, +0x0A, 0xFB, 0x07, 0x8A, 0x6B, 0xD4, 0x41, 0x7F, 0xDF, 0xF8, 0x64, 0xB2, 0x03, 0x8B, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, +0x01, 0xB1, 0x5B, 0xBA, 0x88, 0x8E, 0x91, 0xF8, 0x30, 0x20, 0x9B, 0xB2, 0x98, 0x42, 0x0F, 0xD0, 0x02, 0x2A, 0x16, 0xD0, +0x8B, 0x49, 0x20, 0x20, 0xF4, 0xF7, 0xB4, 0xFE, 0x20, 0x46, 0x31, 0x46, 0x4F, 0xF0, 0x00, 0x42, 0xFF, 0xF7, 0x78, 0xFF, +0x00, 0x20, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x01, 0x3A, 0x25, 0xF4, 0x80, 0x75, 0x01, 0x2A, 0xE5, 0x83, 0x02, 0xD9, +0x91, 0xF8, 0x30, 0x20, 0xE8, 0xE7, 0xDF, 0xF8, 0x1C, 0x92, 0x20, 0x46, 0xD9, 0xF8, 0x2C, 0x34, 0x98, 0x47, 0x63, 0x7F, +0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, 0x03, 0xBB, 0x9B, 0xF8, 0x30, 0x30, 0x02, 0x2B, 0x00, 0xF0, 0xA2, 0x80, 0x4F, 0xF4, +0xA4, 0x63, 0x03, 0xFB, 0x07, 0x87, 0x77, 0x4A, 0x3B, 0x6C, 0x77, 0x49, 0x1F, 0x79, 0x77, 0x4B, 0x00, 0x2F, 0x0C, 0xBF, +0x0F, 0x46, 0x17, 0x46, 0xE7, 0x62, 0x7D, 0x69, 0x93, 0xF8, 0xBD, 0x20, 0xC5, 0xF3, 0xC2, 0x28, 0xED, 0xB2, 0x00, 0x2A, +0x40, 0xF0, 0xB4, 0x80, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x01, 0xAA, 0x0D, 0xF1, 0x03, 0x01, 0x98, 0x47, 0x05, 0xF0, +0x7C, 0x03, 0x58, 0xEA, 0x03, 0x03, 0x0C, 0xBF, 0x9D, 0xF8, 0x03, 0x30, 0x9D, 0xF8, 0x04, 0x30, 0x43, 0xEA, 0x03, 0x23, +0x7B, 0x62, 0xE3, 0x8B, 0xDB, 0x07, 0x4C, 0xD4, 0xA1, 0x6C, 0xD9, 0xF8, 0x1C, 0x34, 0xA8, 0x31, 0x20, 0x46, 0x98, 0x47, +0x45, 0xE0, 0x00, 0x23, 0xEA, 0x06, 0x01, 0x93, 0x5B, 0xD5, 0x5D, 0x4B, 0xE3, 0x62, 0x15, 0xF0, 0x80, 0x05, 0x7D, 0xD1, +0xA8, 0x46, 0xDF, 0xF8, 0x80, 0x91, 0x5B, 0x4F, 0xD9, 0xF8, 0x38, 0x33, 0x50, 0x46, 0x0D, 0xF1, 0x03, 0x02, 0x0D, 0xF1, +0x02, 0x01, 0x98, 0x47, 0xE2, 0x6A, 0x4F, 0xF0, 0x00, 0x0A, 0xA3, 0x68, 0x02, 0xEB, 0x8A, 0x00, 0x23, 0xF0, 0x60, 0x41, +0x13, 0xF0, 0x80, 0x4F, 0x41, 0xF0, 0x00, 0x51, 0x14, 0xBF, 0x41, 0x61, 0x43, 0x69, 0x97, 0xF8, 0xBD, 0x10, 0xC3, 0xF3, +0xC2, 0x20, 0x03, 0xF0, 0x7F, 0x03, 0x51, 0xBB, 0x08, 0xBB, 0x03, 0x2B, 0x02, 0xEB, 0x8A, 0x01, 0x1D, 0xD8, 0x9D, 0xF8, +0x02, 0x30, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x04, 0x0F, 0xDD, 0xD1, 0x00, 0x23, +0xC4, 0xE9, 0x09, 0x33, 0x01, 0x9A, 0x84, 0xF8, 0x32, 0x80, 0x84, 0xF8, 0x33, 0x50, 0x84, 0xF8, 0x42, 0x50, 0x84, 0xF8, +0x35, 0x20, 0xD9, 0xF8, 0x94, 0x33, 0x31, 0x46, 0x20, 0x46, 0x98, 0x47, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x9D, 0xF8, +0x03, 0x30, 0x02, 0xEB, 0x8A, 0x01, 0x43, 0xEA, 0x03, 0x23, 0x4B, 0x62, 0xDE, 0xE7, 0x19, 0x46, 0xD1, 0xF7, 0xF0, 0xFD, +0xE2, 0x6A, 0x02, 0xEB, 0x8A, 0x03, 0x40, 0xEA, 0x00, 0x20, 0x58, 0x62, 0xD4, 0xE7, 0x9A, 0xF8, 0xC0, 0x34, 0x00, 0x2B, +0x9F, 0xD1, 0xDA, 0xF8, 0x40, 0x20, 0x2D, 0x4B, 0x11, 0x79, 0x2B, 0x4A, 0x00, 0x29, 0x18, 0xBF, 0x13, 0x46, 0xC3, 0x62, +0x97, 0xE7, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x07, 0x83, 0x93, 0xF8, 0x62, 0x20, 0x52, 0xB3, 0x02, 0x2A, 0x04, 0xD1, +0x9B, 0xF8, 0x70, 0x32, 0x00, 0x2B, 0x7F, 0xF4, 0x50, 0xAF, 0x24, 0x4B, 0x1B, 0x78, 0x1B, 0xB9, 0xD9, 0xF8, 0x1C, 0x30, +0x20, 0x46, 0x98, 0x47, 0x20, 0x46, 0xFF, 0xF7, 0x67, 0xFE, 0x6E, 0xE7, 0x00, 0x22, 0xC0, 0x21, 0x20, 0x46, 0x01, 0xF0, +0x1D, 0xFB, 0x01, 0x28, 0x1C, 0xD0, 0x02, 0x28, 0x15, 0xD0, 0xE3, 0x8B, 0x00, 0x25, 0x23, 0xF0, 0x80, 0x03, 0xE3, 0x83, +0xA8, 0x46, 0x72, 0xE7, 0x05, 0xF0, 0x7F, 0x01, 0x40, 0x46, 0xD1, 0xF7, 0xAD, 0xFD, 0x40, 0xEA, 0x00, 0x20, 0x78, 0x62, +0x55, 0xE7, 0x93, 0xF8, 0xAC, 0x30, 0x00, 0x2B, 0x7F, 0xF4, 0x27, 0xAF, 0xD5, 0xE7, 0x12, 0x23, 0x00, 0x25, 0x01, 0x93, +0xA8, 0x46, 0x5E, 0xE7, 0x01, 0xA9, 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFB, 0xA3, 0x6C, 0x05, 0x46, 0x03, 0xF1, 0xA8, 0x01, +0x03, 0xF1, 0xA0, 0x00, 0x18, 0x22, 0x07, 0xF0, 0x75, 0xFA, 0xED, 0xB2, 0x4F, 0xF0, 0x18, 0x08, 0x4D, 0xE7, 0x00, 0xBF, +0x70, 0xC1, 0x15, 0x00, 0x84, 0x3C, 0x18, 0x00, 0xC4, 0x3C, 0x18, 0x00, 0x2C, 0x19, 0x17, 0x00, 0xB8, 0x34, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x51, 0x4A, 0x43, 0x7F, +0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x03, 0x23, 0x86, 0xB0, 0xD3, 0xF8, 0xB4, 0x30, 0x1E, 0x68, 0x8E, 0xB1, 0x90, 0xF8, +0x35, 0x30, 0x04, 0x46, 0x6B, 0xB1, 0x90, 0xF8, 0x34, 0x30, 0x85, 0x6C, 0x96, 0xF8, 0x60, 0x20, 0xED, 0x1A, 0x01, 0x2A, +0x05, 0xF1, 0xA8, 0x05, 0x06, 0xD0, 0x03, 0x2A, 0x51, 0xD0, 0x00, 0x2A, 0x4F, 0xD0, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, +0x07, 0x8E, 0x42, 0x4A, 0x00, 0x91, 0x3B, 0x44, 0x06, 0xF1, 0x50, 0x01, 0xD2, 0xF8, 0x7C, 0x73, 0x2A, 0x46, 0xB8, 0x47, +0x3E, 0x4B, 0x1B, 0x68, 0x1B, 0x78, 0x9A, 0x07, 0xED, 0xD5, 0x96, 0xF8, 0x60, 0x20, 0x01, 0x2A, 0x06, 0xF1, 0x64, 0x08, +0x3E, 0xD1, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x0C, 0x33, 0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, +0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0xD8, 0xF8, 0xD6, 0xE9, 0x12, 0x03, 0x32, 0x49, 0x94, 0xF8, 0x1C, 0xC0, 0x88, 0x80, +0x31, 0x4A, 0x00, 0x0C, 0x4F, 0xF4, 0xA4, 0x6E, 0x40, 0xEA, 0x03, 0x40, 0x0E, 0xFB, 0x0C, 0x22, 0x08, 0x60, 0x02, 0xAB, +0x40, 0x46, 0xF2, 0xF7, 0x9F, 0xFA, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x5F, 0xFC, 0x96, 0xF8, 0x60, 0x20, 0xCA, 0xB1, +0x03, 0x2A, 0x17, 0xD0, 0x03, 0x20, 0xD6, 0xF7, 0xF1, 0xF8, 0x39, 0x46, 0x02, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x84, 0xFA, +0x39, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x7A, 0xFC, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x1D, 0x4B, 0x1B, 0x68, 0x1B, 0x78, +0x9B, 0x07, 0xAA, 0xD5, 0x06, 0xF1, 0x64, 0x08, 0x00, 0x27, 0xE4, 0xE7, 0x23, 0x8E, 0x94, 0xF8, 0x34, 0x70, 0x04, 0x33, +0x1F, 0x44, 0xBF, 0xB2, 0x39, 0x1F, 0x4F, 0xF0, 0xFF, 0x33, 0x03, 0x22, 0x28, 0x46, 0xD6, 0xF7, 0x97, 0xF8, 0x96, 0xF8, +0x60, 0x30, 0xB6, 0xF8, 0x48, 0x10, 0xB6, 0xF8, 0x4A, 0x20, 0xAD, 0xF8, 0x08, 0x10, 0x8D, 0xF8, 0x0A, 0x20, 0x41, 0x46, +0x4B, 0xB9, 0x05, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xCA, 0xF9, 0x02, 0xA8, 0x08, 0x21, 0xF2, 0xF7, 0x20, 0xFC, +0xC4, 0xE7, 0x0D, 0x22, 0x0D, 0xF1, 0x0B, 0x00, 0x07, 0xF0, 0xC0, 0xF9, 0x02, 0xA8, 0x10, 0x21, 0xF2, 0xF7, 0x16, 0xFC, +0xBA, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x34, 0x36, 0x17, 0x00, 0xA0, 0x34, 0x17, 0x00, +0x74, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0xC5, 0x6C, 0xC3, 0x8B, 0x2F, 0x69, 0x02, 0x8C, 0x2A, 0x81, 0x00, 0x26, +0x13, 0xF0, 0x08, 0x02, 0x2E, 0x61, 0x04, 0x46, 0x07, 0xF4, 0x00, 0x06, 0x88, 0x46, 0x07, 0xF0, 0x40, 0x47, 0x1C, 0xD0, +0x99, 0x06, 0x01, 0xD5, 0x00, 0x2E, 0x6C, 0xD0, 0x9A, 0x05, 0x3E, 0xD4, 0xB7, 0xF1, 0x40, 0x4F, 0x20, 0xD0, 0xE3, 0x7E, +0xFF, 0x2B, 0x22, 0xD1, 0x2B, 0x69, 0x62, 0x6A, 0x01, 0x20, 0x02, 0xF4, 0x00, 0x12, 0x16, 0xB1, 0x43, 0xF0, 0x08, 0x03, +0x2B, 0x61, 0x00, 0x2A, 0x47, 0xD0, 0x43, 0xF0, 0x01, 0x03, 0x28, 0x73, 0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0x9B, 0x05, +0xE6, 0xD5, 0x43, 0x7F, 0x2A, 0x49, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, 0x03, 0x13, 0xB7, 0xF1, 0x40, 0x4F, 0x83, 0xF8, +0x32, 0x20, 0xDE, 0xD1, 0x2B, 0x69, 0x43, 0xF0, 0x04, 0x03, 0x2B, 0x61, 0xDD, 0xE7, 0x31, 0x1E, 0x42, 0x46, 0x18, 0xBF, +0x01, 0x21, 0x20, 0x46, 0x01, 0xF0, 0x3A, 0xF8, 0x63, 0x6A, 0x13, 0xF4, 0x00, 0x12, 0x20, 0xD0, 0x03, 0xF4, 0x60, 0x13, +0xB3, 0xF5, 0x60, 0x1F, 0x01, 0xD0, 0x00, 0x23, 0x6B, 0x73, 0x2B, 0x69, 0x00, 0x2E, 0xD2, 0xD0, 0xCC, 0xE7, 0x19, 0x4B, +0x60, 0x7F, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x1A, 0xDB, 0x00, 0x23, 0x1A, 0x46, 0x17, 0x21, 0xE0, 0xF7, +0x0D, 0xFA, 0x12, 0x4A, 0x63, 0x7F, 0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x03, 0x23, 0x00, 0x22, 0x83, 0xF8, 0x32, 0x20, +0xAA, 0xE7, 0x2B, 0x69, 0x0E, 0xB1, 0x43, 0xF0, 0x08, 0x03, 0x01, 0x22, 0x43, 0xF0, 0x01, 0x03, 0x6A, 0x73, 0x28, 0x73, +0x2B, 0x61, 0xBD, 0xE8, 0xF0, 0x81, 0xFF, 0x28, 0xE2, 0xD1, 0x08, 0x48, 0x08, 0x49, 0x4F, 0xF4, 0xA4, 0x62, 0xF4, 0xF7, +0x89, 0xFE, 0x60, 0x7F, 0xDA, 0xE7, 0xFF, 0xF7, 0xC7, 0xF9, 0xE3, 0x8B, 0x8E, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, +0x38, 0x36, 0x17, 0x00, 0x84, 0xC1, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0x70, 0xB5, 0x90, 0xF8, 0x33, 0x30, 0x82, 0xB0, +0x04, 0x46, 0x0D, 0x46, 0x16, 0x46, 0x7B, 0xB1, 0x90, 0xF8, 0x35, 0x20, 0x01, 0x92, 0x18, 0x46, 0x2B, 0x88, 0x2E, 0x44, +0x43, 0xF4, 0x80, 0x43, 0x31, 0x18, 0x2B, 0x80, 0x20, 0x46, 0x00, 0x22, 0xFF, 0xF7, 0x12, 0xFC, 0x02, 0xB0, 0x70, 0xBD, +0x01, 0xA9, 0xFF, 0xF7, 0xCD, 0xF9, 0x01, 0x9B, 0x84, 0xF8, 0x33, 0x00, 0x84, 0xF8, 0x35, 0x30, 0xEA, 0xE7, 0x00, 0xBF, +0x10, 0xB4, 0x0C, 0x88, 0x0B, 0x46, 0x44, 0xF4, 0x80, 0x44, 0x11, 0x44, 0x1C, 0x80, 0x00, 0x22, 0x5D, 0xF8, 0x04, 0x4B, +0xFF, 0xF7, 0xFA, 0xBB, 0xF0, 0xB5, 0x00, 0x22, 0x18, 0x4C, 0x85, 0xB0, 0x05, 0x46, 0x0F, 0x46, 0x02, 0xE0, 0x01, 0x32, +0x20, 0x2A, 0x26, 0xD0, 0xA5, 0x42, 0x96, 0xB2, 0x04, 0xF1, 0x18, 0x04, 0xF7, 0xD1, 0x12, 0x02, 0x02, 0xF4, 0x7F, 0x42, +0x42, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xF6, 0xFF, 0x04, 0x28, 0x18, 0xD1, 0x17, 0xF4, 0x00, 0x03, 0x02, 0xD1, 0xEA, 0x7C, +0x02, 0x2A, 0x06, 0xD9, 0x28, 0x7B, 0x31, 0x46, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x40, 0x00, 0xF0, 0x65, 0xBC, 0x08, 0x49, +0x01, 0x32, 0xEA, 0x74, 0x27, 0x22, 0xCD, 0xE9, 0x01, 0x21, 0x00, 0x93, 0x28, 0x7B, 0x02, 0x22, 0x29, 0x46, 0x00, 0xF0, +0xBB, 0xFC, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, 0x2D, 0xE9, 0xF0, 0x43, +0x10, 0x46, 0x85, 0xB0, 0x14, 0x46, 0x0F, 0x46, 0xF2, 0xF7, 0xCC, 0xFF, 0x03, 0x28, 0x09, 0xD0, 0x50, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x72, 0xDB, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x4C, 0x4E, 0x4F, 0xEA, +0x14, 0x28, 0x08, 0xEB, 0x48, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x96, 0xF8, 0x0D, 0x90, 0xB9, 0xF1, 0x00, 0x0F, 0x39, 0xD0, +0xB9, 0xF1, 0x01, 0x0F, 0x29, 0xD1, 0xBB, 0x78, 0x00, 0x2B, 0x7C, 0xD1, 0x05, 0x46, 0x30, 0x46, 0x96, 0xF8, 0x0F, 0x90, +0x00, 0xF0, 0xA0, 0xFF, 0x41, 0x4B, 0x1B, 0x69, 0x73, 0x60, 0x05, 0x22, 0x2B, 0x46, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, +0x3D, 0x78, 0x7F, 0x78, 0xF2, 0xF7, 0xFA, 0xFC, 0xA9, 0xF1, 0x04, 0x09, 0x4F, 0xFA, 0x89, 0xF9, 0x80, 0xF8, 0x02, 0x90, +0x05, 0x70, 0x47, 0x70, 0xF2, 0xF7, 0x20, 0xFD, 0x73, 0x89, 0x00, 0x2B, 0x39, 0xD1, 0x20, 0x46, 0x01, 0x21, 0xF2, 0xF7, +0xE3, 0xFE, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x2F, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xBC, 0xDA, 0x2F, 0x49, 0x2F, 0x48, 0x40, 0xF2, 0x29, 0x12, 0xF4, 0xF7, 0xD3, 0xFD, 0xB5, 0xE7, 0xBA, 0x78, 0x33, 0x7C, +0x72, 0xBB, 0xB0, 0x7B, 0xF1, 0x7B, 0x02, 0x92, 0x9B, 0x00, 0x43, 0xEA, 0x40, 0x03, 0x43, 0xEA, 0x81, 0x13, 0xCD, 0xE9, +0x00, 0x32, 0x31, 0x46, 0x73, 0x7C, 0x30, 0x7B, 0x01, 0x22, 0x00, 0xF0, 0x47, 0xFC, 0x3B, 0x78, 0x7D, 0x78, 0x23, 0x4A, +0x1F, 0x48, 0x71, 0x89, 0x03, 0xEB, 0x83, 0x07, 0xC3, 0xEB, 0x07, 0x13, 0x2B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x83, 0xF8, +0xA4, 0x81, 0x03, 0x69, 0x73, 0x60, 0x00, 0x29, 0xC5, 0xD0, 0x40, 0x46, 0x00, 0xF0, 0x9A, 0xFB, 0xC1, 0xE7, 0x17, 0x49, +0x17, 0x48, 0xC8, 0x22, 0xF4, 0xF7, 0xA4, 0xFD, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0xB1, 0x7B, 0xF2, 0x7B, +0xCD, 0xF8, 0x08, 0x90, 0x9B, 0x00, 0x43, 0xEA, 0x41, 0x03, 0x43, 0xEA, 0x82, 0x13, 0x25, 0x22, 0xCD, 0xE9, 0x00, 0x32, +0x31, 0x46, 0x30, 0x7B, 0x73, 0x7C, 0x01, 0x22, 0x00, 0xF0, 0x16, 0xFC, 0x49, 0x46, 0x20, 0x46, 0xF2, 0xF7, 0x8A, 0xFE, +0x6C, 0xE7, 0x40, 0x46, 0x00, 0xF0, 0xF8, 0xFA, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x82, 0xFE, 0x64, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, +0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x8B, 0x78, 0x02, 0x2B, 0x01, 0xD0, 0x00, 0x20, 0xF8, 0xBD, 0x02, 0xF4, 0x7F, 0x40, +0x40, 0xF0, 0x08, 0x00, 0x0C, 0x46, 0x15, 0x0A, 0xF2, 0xF7, 0x0E, 0xFF, 0x04, 0x28, 0xF3, 0xD1, 0x11, 0x4E, 0x05, 0xEB, +0x45, 0x03, 0x06, 0xEB, 0xC3, 0x06, 0x73, 0x7B, 0x01, 0x2B, 0x04, 0xD0, 0x0E, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, +0xE6, 0xE7, 0x70, 0x69, 0x00, 0xF0, 0x1E, 0xFF, 0xF3, 0x7B, 0x67, 0x78, 0x26, 0x78, 0xC3, 0xF1, 0x04, 0x03, 0x1C, 0x18, +0x05, 0x22, 0x03, 0x23, 0x0C, 0x21, 0x41, 0xF2, 0x0B, 0x40, 0xF2, 0xF7, 0x4D, 0xFC, 0x64, 0xB2, 0x84, 0x70, 0x06, 0x70, +0x47, 0x70, 0xF2, 0xF7, 0x77, 0xFC, 0xE3, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0xB7, 0x4F, 0xCE, 0x79, 0xB7, 0x4A, 0x4F, 0xF4, 0x1E, 0x75, 0x05, 0xFB, 0x06, 0x75, 0x0C, 0x46, 0x95, 0xF8, 0x22, 0x30, +0x4F, 0xF4, 0xA4, 0x61, 0x01, 0xFB, 0x03, 0x23, 0x85, 0xB0, 0x93, 0xF8, 0x64, 0x30, 0x1B, 0xB9, 0x00, 0x20, 0x05, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x20, 0x94, 0xF8, 0x0D, 0x80, 0xF2, 0xF7, 0xC7, 0xFE, 0x09, 0x28, 0x04, 0xF1, 0x0C, 0x09, +0xF2, 0xD0, 0xB8, 0xF1, 0x01, 0x0F, 0x5B, 0xD0, 0xB8, 0xF1, 0x02, 0x0F, 0x1B, 0xD0, 0xB8, 0xF1, 0x00, 0x0F, 0xE9, 0xD1, +0xB9, 0xF8, 0x03, 0x80, 0x99, 0xF8, 0x02, 0xB0, 0xC8, 0xF3, 0x83, 0x0A, 0xBA, 0xF1, 0x08, 0x0F, 0x04, 0xD8, 0xA1, 0x4B, +0x1B, 0x78, 0x00, 0x2B, 0x00, 0xF0, 0x87, 0x80, 0x25, 0x23, 0x00, 0x21, 0xCD, 0xE9, 0x00, 0x83, 0x30, 0x46, 0x5B, 0x46, +0x02, 0x91, 0x01, 0x22, 0x00, 0xF0, 0x82, 0xFB, 0xD0, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xB1, 0xF5, 0x10, 0x4F, 0x4F, 0xEA, +0x11, 0x35, 0xC9, 0xD2, 0xE3, 0x79, 0xFF, 0x2B, 0xC6, 0xD0, 0x09, 0x05, 0x2A, 0x46, 0x40, 0xF1, 0xBA, 0x80, 0x93, 0x49, +0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xA4, 0xFA, 0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, +0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x51, 0x21, 0x2D, 0xB1, 0xD0, 0x2E, 0x02, 0x46, 0xF0, 0x08, 0x06, 0x30, 0x46, +0xF2, 0xF7, 0x7C, 0xFE, 0x04, 0x28, 0xA9, 0xD0, 0x31, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, 0xE1, 0xFA, 0x30, 0x46, +0xF2, 0xF7, 0x72, 0xFE, 0x01, 0x28, 0x00, 0xF0, 0xD2, 0x80, 0x30, 0x46, 0xF2, 0xF7, 0x6C, 0xFE, 0x03, 0x28, 0x00, 0xF0, +0xCC, 0x80, 0x7F, 0x4B, 0x28, 0x46, 0x9B, 0x6A, 0x98, 0x47, 0x93, 0xE7, 0xB9, 0xF8, 0x05, 0x50, 0xC5, 0xF3, 0x83, 0x06, +0x08, 0x2E, 0x8D, 0xD8, 0xE3, 0x79, 0x7A, 0x49, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x33, 0x44, 0x07, 0xEB, +0xC3, 0x07, 0x32, 0x46, 0x97, 0xF8, 0xA5, 0x71, 0x4F, 0xF4, 0x00, 0x60, 0x3B, 0x46, 0xF4, 0xF7, 0x63, 0xFA, 0x21, 0x2F, +0x3F, 0xF4, 0x7A, 0xAF, 0x4F, 0xEA, 0x07, 0x28, 0x48, 0xF0, 0x08, 0x08, 0x40, 0x46, 0xF2, 0xF7, 0x43, 0xFE, 0x02, 0x28, +0x7F, 0xF4, 0x70, 0xAF, 0x41, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0xA7, 0xFA, 0x6A, 0x4A, 0x99, 0xF8, 0x02, 0x10, +0x07, 0xEB, 0x47, 0x03, 0x02, 0xEB, 0xC3, 0x03, 0x58, 0x7C, 0x88, 0x42, 0x03, 0xD1, 0x1B, 0x7C, 0xB3, 0x42, 0x00, 0xF0, +0x9B, 0x80, 0x38, 0x46, 0x00, 0xF0, 0xF4, 0xF9, 0x40, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0x7E, 0xFD, 0x54, 0xE7, 0x60, 0x49, +0x4F, 0xF4, 0x00, 0x60, 0x52, 0x46, 0xF4, 0xF7, 0x35, 0xFA, 0x51, 0x46, 0x30, 0x46, 0xE8, 0xF7, 0x85, 0xF9, 0x00, 0x28, +0x4F, 0xD1, 0x95, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0x3F, 0xF4, 0x68, 0xAF, 0x00, 0xF0, 0x04, 0xFA, 0x21, 0x28, 0x04, 0x46, +0x3F, 0xF4, 0x62, 0xAF, 0x53, 0x4D, 0x55, 0x4A, 0x00, 0xEB, 0x40, 0x01, 0x05, 0xEB, 0xC1, 0x03, 0xC8, 0xF3, 0x40, 0x00, +0x12, 0x68, 0x83, 0xF8, 0x10, 0xA0, 0x00, 0x27, 0x1E, 0x73, 0x83, 0xF8, 0x11, 0xB0, 0x98, 0x73, 0x5F, 0x73, 0x90, 0x6B, +0xB9, 0xF8, 0x05, 0x20, 0x5A, 0x81, 0x4F, 0xEA, 0x98, 0x18, 0x80, 0x45, 0x28, 0xBF, 0x80, 0x46, 0x83, 0xF8, 0x0F, 0x80, +0xB9, 0xF8, 0x07, 0x00, 0xC9, 0x00, 0x00, 0x09, 0x92, 0xB2, 0x6F, 0x50, 0x18, 0x81, 0x1A, 0xB9, 0x44, 0x4A, 0x12, 0x68, +0x52, 0x88, 0x5A, 0x81, 0x30, 0x46, 0x21, 0x46, 0x00, 0xF0, 0x3C, 0xFA, 0x20, 0x02, 0x00, 0xF4, 0x7F, 0x40, 0x40, 0xF0, +0x08, 0x00, 0x03, 0x21, 0xF2, 0xF7, 0x32, 0xFD, 0x08, 0xE7, 0x3D, 0x49, 0x4F, 0xF4, 0x00, 0x60, 0xF4, 0xF7, 0xEA, 0xF9, +0xE3, 0x79, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x2B, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA5, 0x51, +0x44, 0xE7, 0x06, 0xEB, 0x86, 0x03, 0xC6, 0xEB, 0x03, 0x13, 0x53, 0x44, 0x07, 0xEB, 0xC3, 0x07, 0x97, 0xF8, 0xA4, 0x71, +0x3D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0x28, 0x46, 0xF2, 0xF7, 0xBA, 0xFD, 0x01, 0x28, 0x7F, 0xF4, 0x0B, 0xAF, 0x2A, 0x4B, +0x27, 0x4A, 0x1B, 0x68, 0x07, 0xEB, 0x47, 0x01, 0x02, 0xEB, 0xC1, 0x02, 0x99, 0x6B, 0xD2, 0x7B, 0x4F, 0xEA, 0x98, 0x13, +0x8B, 0x42, 0x28, 0xBF, 0x0B, 0x46, 0x9A, 0x42, 0x12, 0xD0, 0x28, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xFB, 0xFC, 0xE0, 0x79, +0x39, 0x46, 0x00, 0xF0, 0x1D, 0xFA, 0x25, 0x23, 0xF1, 0xE6, 0x30, 0x46, 0x04, 0x21, 0xF2, 0xF7, 0xF1, 0xFC, 0xE0, 0x79, +0x29, 0x46, 0x00, 0xF0, 0x13, 0xFA, 0xC3, 0xE6, 0x00, 0x23, 0xE6, 0xE6, 0xB9, 0xF8, 0x03, 0x30, 0x00, 0x2B, 0x7F, 0xF4, +0x60, 0xAF, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x23, 0xA9, 0x09, 0xDB, 0x7B, 0xB3, 0xEB, 0x95, 0x1F, 0x03, 0xD9, 0x18, 0x23, +0x03, 0xFB, 0x07, 0x23, 0xD9, 0x73, 0x18, 0x23, 0x03, 0xFB, 0x07, 0x22, 0x05, 0xF0, 0x01, 0x05, 0x95, 0x74, 0xE0, 0x79, +0x39, 0x46, 0x00, 0xF0, 0xD1, 0xF9, 0x40, 0x46, 0x03, 0x21, 0xF2, 0xF7, 0xCB, 0xFC, 0xA1, 0xE6, 0x68, 0x65, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0xB9, 0x34, 0x17, 0x00, 0xE4, 0xC1, 0x15, 0x00, 0x88, 0x1A, 0x17, 0x00, 0xC0, 0xC1, 0x15, 0x00, +0xF4, 0xE4, 0x17, 0x00, 0xA4, 0xC1, 0x15, 0x00, 0x78, 0x36, 0x17, 0x00, 0xC8, 0x35, 0x17, 0x00, 0x08, 0xC2, 0x15, 0x00, +0x10, 0xB5, 0x10, 0x46, 0x14, 0x46, 0xF2, 0xF7, 0x57, 0xFD, 0x02, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x10, 0xBD, 0x20, 0x0A, +0x00, 0xF0, 0x1A, 0xF9, 0x20, 0x46, 0x00, 0x21, 0xF2, 0xF7, 0xA4, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x10, 0x46, +0x84, 0xB0, 0x14, 0x46, 0xF2, 0xF7, 0x44, 0xFD, 0x01, 0x28, 0x02, 0xD0, 0x00, 0x20, 0x04, 0xB0, 0x70, 0xBD, 0x20, 0x0A, +0x13, 0x4A, 0x00, 0xEB, 0x40, 0x05, 0x52, 0xF8, 0x35, 0x60, 0x02, 0xEB, 0xC5, 0x05, 0x3E, 0xB9, 0x10, 0x4B, 0x6A, 0x68, +0x19, 0x69, 0x6B, 0x89, 0x52, 0x1A, 0x12, 0xEB, 0x83, 0x23, 0x04, 0xD4, 0x00, 0xF0, 0x74, 0xF9, 0x00, 0x20, 0x04, 0xB0, +0x70, 0xBD, 0x20, 0x46, 0x04, 0x21, 0x2C, 0x7B, 0xF2, 0xF7, 0x7C, 0xFC, 0x08, 0x4B, 0x02, 0x93, 0x27, 0x22, 0x01, 0x92, +0x00, 0x96, 0x20, 0x46, 0x33, 0x46, 0x29, 0x46, 0x02, 0x22, 0xEE, 0x74, 0x00, 0xF0, 0xF8, 0xF9, 0xD4, 0xE7, 0x00, 0xBF, +0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0xE5, 0xFE, 0x14, 0x00, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x47, 0x20, +0x19, 0x44, 0xB1, 0xFB, 0xF2, 0xF0, 0x02, 0xFB, 0x10, 0x10, 0x70, 0x47, 0x90, 0xF8, 0x46, 0x30, 0x90, 0xF8, 0x48, 0x00, +0x19, 0x44, 0x08, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x03, 0x4B, 0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x20, 0xC0, 0xF3, 0xC0, 0x30, +0x70, 0x47, 0x00, 0xBF, 0x00, 0x10, 0x50, 0x40, 0x70, 0xB5, 0x90, 0xF8, 0x46, 0x30, 0x03, 0x44, 0x9A, 0x79, 0x02, 0x2A, +0x17, 0xD1, 0x00, 0x26, 0x04, 0x46, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, +0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, +0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0x70, 0xBD, 0x00, 0x26, 0x30, 0x46, 0x70, 0xBD, 0x38, 0xB5, 0x85, 0x88, +0x03, 0x68, 0x49, 0x1B, 0xC1, 0xF3, 0x0B, 0x01, 0x04, 0x46, 0x15, 0x46, 0x98, 0x47, 0x20, 0x44, 0x85, 0x71, 0x38, 0xBD, +0xF8, 0xB5, 0x05, 0x46, 0x33, 0x48, 0x6F, 0x6A, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0xC1, 0x00, 0xBF, 0x02, 0x44, 0x69, +0x03, 0xD5, 0x11, 0x46, 0x4B, 0xB3, 0x00, 0x2A, 0x49, 0xD0, 0xA2, 0x88, 0x29, 0x8C, 0x23, 0x68, 0x89, 0x1A, 0xC1, 0xF3, +0x0B, 0x01, 0x20, 0x46, 0x98, 0x47, 0x20, 0x44, 0x02, 0x23, 0x83, 0x71, 0x94, 0xF8, 0x46, 0x30, 0x23, 0x44, 0x00, 0x26, +0x9A, 0x79, 0x02, 0x2A, 0x13, 0xD1, 0x35, 0x46, 0x9D, 0x71, 0xA3, 0x88, 0x22, 0x68, 0x01, 0x33, 0xC3, 0xF3, 0x0B, 0x03, +0xA3, 0x80, 0x01, 0x21, 0x20, 0x46, 0x90, 0x47, 0x54, 0xFA, 0x80, 0xF3, 0x84, 0xF8, 0x46, 0x00, 0x9A, 0x79, 0x01, 0x36, +0x02, 0x2A, 0x76, 0xB2, 0xEC, 0xD0, 0x30, 0x46, 0xF8, 0xBD, 0x00, 0x2A, 0xD5, 0xD1, 0x19, 0x4B, 0xB5, 0xF8, 0x40, 0x00, +0x1B, 0x69, 0xA0, 0xEB, 0x93, 0x23, 0x1B, 0x04, 0xCD, 0xD4, 0xEA, 0x8B, 0xEB, 0x6C, 0x6F, 0xEA, 0x42, 0x42, 0x1C, 0x69, +0x6F, 0xEA, 0x52, 0x42, 0xEA, 0x83, 0x44, 0xF0, 0x02, 0x04, 0x6A, 0x8F, 0x0E, 0x46, 0x29, 0x8F, 0x19, 0x80, 0x1C, 0x61, +0xE9, 0x8F, 0xAC, 0x8F, 0x5A, 0x80, 0x2A, 0x8C, 0x1A, 0x81, 0x9C, 0x80, 0xD9, 0x80, 0x58, 0x81, 0xDB, 0xE7, 0x09, 0x48, +0xB5, 0xF8, 0x40, 0x20, 0x03, 0x69, 0xA2, 0xEB, 0x93, 0x23, 0x1E, 0x04, 0xAD, 0xD4, 0x03, 0x69, 0x05, 0x48, 0xA2, 0xEB, +0x93, 0x22, 0xC2, 0xF3, 0xC0, 0x32, 0xF4, 0xF7, 0x23, 0xF8, 0xA4, 0xE7, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, +0x34, 0xC2, 0x15, 0x00, 0xF8, 0xB5, 0x0D, 0x4D, 0x0D, 0x4E, 0xFF, 0x27, 0x2F, 0x73, 0x00, 0x24, 0x08, 0xE0, 0x0F, 0x2C, +0x85, 0xF8, 0x24, 0x70, 0x03, 0xDD, 0x4C, 0x23, 0x03, 0xFB, 0x04, 0x63, 0xEB, 0x62, 0x18, 0x35, 0x20, 0x02, 0x00, 0xF4, +0x7F, 0x40, 0x40, 0xF0, 0x08, 0x00, 0x01, 0x34, 0x00, 0x21, 0xF2, 0xF7, 0x95, 0xFB, 0x20, 0x2C, 0xEB, 0xD1, 0xF8, 0xBD, +0xF4, 0xE4, 0x17, 0x00, 0x74, 0xDB, 0x17, 0x00, 0x11, 0x4B, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0xC0, 0x00, 0x42, 0x7B, +0x03, 0x7B, 0x01, 0x7C, 0x72, 0xB1, 0x01, 0x2A, 0x0B, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0B, 0x4A, +0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x70, 0x47, 0x70, 0x47, 0x03, 0xEB, 0x83, 0x02, +0xC3, 0xEB, 0x02, 0x13, 0x04, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, 0x70, 0x47, +0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0x00, 0x28, 0x09, 0x4B, 0x14, 0xBF, 0x10, 0x20, 0x00, 0x20, 0x03, 0xEB, +0x40, 0x03, 0x14, 0xBF, 0x20, 0x21, 0x10, 0x21, 0x33, 0xF8, 0x02, 0x2F, 0x22, 0xB1, 0x01, 0x30, 0x88, 0x42, 0xF9, 0xDB, +0x21, 0x20, 0x70, 0x47, 0x80, 0xB2, 0x70, 0x47, 0xF2, 0xDF, 0x17, 0x00, 0x38, 0xB5, 0x05, 0x02, 0x45, 0xF0, 0x08, 0x05, +0x04, 0x46, 0x29, 0x46, 0x4F, 0xF4, 0x00, 0x50, 0xF2, 0xF7, 0x5A, 0xF8, 0x29, 0x46, 0x42, 0xF2, 0x01, 0x00, 0xF2, 0xF7, +0x55, 0xF8, 0x16, 0x48, 0x04, 0xEB, 0x44, 0x04, 0x00, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x23, 0x7B, 0x21, 0x7C, 0x92, 0xB1, +0x01, 0x2A, 0x0A, 0xD1, 0x03, 0xEB, 0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x0F, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, +0x21, 0x22, 0x83, 0xF8, 0xA5, 0x21, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x25, 0xBB, 0x03, 0xEB, +0x83, 0x02, 0xC3, 0xEB, 0x02, 0x13, 0x07, 0x4A, 0x0B, 0x44, 0x02, 0xEB, 0xC3, 0x03, 0x21, 0x22, 0x83, 0xF8, 0xA4, 0x21, +0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0x38, 0x40, 0xF2, 0xF7, 0x14, 0xBB, 0xF4, 0xE4, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x07, 0x4B, 0x00, 0xEB, 0x40, 0x02, 0x03, 0xEB, 0xC2, 0x03, 0x00, 0x02, 0x5A, 0x89, 0x00, 0xF4, 0x7F, 0x41, 0x41, 0xF0, +0x08, 0x01, 0x92, 0x02, 0x42, 0xF2, 0x01, 0x00, 0xF1, 0xF7, 0x64, 0xBF, 0xF4, 0xE4, 0x17, 0x00, 0x0A, 0x02, 0x02, 0xF4, +0x7F, 0x42, 0x38, 0xB5, 0x42, 0xF0, 0x08, 0x02, 0x05, 0x46, 0x0C, 0x46, 0x06, 0x23, 0x00, 0x21, 0x28, 0x20, 0xF2, 0xF7, +0xF7, 0xF8, 0x0A, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x62, 0x7B, 0x45, 0x70, 0x01, 0x3A, 0x18, 0xBF, +0x01, 0x22, 0x02, 0x70, 0x22, 0x7C, 0x82, 0x70, 0xE2, 0x7B, 0xC2, 0x70, 0x22, 0x89, 0x82, 0x80, 0xBD, 0xE8, 0x38, 0x40, +0xF2, 0xF7, 0x12, 0xB9, 0xF4, 0xE4, 0x17, 0x00, 0xF8, 0xB5, 0x0D, 0x02, 0x45, 0xF0, 0x08, 0x05, 0xAD, 0xB2, 0x03, 0x23, +0x0C, 0x46, 0x07, 0x46, 0x2A, 0x46, 0x00, 0x21, 0x2A, 0x20, 0xF2, 0xF7, 0xD3, 0xF8, 0x12, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0x06, 0x46, 0x11, 0xDB, 0x0F, 0x49, 0x04, 0xEB, 0x44, 0x04, 0x01, 0xEB, 0xC4, 0x04, 0x30, 0x46, +0x63, 0x7B, 0x77, 0x70, 0x01, 0x3B, 0x18, 0xBF, 0x01, 0x23, 0x33, 0x70, 0x23, 0x7C, 0xB3, 0x70, 0xBD, 0xE8, 0xF8, 0x40, +0xF2, 0xF7, 0xEA, 0xB8, 0x28, 0x46, 0xF2, 0xF7, 0x59, 0xFB, 0x04, 0x28, 0xE8, 0xD0, 0x05, 0x49, 0x05, 0x48, 0x40, 0xF2, +0x05, 0x22, 0xF4, 0xF7, 0x91, 0xF9, 0xE1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x60, 0xC2, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x10, 0x4E, 0x11, 0x4D, 0x80, 0x46, 0x87, 0xB2, 0x00, 0x24, 0x36, 0xF8, +0x02, 0x3F, 0x8B, 0xB1, 0x2B, 0x7B, 0x43, 0x45, 0x0E, 0xD1, 0x1F, 0xFA, 0x84, 0xF9, 0x4F, 0xEA, 0x09, 0x23, 0x03, 0xF4, +0x7F, 0x43, 0x43, 0xF0, 0x08, 0x00, 0x04, 0x21, 0xF2, 0xF7, 0x88, 0xFA, 0x49, 0x46, 0x38, 0x46, 0xFF, 0xF7, 0xAA, 0xFF, +0x01, 0x34, 0x20, 0x2C, 0x05, 0xF1, 0x18, 0x05, 0xE5, 0xD1, 0xBD, 0xE8, 0xF8, 0x83, 0x00, 0xBF, 0xF2, 0xDF, 0x17, 0x00, +0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xDF, 0xF8, 0x50, 0x92, 0xBD, 0xF8, 0x50, 0x40, 0x09, 0x94, +0xBD, 0xF8, 0x54, 0x40, 0x07, 0x94, 0x16, 0x9C, 0x04, 0x94, 0x4F, 0xF4, 0x1E, 0x74, 0x04, 0xFB, 0x00, 0x94, 0x87, 0x4F, +0x94, 0xF8, 0x22, 0x80, 0xDF, 0xF8, 0x30, 0xA2, 0x03, 0x91, 0x06, 0x46, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x08, 0x70, +0x93, 0x46, 0x00, 0x6C, 0x08, 0x93, 0x00, 0x28, 0x00, 0xF0, 0xC4, 0x80, 0xDA, 0xF8, 0x00, 0x30, 0x02, 0x79, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x08, 0x73, 0x4F, 0xF4, 0xC0, 0x71, +0x93, 0xF8, 0xC0, 0x34, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xDF, 0xF7, 0x14, 0xFB, 0x04, 0x46, 0x00, 0x28, +0x00, 0xF0, 0x9B, 0x80, 0x4F, 0xF4, 0xA4, 0x65, 0x05, 0xFB, 0x08, 0xF5, 0x78, 0x19, 0x21, 0x46, 0x05, 0x90, 0xF1, 0xF7, +0x05, 0xFC, 0x4F, 0xF4, 0x1E, 0x72, 0xA3, 0x6C, 0x02, 0xFB, 0x06, 0xF2, 0x00, 0x21, 0x26, 0x32, 0x6F, 0xF0, 0x2F, 0x0C, +0x83, 0xF8, 0x68, 0xC0, 0x83, 0xF8, 0x69, 0x10, 0x83, 0xF8, 0x6A, 0x10, 0x83, 0xF8, 0x6B, 0x10, 0x39, 0xF8, 0x02, 0x10, +0xA3, 0xF8, 0x6C, 0x10, 0x09, 0xEB, 0x02, 0x01, 0x5C, 0x35, 0xB1, 0xF8, 0x02, 0xC0, 0xA3, 0xF8, 0x6E, 0xC0, 0xB1, 0xF8, +0x04, 0xC0, 0xA3, 0xF8, 0x70, 0xC0, 0x37, 0xF8, 0x05, 0xC0, 0xA3, 0xF8, 0x72, 0xC0, 0x07, 0xEB, 0x05, 0x0C, 0x03, 0xF1, +0x68, 0x00, 0xBC, 0xF8, 0x02, 0xE0, 0xA3, 0xF8, 0x74, 0xE0, 0xBC, 0xF8, 0x04, 0xE0, 0x06, 0x90, 0x05, 0x98, 0xA3, 0xF8, +0x76, 0xE0, 0x90, 0xF8, 0x62, 0x00, 0x02, 0x28, 0x5E, 0xD0, 0x39, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x78, 0x20, 0x4A, 0x88, +0xA3, 0xF8, 0x7A, 0x20, 0x8A, 0x88, 0xA3, 0xF8, 0x7C, 0x20, 0x4E, 0x49, 0xB1, 0xF8, 0xFC, 0x21, 0x01, 0x32, 0x92, 0xB2, +0xA1, 0xF8, 0xFC, 0x21, 0x10, 0x01, 0x00, 0x21, 0xA3, 0xF8, 0x7E, 0x00, 0x03, 0x22, 0x84, 0xF8, 0x33, 0x10, 0x84, 0xF8, +0x35, 0x10, 0x84, 0xF8, 0x1C, 0x80, 0x66, 0x77, 0xD0, 0x21, 0x20, 0x46, 0x00, 0xF0, 0xE6, 0xFB, 0x01, 0x28, 0x70, 0xD0, +0x18, 0x25, 0xBB, 0xF1, 0x01, 0x0F, 0x4A, 0xD0, 0xBB, 0xF1, 0x02, 0x0F, 0x54, 0xD0, 0xBB, 0xF1, 0x00, 0x0F, 0x5C, 0xD0, +0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x69, 0xDB, 0x03, 0x26, 0xE1, 0x6C, 0x94, 0xF8, 0x35, 0x30, +0x4A, 0x6A, 0x1D, 0x44, 0x01, 0x3A, 0x04, 0x9B, 0x2A, 0x44, 0x04, 0x35, 0xC1, 0xE9, 0x0A, 0x25, 0x13, 0xB1, 0x63, 0x65, +0x03, 0x9B, 0xA3, 0x65, 0x31, 0x46, 0x20, 0x46, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xDF, 0xF7, 0x97, 0xBA, 0x02, 0x2A, +0x7F, 0xF4, 0x62, 0xAF, 0x2D, 0x49, 0x2E, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xF4, 0xF7, 0x92, 0xF8, 0x01, 0x20, 0x4F, 0xF4, +0xC0, 0x71, 0xDF, 0xF7, 0x79, 0xFA, 0x04, 0x46, 0x00, 0x28, 0x7F, 0xF4, 0x65, 0xAF, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x7A, 0x5B, 0xA3, 0xF8, 0x78, 0x20, 0xBC, 0xF8, 0x02, 0x20, 0xA3, 0xF8, 0x7A, 0x20, 0xBC, 0xF8, 0x04, 0x20, 0xA3, 0xF8, +0x7C, 0x20, 0x9E, 0xE7, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xE1, 0xDA, 0xDA, 0xE7, 0x06, 0x99, +0x07, 0x9B, 0x00, 0x93, 0x29, 0x44, 0x08, 0x46, 0xDD, 0xE9, 0x08, 0x32, 0x03, 0x99, 0xF5, 0xF7, 0x4D, 0xFA, 0x03, 0x26, +0x05, 0x44, 0xB4, 0xE7, 0xDD, 0xE9, 0x06, 0x02, 0x03, 0x99, 0x15, 0x4E, 0x0B, 0x7C, 0x28, 0x44, 0xF6, 0x5C, 0xF5, 0xF7, +0x5D, 0xFA, 0x05, 0x44, 0xA9, 0xE7, 0x03, 0x99, 0x06, 0x98, 0x10, 0x4A, 0x0B, 0x7C, 0x28, 0x44, 0xD6, 0x5C, 0xF5, 0xF7, +0x1B, 0xFA, 0x05, 0x44, 0x9F, 0xE7, 0x06, 0x99, 0x18, 0x22, 0x20, 0x46, 0xFF, 0xF7, 0xD2, 0xF9, 0x94, 0xF8, 0x33, 0x50, +0x18, 0x35, 0x86, 0xE7, 0x05, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x6E, 0x22, 0xF4, 0xF7, 0x5A, 0xF8, 0x03, 0x26, 0x8E, 0xE7, +0x18, 0x88, 0x17, 0x00, 0x20, 0x62, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, 0xC0, 0xB2, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x35, 0x4B, 0x87, 0xB0, +0x81, 0x46, 0x8A, 0x46, 0x93, 0x46, 0x10, 0x24, 0x33, 0xF8, 0x02, 0x5F, 0x35, 0xB1, 0x01, 0x34, 0x20, 0x2C, 0xF9, 0xD1, +0x03, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x2E, 0x4A, 0xDF, 0xF8, 0xCC, 0x80, 0x04, 0xEB, 0x44, 0x03, 0x02, 0xEB, +0xC3, 0x06, 0xDB, 0x00, 0x86, 0xF8, 0x0C, 0x90, 0x86, 0xF8, 0x10, 0xA0, 0x05, 0x93, 0x06, 0xF0, 0xBB, 0xFB, 0x28, 0x49, +0x70, 0x74, 0x09, 0x68, 0x27, 0x48, 0xB1, 0xF8, 0x02, 0xC0, 0x10, 0xF8, 0x0A, 0x00, 0x05, 0x9B, 0x25, 0x49, 0x22, 0x4A, +0x02, 0x95, 0x09, 0xEB, 0x89, 0x07, 0xC9, 0xEB, 0x07, 0x17, 0x57, 0x44, 0x00, 0x95, 0x34, 0x37, 0x51, 0xF8, 0x20, 0xE0, +0xD5, 0x50, 0x08, 0xEB, 0xC7, 0x00, 0x27, 0x23, 0x01, 0x93, 0xA6, 0xF8, 0x0A, 0xC0, 0x4F, 0xF0, 0x01, 0x0C, 0x86, 0xF8, +0x0F, 0xE0, 0x86, 0xF8, 0x0E, 0xC0, 0x86, 0xF8, 0x0D, 0xC0, 0x31, 0x46, 0x2B, 0x46, 0x44, 0x71, 0xA6, 0xF8, 0x08, 0xB0, +0x48, 0x46, 0x02, 0x22, 0xFF, 0xF7, 0x82, 0xFE, 0x24, 0x02, 0x31, 0x46, 0x48, 0x46, 0x2B, 0x46, 0x2A, 0x46, 0xCD, 0xE9, +0x01, 0x55, 0x00, 0x95, 0xFF, 0xF7, 0x78, 0xFE, 0x44, 0xF0, 0x08, 0x04, 0x0E, 0x4B, 0xA4, 0xB2, 0x1B, 0x69, 0x48, 0xF8, +0x37, 0x30, 0x21, 0x46, 0x4F, 0xF4, 0xFA, 0x22, 0x4F, 0xF4, 0x00, 0x50, 0xF1, 0xF7, 0x46, 0xFD, 0x20, 0x46, 0x02, 0x21, +0xF2, 0xF7, 0xDE, 0xF8, 0x28, 0x46, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0xE0, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, +0xC8, 0x35, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x7C, 0x28, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x19, 0x4C, 0x1A, 0x4D, 0xDF, 0xF8, 0x68, 0xA0, 0xC4, 0xEB, 0x44, 0x29, 0x4F, 0xEA, 0xC9, 0x19, +0x84, 0xB0, 0x07, 0x46, 0x1F, 0xFA, 0x89, 0xF9, 0x04, 0xF1, 0x40, 0x06, 0x4F, 0xF0, 0x00, 0x08, 0x34, 0xF8, 0x02, 0x3F, +0xCB, 0xB1, 0x2B, 0x7B, 0xBB, 0x42, 0x16, 0xD1, 0x09, 0xEB, 0xC4, 0x10, 0xA0, 0xF5, 0x80, 0x70, 0x40, 0xF0, 0x08, 0x00, +0x80, 0xB2, 0x04, 0x21, 0xF2, 0xF7, 0xAA, 0xF8, 0x27, 0x23, 0xCD, 0xE9, 0x00, 0x83, 0xCD, 0xF8, 0x08, 0xA0, 0x00, 0x23, +0x02, 0x22, 0x29, 0x46, 0x38, 0x46, 0x85, 0xF8, 0x13, 0x80, 0xFF, 0xF7, 0x25, 0xFE, 0xB4, 0x42, 0x05, 0xF1, 0x18, 0x05, +0xDE, 0xD1, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xF2, 0xDF, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0xE5, 0xFE, 0x14, 0x00, +0xFF, 0x29, 0x2F, 0xD0, 0xF8, 0xB5, 0xC3, 0xB2, 0x03, 0xEB, 0x83, 0x02, 0x16, 0x4F, 0xC3, 0xEB, 0x02, 0x13, 0x53, 0xFA, +0x81, 0xF3, 0x07, 0xEB, 0xC3, 0x03, 0x0C, 0x46, 0x93, 0xF8, 0xA5, 0x61, 0x21, 0x2E, 0x05, 0x46, 0x1C, 0xD0, 0x30, 0x02, +0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0x20, 0xF9, 0x01, 0x28, 0x15, 0xD1, 0x0D, 0x4B, 0x06, 0xEB, 0x46, 0x06, 0x03, 0xEB, +0xC6, 0x06, 0x4F, 0xF4, 0x9E, 0x71, 0x01, 0xFB, 0x05, 0x44, 0x73, 0x69, 0x07, 0xEB, 0x44, 0x04, 0x9A, 0x88, 0xB4, 0xF8, +0x34, 0x31, 0x9B, 0x1A, 0x13, 0xF4, 0x7C, 0x6F, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0xF8, 0xBD, 0x01, 0x20, 0xF8, 0xBD, +0x02, 0x20, 0x70, 0x47, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0x50, 0x48, +0xE1, 0x7E, 0xD0, 0xF8, 0x10, 0x90, 0xFF, 0x29, 0x23, 0xD0, 0x65, 0x7F, 0x4D, 0x4E, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, +0x05, 0x63, 0x5A, 0x68, 0x97, 0x07, 0x1A, 0xD5, 0x05, 0xEB, 0x85, 0x07, 0xC5, 0xEB, 0x07, 0x17, 0x7A, 0x18, 0x34, 0x32, +0x06, 0xEB, 0xC2, 0x0C, 0x9C, 0xF8, 0x07, 0xE0, 0x9C, 0xF8, 0x05, 0x80, 0x0E, 0xF1, 0x01, 0x0E, 0xB8, 0xF1, 0x21, 0x0F, +0x8C, 0xF8, 0x07, 0xE0, 0x09, 0xD1, 0x00, 0x69, 0x56, 0xF8, 0x32, 0x20, 0xDF, 0xF8, 0x14, 0xC1, 0x82, 0x1A, 0x62, 0x45, +0x48, 0xD8, 0xBD, 0xE8, 0xF0, 0x87, 0xDF, 0xF8, 0x0C, 0xA1, 0x08, 0xEB, 0x48, 0x07, 0x0A, 0xEB, 0xC7, 0x07, 0x4F, 0xEA, +0x08, 0x20, 0xC7, 0xF8, 0x04, 0x90, 0x40, 0xF0, 0x08, 0x00, 0xF2, 0xF7, 0xC3, 0xF8, 0x01, 0x28, 0x4F, 0xEA, 0x48, 0x09, +0xEB, 0xD1, 0x7F, 0x69, 0xE3, 0x8B, 0xB8, 0x88, 0x60, 0x84, 0xD9, 0x07, 0x57, 0xD4, 0x4F, 0xF4, 0x1E, 0x72, 0x02, 0xFB, +0x05, 0x65, 0xD5, 0xF8, 0x4C, 0x21, 0x92, 0xF8, 0xA2, 0x20, 0x52, 0x07, 0x03, 0xD5, 0x62, 0x6A, 0x42, 0xF4, 0x00, 0x12, +0x62, 0x62, 0x21, 0x8C, 0x3A, 0x68, 0x43, 0xF0, 0x02, 0x03, 0x09, 0x1A, 0xE3, 0x83, 0xC1, 0xF3, 0x0B, 0x01, 0x38, 0x46, +0x90, 0x47, 0x38, 0x44, 0x01, 0x23, 0x83, 0x71, 0xE3, 0x8B, 0xDB, 0x07, 0x07, 0xD4, 0x1F, 0x4A, 0x20, 0x4B, 0x12, 0x69, +0x9B, 0x8D, 0x03, 0xEB, 0x92, 0x23, 0xA4, 0xF8, 0x40, 0x30, 0xC8, 0x44, 0x4F, 0xEA, 0xC8, 0x08, 0x5A, 0xF8, 0x08, 0x30, +0x01, 0x33, 0x4A, 0xF8, 0x08, 0x30, 0xB6, 0xE7, 0x93, 0xF8, 0x24, 0x30, 0x01, 0x2B, 0xB2, 0xD0, 0x17, 0x4B, 0x18, 0x48, +0x5A, 0x5C, 0x54, 0x23, 0x03, 0xFB, 0x02, 0xF3, 0xC3, 0x58, 0x00, 0x2B, 0xA9, 0xD1, 0x15, 0x4B, 0x53, 0xF8, 0x32, 0x30, +0x00, 0x2B, 0xA4, 0xD1, 0xBB, 0x18, 0x46, 0x33, 0x56, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x9E, 0xD1, 0x23, 0x7F, 0x10, 0x48, +0xA4, 0x26, 0x06, 0xFB, 0x03, 0x23, 0x9E, 0x33, 0x50, 0xF8, 0x33, 0x30, 0x00, 0x2B, 0x94, 0xD1, 0x0C, 0x4B, 0x22, 0x8C, +0x1B, 0x6A, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0x18, 0x47, 0x03, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0x89, 0xD1, 0xA2, 0xE7, +0x00, 0x10, 0x50, 0x40, 0x68, 0x65, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0xC0, 0xB2, 0x15, 0x00, 0x20, 0x62, 0x17, 0x00, +0x24, 0x64, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x88, 0x1A, 0x17, 0x00, 0x40, 0x42, 0x0F, 0x00, 0xF4, 0xE4, 0x17, 0x00, +0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x1C, 0x48, 0x6C, 0x7F, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x04, 0x03, 0x5E, 0x68, +0xB6, 0x07, 0x0E, 0xD5, 0xEB, 0x7E, 0x04, 0xEB, 0x84, 0x06, 0xC4, 0xEB, 0x06, 0x14, 0x1C, 0x44, 0x34, 0x34, 0x00, 0xEB, +0xC4, 0x04, 0xE3, 0x79, 0x01, 0x3B, 0xE3, 0x71, 0xEB, 0x8B, 0x9B, 0x07, 0x02, 0xD4, 0x01, 0x20, 0xBD, 0xE8, 0xF0, 0x87, +0x66, 0x79, 0x21, 0x2E, 0xF9, 0xD0, 0x30, 0x02, 0x40, 0xF0, 0x08, 0x00, 0x88, 0x46, 0x91, 0x46, 0xF2, 0xF7, 0x20, 0xF8, +0x01, 0x28, 0xF0, 0xD1, 0x06, 0xEB, 0x46, 0x07, 0xFF, 0x00, 0xDF, 0xF8, 0x20, 0xC0, 0x5C, 0xF8, 0x07, 0x40, 0x01, 0x3C, +0x4C, 0xF8, 0x07, 0x40, 0x4B, 0x46, 0x42, 0x46, 0x28, 0x46, 0x31, 0x46, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x46, 0xBB, +0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x38, 0xB5, 0x45, 0x69, 0x04, 0x46, 0x40, 0x22, 0x00, 0x21, 0xA8, 0x1D, +0xCF, 0xF7, 0x58, 0xF9, 0x22, 0x7B, 0x21, 0x7C, 0x0C, 0x4B, 0x4F, 0xF4, 0x9E, 0x70, 0x00, 0xFB, 0x02, 0x12, 0x03, 0xEB, +0x42, 0x03, 0x00, 0x22, 0xB3, 0xF8, 0x34, 0x31, 0xAB, 0x80, 0x85, 0xF8, 0x46, 0x20, 0xE3, 0x7B, 0x85, 0xF8, 0x47, 0x30, +0x5A, 0x1E, 0x1A, 0x42, 0x12, 0xBF, 0x04, 0x4B, 0x04, 0x4B, 0x85, 0xF8, 0x48, 0x20, 0x2B, 0x60, 0x38, 0xBD, 0x00, 0xBF, +0x68, 0x65, 0x17, 0x00, 0xDD, 0x04, 0x15, 0x00, 0xF1, 0x04, 0x15, 0x00, 0x90, 0xF8, 0x47, 0x10, 0x59, 0xB1, 0x43, 0x1D, +0x19, 0x44, 0x00, 0x20, 0x13, 0xF8, 0x01, 0x2F, 0x02, 0x2A, 0x04, 0xBF, 0x01, 0x30, 0x40, 0xB2, 0x8B, 0x42, 0xF7, 0xD1, +0x70, 0x47, 0x08, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x11, 0x4A, 0x12, 0x4B, 0x12, 0x68, 0x10, 0xB5, 0x00, 0xEB, 0x80, 0x04, +0xC0, 0xEB, 0x04, 0x10, 0x08, 0x44, 0x03, 0xEB, 0xC0, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x90, 0xF8, 0xA4, 0x41, 0x00, 0x2B, +0x08, 0xDB, 0x0B, 0x4B, 0x0B, 0x4A, 0x04, 0xEB, 0x44, 0x04, 0x03, 0xEB, 0xC4, 0x04, 0x13, 0x69, 0x63, 0x60, 0x10, 0xBD, +0x20, 0x2C, 0xF4, 0xD9, 0x07, 0x49, 0x08, 0x48, 0x40, 0xF2, 0x52, 0x32, 0xF3, 0xF7, 0xEA, 0xFD, 0xED, 0xE7, 0x00, 0xBF, +0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF4, 0xE4, 0x17, 0x00, 0x00, 0x10, 0x50, 0x40, 0x70, 0x79, 0x15, 0x00, +0x9C, 0xC2, 0x15, 0x00, 0x10, 0xF0, 0x0C, 0x0F, 0x11, 0xD1, 0x00, 0xF0, 0xF0, 0x03, 0xC0, 0x2B, 0x0B, 0xD0, 0xD0, 0x2B, +0x05, 0xD0, 0xA3, 0xF1, 0xA0, 0x00, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, 0x70, 0x47, 0x0F, 0x29, 0x24, 0xD8, 0x03, 0x29, +0x03, 0xD8, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x04, 0x39, 0x0B, 0x29, 0xF8, 0xD8, 0x01, 0xA3, 0x53, 0xF8, +0x21, 0xF0, 0x00, 0xBF, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, +0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, +0xEB, 0x0F, 0x15, 0x00, 0xEB, 0x0F, 0x15, 0x00, 0xEF, 0x0F, 0x15, 0x00, 0xB1, 0xF1, 0x7F, 0x00, 0x18, 0xBF, 0x01, 0x20, +0x70, 0x47, 0x00, 0xBF, 0x2D, 0xE9, 0xF0, 0x4F, 0x90, 0xF8, 0x08, 0xB0, 0xB0, 0xF8, 0x00, 0x90, 0x1B, 0xF8, 0x01, 0xA0, +0x0C, 0x46, 0x85, 0xB0, 0x80, 0x46, 0x51, 0x46, 0x48, 0x46, 0x1D, 0x46, 0xFF, 0xF7, 0xB4, 0xFF, 0x0B, 0xEB, 0x04, 0x0C, +0x00, 0x28, 0x00, 0xF0, 0x81, 0x80, 0x98, 0xF8, 0x09, 0x30, 0xFF, 0x2B, 0x24, 0xD0, 0x98, 0xF8, 0x0A, 0x70, 0xFF, 0x2F, +0x20, 0xD0, 0x50, 0x49, 0x16, 0x46, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x07, 0x12, 0xD2, 0xF8, 0xA8, 0x24, 0x00, 0x2A, +0x6E, 0xD0, 0x98, 0xF8, 0x30, 0x20, 0x12, 0x07, 0x6E, 0xD5, 0x09, 0xF0, 0xFC, 0x03, 0xD0, 0x2B, 0x00, 0xF0, 0x84, 0x80, +0x46, 0x4B, 0x4F, 0xF4, 0xA4, 0x68, 0x08, 0xFB, 0x07, 0xF8, 0x43, 0x44, 0xD3, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x5B, 0xD0, +0x0B, 0xF1, 0x13, 0x03, 0xB3, 0x42, 0x05, 0xDB, 0x00, 0x23, 0x01, 0x20, 0x2B, 0x70, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0xB1, 0x1E, 0xA1, 0xEB, 0x0B, 0x01, 0x0C, 0xF1, 0x02, 0x00, 0x89, 0xB2, 0xF2, 0xF7, 0x3A, 0xFC, 0x1F, 0xFA, 0x8B, 0xF3, +0x00, 0x28, 0xED, 0xD0, 0xB0, 0xF8, 0x02, 0xC0, 0xAC, 0xF1, 0x04, 0x02, 0x01, 0x2A, 0xE7, 0xD8, 0x33, 0x4A, 0xCC, 0xEB, +0x0C, 0x11, 0x08, 0xEB, 0xC1, 0x01, 0x11, 0x44, 0x4F, 0xEA, 0x0C, 0x12, 0x03, 0x92, 0x91, 0xF8, 0x3B, 0x22, 0x00, 0x2A, +0xDA, 0xD0, 0xD1, 0xE9, 0x76, 0xAB, 0x42, 0x68, 0x4F, 0xF0, 0x00, 0x0E, 0x22, 0xF0, 0x7F, 0x48, 0xF3, 0x45, 0x08, 0xBF, +0xC2, 0x45, 0xF1, 0x46, 0xCE, 0xD2, 0x82, 0x46, 0xDD, 0xF8, 0x0C, 0xB0, 0x5A, 0xF8, 0x0A, 0x2F, 0x00, 0x92, 0xDA, 0xF8, +0x04, 0x20, 0x01, 0x92, 0xC1, 0xE9, 0x76, 0x89, 0x12, 0x30, 0x52, 0x46, 0x02, 0xF8, 0x01, 0xEB, 0x82, 0x42, 0xFB, 0xD1, +0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x07, 0xF0, 0xAB, 0xEB, 0x0C, 0x0C, 0x21, 0x46, 0x00, 0xF5, 0xEC, 0x70, 0x1A, 0x4C, +0x00, 0xEB, 0xCC, 0x00, 0x20, 0x44, 0x32, 0x46, 0x00, 0xF0, 0xD2, 0xFA, 0xDD, 0xE9, 0x00, 0x34, 0x8C, 0x42, 0x08, 0xBF, +0x83, 0x42, 0xA7, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x12, 0x4A, 0x4F, 0xF4, 0x1E, 0x70, 0x00, 0xFB, +0x03, 0x23, 0x5B, 0x68, 0x1B, 0x07, 0xF3, 0xD5, 0x19, 0xF4, 0x80, 0x4F, 0xF0, 0xD1, 0x09, 0xF0, 0xFC, 0x09, 0xB9, 0xF1, +0xC0, 0x0F, 0x02, 0xD0, 0xB9, 0xF1, 0xA0, 0x0F, 0x90, 0xD1, 0xAA, 0xF1, 0x06, 0x01, 0x01, 0x29, 0x8C, 0xD8, 0x01, 0x20, +0x28, 0x70, 0xE2, 0xE7, 0xAA, 0xF1, 0x0D, 0x01, 0x01, 0x29, 0x3F, 0xF6, 0x77, 0xAF, 0x89, 0xF4, 0x80, 0x40, 0xC0, 0xF3, +0x80, 0x30, 0xD8, 0xE7, 0x18, 0x88, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x45, 0x7F, 0x06, 0x7F, 0xFF, 0x2D, +0x2B, 0xD0, 0x19, 0x4F, 0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x06, 0x73, 0xD3, 0xF8, 0xA8, 0x04, 0xE0, 0xB1, 0x0C, 0x46, +0x20, 0x46, 0x11, 0x46, 0xFF, 0xF7, 0xF0, 0xFE, 0xB0, 0xB1, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x05, 0xF5, 0x11, 0x4B, +0xE8, 0x5C, 0x10, 0xF0, 0x01, 0x00, 0x0E, 0xD0, 0x04, 0xF0, 0xFC, 0x04, 0xD0, 0x2C, 0x12, 0xD0, 0x4F, 0xF4, 0xA4, 0x63, +0x03, 0xFB, 0x06, 0x76, 0xD6, 0xF8, 0xAC, 0x34, 0x00, 0x2B, 0x0C, 0xBF, 0x00, 0x20, 0x02, 0x20, 0xF8, 0xBD, 0x1D, 0x44, +0x55, 0xF8, 0x22, 0x0C, 0xC0, 0xF3, 0xC0, 0x00, 0xF8, 0xBD, 0x00, 0x20, 0xF8, 0xBD, 0x0D, 0x3A, 0x01, 0x2A, 0xE9, 0xD8, +0xF2, 0xE7, 0x00, 0xBF, 0x18, 0x88, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0xF8, 0xB5, 0x2A, 0x4C, 0x03, 0x7F, 0x4F, 0xF4, +0xA4, 0x60, 0x00, 0xFB, 0x03, 0x43, 0x02, 0xEB, 0x01, 0x0C, 0xD3, 0xF8, 0xAC, 0x04, 0x00, 0x28, 0x47, 0xD0, 0x4C, 0x23, +0x53, 0x54, 0x10, 0x23, 0x8C, 0xF8, 0x01, 0x30, 0xD0, 0xE9, 0x12, 0x37, 0x01, 0x33, 0x90, 0xF8, 0x61, 0x40, 0xAC, 0xF8, +0x02, 0x40, 0x47, 0xF1, 0x00, 0x07, 0xC0, 0xE9, 0x12, 0x37, 0x0C, 0xF1, 0x04, 0x0E, 0x00, 0x24, 0x01, 0xE0, 0xD0, 0xE9, +0x12, 0x37, 0xC4, 0xF1, 0x20, 0x06, 0xE3, 0x40, 0xA4, 0xF1, 0x20, 0x05, 0x07, 0xFA, 0x06, 0xF6, 0x33, 0x43, 0x27, 0xFA, +0x05, 0xF5, 0x08, 0x34, 0x2B, 0x43, 0x30, 0x2C, 0x0E, 0xF8, 0x01, 0x3B, 0xED, 0xD1, 0x0C, 0xF1, 0x0A, 0x06, 0x0C, 0xF1, +0x12, 0x04, 0x33, 0x46, 0x00, 0x25, 0x03, 0xF8, 0x01, 0x5B, 0xA3, 0x42, 0xFB, 0xD1, 0x12, 0x32, 0x18, 0x23, 0x92, 0xB2, +0x00, 0xF0, 0x22, 0xFA, 0x00, 0x23, 0xC3, 0xF1, 0x20, 0x05, 0x20, 0xFA, 0x03, 0xF2, 0xA3, 0xF1, 0x20, 0x04, 0x01, 0xFA, +0x05, 0xF5, 0x2A, 0x43, 0x21, 0xFA, 0x04, 0xF4, 0x08, 0x33, 0x22, 0x43, 0x40, 0x2B, 0x06, 0xF8, 0x01, 0x2B, 0xEE, 0xD1, +0x12, 0x20, 0xF8, 0xBD, 0x18, 0x88, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x0A, 0x68, 0x05, 0x68, 0x4B, 0x68, 0xAE, 0x4C, +0xDF, 0xF8, 0xBC, 0x82, 0x8F, 0xB0, 0x0E, 0x46, 0x6A, 0x40, 0x01, 0x92, 0x32, 0x46, 0x07, 0x46, 0x0D, 0x90, 0xF0, 0x68, +0x01, 0x9E, 0x04, 0x91, 0x89, 0x68, 0x16, 0x60, 0x7E, 0x68, 0x07, 0x97, 0x83, 0xEA, 0x06, 0x05, 0x55, 0x60, 0x13, 0x46, +0xBA, 0x68, 0x00, 0x95, 0x81, 0xEA, 0x02, 0x09, 0xC3, 0xF8, 0x08, 0x90, 0xFB, 0x68, 0xCD, 0xF8, 0x0C, 0x90, 0x43, 0x40, +0x02, 0x93, 0x07, 0xF1, 0x90, 0x03, 0x0C, 0x93, 0x00, 0x9E, 0x01, 0x98, 0x02, 0x99, 0x03, 0x9D, 0xF3, 0xB2, 0x5F, 0xFA, +0x80, 0xFC, 0xC6, 0xF3, 0x07, 0x2A, 0x4F, 0xEA, 0x10, 0x69, 0xE0, 0x5C, 0x06, 0x90, 0x0A, 0x0E, 0x96, 0x48, 0x08, 0x93, +0x14, 0xF8, 0x0A, 0x30, 0x87, 0x5C, 0x18, 0xF8, 0x02, 0x10, 0x05, 0x93, 0xC5, 0xF3, 0x07, 0x26, 0xA3, 0x5C, 0x03, 0x9A, +0x0A, 0x97, 0xC2, 0xF3, 0x07, 0x4E, 0xA7, 0x5D, 0x10, 0xF8, 0x0E, 0x20, 0x18, 0xF8, 0x09, 0xB0, 0x14, 0xF8, 0x0C, 0x50, +0x38, 0x46, 0x06, 0x9F, 0x09, 0x90, 0x87, 0xEA, 0x0B, 0x0B, 0x05, 0x9F, 0x80, 0xEA, 0x0B, 0x0B, 0x69, 0x40, 0x87, 0x48, +0x79, 0x40, 0x51, 0x40, 0x10, 0xF8, 0x0A, 0x20, 0x5D, 0x40, 0x6A, 0x40, 0x18, 0xF8, 0x0E, 0x50, 0x14, 0xF8, 0x0E, 0xE0, +0x6A, 0x40, 0x09, 0x04, 0x41, 0xEA, 0x02, 0x21, 0x7F, 0x4A, 0x02, 0x9D, 0x12, 0xF8, 0x0C, 0x20, 0x5F, 0x46, 0x18, 0xF8, +0x0A, 0xB0, 0x14, 0xF8, 0x09, 0xA0, 0x10, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x53, 0x40, 0xC5, 0xF3, 0x07, 0x49, +0x06, 0x98, 0x18, 0xF8, 0x0C, 0x50, 0x76, 0x4A, 0x83, 0xEA, 0x0B, 0x0B, 0x0A, 0x9B, 0x18, 0xF8, 0x06, 0xC0, 0x5D, 0x40, +0x12, 0xF8, 0x09, 0x30, 0x92, 0x5D, 0x71, 0x4E, 0x8A, 0xEA, 0x00, 0x00, 0x50, 0x40, 0x08, 0x9A, 0xB6, 0x5C, 0x18, 0xF8, +0x02, 0x20, 0x8A, 0xEA, 0x06, 0x0A, 0x7B, 0x40, 0x0B, 0x9E, 0x05, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x18, 0xF8, 0x09, 0xC0, +0x14, 0xF8, 0x09, 0x90, 0x8E, 0xEA, 0x05, 0x05, 0x56, 0x40, 0x7D, 0x40, 0x1B, 0x04, 0x09, 0x9F, 0x80, 0xEA, 0x0C, 0x00, +0x8E, 0xEA, 0x0B, 0x0B, 0x43, 0xEA, 0x00, 0x20, 0x89, 0xEA, 0x06, 0x03, 0x41, 0xEA, 0x0B, 0x02, 0x02, 0x99, 0x00, 0x9E, +0x83, 0xEA, 0x07, 0x0B, 0x03, 0x9B, 0x89, 0xEA, 0x0A, 0x0A, 0x40, 0xEA, 0x0A, 0x0C, 0x5F, 0xFA, 0x83, 0xFE, 0x4F, 0xEA, +0x13, 0x69, 0xC1, 0xF3, 0x07, 0x20, 0xCB, 0xB2, 0x01, 0x99, 0x02, 0x93, 0x42, 0xEA, 0x05, 0x67, 0x04, 0x9A, 0x03, 0x97, +0xC1, 0xF3, 0x07, 0x4A, 0x4C, 0xEA, 0x0B, 0x65, 0x17, 0x60, 0x27, 0x5C, 0x55, 0x60, 0x36, 0x0E, 0x05, 0x95, 0x01, 0x97, +0x4F, 0x4D, 0x14, 0xF8, 0x0A, 0x70, 0x06, 0x97, 0x18, 0xF8, 0x0A, 0x70, 0x15, 0xF8, 0x00, 0xB0, 0xA2, 0x5D, 0x18, 0xF8, +0x06, 0x30, 0x08, 0x97, 0xC1, 0xF3, 0x07, 0x2C, 0x14, 0xF8, 0x0E, 0x10, 0x15, 0xF8, 0x0A, 0xA0, 0x18, 0xF8, 0x00, 0x00, +0x01, 0x9F, 0x09, 0x90, 0xA8, 0x5D, 0x0A, 0x90, 0x4B, 0x40, 0x02, 0x98, 0x00, 0x9E, 0x25, 0x5C, 0x18, 0xF8, 0x09, 0x00, +0x7B, 0x40, 0x83, 0xEA, 0x0A, 0x03, 0x14, 0xF8, 0x0C, 0xA0, 0x51, 0x40, 0x57, 0x46, 0x68, 0x40, 0x8B, 0xEA, 0x01, 0x0B, +0x00, 0x97, 0x3B, 0x49, 0x14, 0xF8, 0x09, 0xA0, 0x11, 0xF8, 0x09, 0x90, 0xCD, 0xF8, 0x2C, 0x90, 0x78, 0x40, 0x08, 0x9F, +0x8B, 0xEA, 0x07, 0x01, 0x35, 0x4F, 0x08, 0x91, 0x17, 0xF8, 0x0E, 0x90, 0x09, 0x99, 0x18, 0xF8, 0x0E, 0xE0, 0xC6, 0xF3, +0x07, 0x46, 0x82, 0xEA, 0x09, 0x02, 0x17, 0xF8, 0x06, 0xB0, 0x17, 0xF8, 0x0C, 0x90, 0x02, 0x9F, 0x18, 0xF8, 0x0C, 0xC0, +0x4A, 0x40, 0x2C, 0x49, 0x80, 0xEA, 0x0B, 0x00, 0x11, 0xF8, 0x07, 0xB0, 0x0A, 0x99, 0x8A, 0xEA, 0x05, 0x05, 0x89, 0xEA, +0x05, 0x05, 0x8E, 0xEA, 0x01, 0x0E, 0x18, 0xF8, 0x07, 0x90, 0x0B, 0x99, 0x89, 0xEA, 0x01, 0x09, 0x08, 0x99, 0x1B, 0x04, +0x43, 0xEA, 0x01, 0x21, 0x06, 0x9B, 0x8A, 0xEA, 0x0B, 0x0A, 0x18, 0xF8, 0x06, 0xB0, 0xA6, 0x5D, 0x01, 0x9F, 0x83, 0xEA, +0x0E, 0x0E, 0x85, 0xEA, 0x0B, 0x05, 0x87, 0xEA, 0x0E, 0x0E, 0x00, 0x04, 0x00, 0x9F, 0x8A, 0xEA, 0x0C, 0x0A, 0x5A, 0x40, +0x40, 0xEA, 0x05, 0x20, 0x86, 0xEA, 0x0A, 0x0A, 0x86, 0xEA, 0x09, 0x09, 0x11, 0x43, 0x87, 0xEA, 0x09, 0x09, 0x04, 0x9A, +0x07, 0x9E, 0x03, 0x9F, 0x05, 0x9B, 0x40, 0xEA, 0x0A, 0x00, 0x41, 0xEA, 0x0E, 0x61, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xE9, +0x02, 0x10, 0x35, 0x69, 0x6F, 0x40, 0x17, 0x60, 0x35, 0x46, 0x76, 0x69, 0x01, 0x97, 0x5E, 0x40, 0x56, 0x60, 0x00, 0x96, +0x2E, 0x46, 0xAD, 0x69, 0x69, 0x40, 0x91, 0x60, 0xF3, 0x69, 0x03, 0x91, 0x43, 0x40, 0x02, 0x93, 0xD3, 0x60, 0x0C, 0x9B, +0x06, 0xF1, 0x10, 0x01, 0x8B, 0x42, 0x07, 0x91, 0x7F, 0xF4, 0xC8, 0xAE, 0x06, 0xE0, 0x00, 0xBF, 0xE4, 0xC2, 0x15, 0x00, +0xE4, 0xC3, 0x15, 0x00, 0xE4, 0xC4, 0x15, 0x00, 0xDD, 0xF8, 0x00, 0xE0, 0x3E, 0x0E, 0x5F, 0xFA, 0x8E, 0xF2, 0xDD, 0xE9, +0x02, 0x39, 0x14, 0xF8, 0x06, 0xC0, 0xA2, 0x5C, 0x70, 0x46, 0x42, 0xEA, 0x0C, 0x62, 0x00, 0x92, 0x1D, 0x0E, 0x02, 0x9A, +0x65, 0x5D, 0xF9, 0xB2, 0x5F, 0xFA, 0x89, 0xF3, 0x00, 0x0E, 0x61, 0x5C, 0x20, 0x5C, 0xE3, 0x5C, 0xB8, 0x46, 0x5F, 0xFA, +0x82, 0xFC, 0x4F, 0xEA, 0x19, 0x67, 0x43, 0xEA, 0x00, 0x63, 0xE7, 0x5D, 0x14, 0xF8, 0x0C, 0x00, 0x41, 0xEA, 0x05, 0x61, +0xCE, 0xF3, 0x07, 0x25, 0x40, 0xEA, 0x07, 0x67, 0x65, 0x5D, 0xC9, 0xF3, 0x07, 0x20, 0x41, 0xEA, 0x05, 0x21, 0x14, 0xF8, +0x00, 0xB0, 0xC8, 0xF3, 0x07, 0x25, 0xC2, 0xF3, 0x07, 0x20, 0xCE, 0xF3, 0x07, 0x46, 0xC9, 0xF3, 0x07, 0x4A, 0xC2, 0xF3, +0x07, 0x4C, 0xC8, 0xF3, 0x07, 0x48, 0x65, 0x5D, 0x00, 0x9A, 0x20, 0x5C, 0x14, 0xF8, 0x0A, 0xE0, 0x14, 0xF8, 0x0C, 0xC0, +0x14, 0xF8, 0x08, 0x80, 0xA6, 0x5D, 0x47, 0xEA, 0x05, 0x27, 0x42, 0xEA, 0x0B, 0x24, 0x43, 0xEA, 0x00, 0x20, 0x04, 0x9A, +0x0D, 0x9D, 0x41, 0xEA, 0x0E, 0x41, 0x44, 0xEA, 0x0C, 0x44, 0x40, 0xEA, 0x08, 0x40, 0x47, 0xEA, 0x06, 0x46, 0xC2, 0xE9, +0x00, 0x14, 0xC2, 0xE9, 0x02, 0x06, 0xD5, 0xF8, 0xA0, 0x30, 0x59, 0x40, 0x11, 0x60, 0xD5, 0xF8, 0xA4, 0x30, 0x5C, 0x40, +0x54, 0x60, 0xD5, 0xF8, 0xA8, 0x30, 0x58, 0x40, 0x90, 0x60, 0xD5, 0xF8, 0xAC, 0x30, 0x5E, 0x40, 0xD6, 0x60, 0x0F, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0xD0, 0xE9, 0x01, 0x23, 0xF0, 0xB5, 0x19, 0x49, 0x05, 0x68, 0xC7, 0x68, 0x54, 0x04, 0x04, 0xF0, +0x80, 0x76, 0x01, 0xEA, 0xD5, 0x34, 0x34, 0x43, 0x6E, 0x00, 0x06, 0xF0, 0xFE, 0x36, 0x34, 0x43, 0x4F, 0xEA, 0x43, 0x4E, +0x7E, 0x04, 0x0E, 0xF0, 0x80, 0x7E, 0x04, 0x60, 0x01, 0xEA, 0xD2, 0x34, 0x52, 0x00, 0x06, 0xF0, 0x80, 0x7C, 0x44, 0xEA, +0x0E, 0x04, 0x01, 0xEA, 0xD3, 0x36, 0x02, 0xF0, 0xFE, 0x32, 0x5B, 0x00, 0x22, 0x43, 0x46, 0xEA, 0x0C, 0x06, 0x03, 0xF0, +0xFE, 0x33, 0x7C, 0x00, 0x33, 0x43, 0x01, 0xEA, 0xD7, 0x31, 0x04, 0xF0, 0xFE, 0x34, 0x21, 0x43, 0xC0, 0xE9, 0x01, 0x23, +0x2B, 0x06, 0x48, 0xBF, 0x81, 0xF0, 0x07, 0x41, 0xC1, 0x60, 0xF0, 0xBD, 0x01, 0x01, 0x01, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x29, 0x2A, 0xBD, 0xB0, 0x0B, 0xD8, 0x8B, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x00, 0x81, +0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x88, 0x46, 0x1D, 0x46, 0x31, 0xF8, 0x04, 0x3B, 0x06, 0x46, +0x23, 0xF4, 0x60, 0x53, 0x14, 0x46, 0x0D, 0xF1, 0x2E, 0x00, 0x12, 0x22, 0xAD, 0xF8, 0x2C, 0x30, 0x05, 0xF0, 0xC4, 0xFC, +0xD6, 0xE9, 0x14, 0x13, 0xD6, 0xE9, 0x16, 0x72, 0xC5, 0xF5, 0x7F, 0x40, 0xF4, 0x30, 0x80, 0xB2, 0x01, 0x90, 0xCD, 0xE9, +0x11, 0x37, 0xDF, 0xF8, 0xEC, 0xE1, 0xDF, 0xF8, 0xEC, 0xC1, 0x10, 0x91, 0x13, 0x92, 0x10, 0xAE, 0x0D, 0xF1, 0xD0, 0x0A, +0x01, 0x20, 0x02, 0xE0, 0x5E, 0xF8, 0x04, 0x0F, 0x10, 0x36, 0xC2, 0xF3, 0x07, 0x2B, 0x5F, 0xFA, 0x82, 0xF9, 0x1C, 0xF8, +0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x8B, 0xEA, 0x00, 0x00, 0x4F, 0xEA, 0x12, 0x6B, 0x40, 0xEA, 0x09, 0x60, 0xC2, 0xF3, +0x07, 0x49, 0x1C, 0xF8, 0x0B, 0xB0, 0x1C, 0xF8, 0x09, 0x90, 0x40, 0xEA, 0x0B, 0x40, 0x40, 0xEA, 0x09, 0x20, 0x41, 0x40, +0x4B, 0x40, 0x5F, 0x40, 0x7A, 0x40, 0x56, 0x45, 0xC6, 0xE9, 0x06, 0x72, 0xC6, 0xE9, 0x04, 0x13, 0xDA, 0xD1, 0x10, 0x22, +0x00, 0x21, 0x03, 0xA8, 0xCE, 0xF7, 0xF6, 0xFC, 0x0D, 0xF1, 0x0A, 0x06, 0x00, 0x21, 0x07, 0xA8, 0x10, 0x22, 0xCE, 0xF7, +0xEF, 0xFC, 0x0D, 0xF1, 0x1A, 0x07, 0x33, 0x46, 0x0D, 0xF1, 0x2A, 0x01, 0x33, 0xF8, 0x02, 0x2F, 0x31, 0xF8, 0x02, 0x0F, +0x9F, 0x42, 0x82, 0xEA, 0x00, 0x02, 0x1A, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x7B, 0xFD, 0x03, 0x9B, +0x0F, 0x9A, 0x6D, 0x08, 0x08, 0xEB, 0x45, 0x08, 0x53, 0x40, 0xA8, 0xF1, 0x02, 0x01, 0x08, 0xF1, 0x0A, 0x05, 0x03, 0x93, +0x0D, 0xF1, 0x0E, 0x02, 0x32, 0xF8, 0x02, 0x3F, 0x31, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x8D, 0x42, 0x13, 0x80, 0xF7, 0xD1, +0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x62, 0xFD, 0x01, 0x9B, 0x1C, 0x44, 0xA4, 0xB2, 0x10, 0x2C, 0x08, 0xF1, 0x0C, 0x09, +0x26, 0xD9, 0xA4, 0xF1, 0x11, 0x0A, 0xCA, 0xF3, 0x0B, 0x1A, 0x08, 0xEB, 0x0A, 0x18, 0x08, 0xF1, 0x1C, 0x08, 0x4D, 0x46, +0xAA, 0x1E, 0x33, 0x46, 0x05, 0xF1, 0x0E, 0x00, 0x33, 0xF8, 0x02, 0x1F, 0x32, 0xF8, 0x02, 0xCF, 0x81, 0xEA, 0x0C, 0x01, +0x90, 0x42, 0x19, 0x80, 0xF6, 0xD1, 0x10, 0x35, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x40, 0xFD, 0x45, 0x45, 0xEB, 0xD1, +0xCA, 0xEB, 0x0A, 0x33, 0x10, 0x3C, 0x04, 0xEB, 0x03, 0x14, 0x0A, 0xF1, 0x01, 0x0A, 0xA4, 0xB2, 0x09, 0xEB, 0x0A, 0x19, +0x07, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0x30, 0xFD, 0x07, 0xA8, 0xFF, 0xF7, 0x01, 0xFF, 0x10, 0x2C, 0x34, 0xD0, 0x65, 0x08, +0x07, 0xA8, 0xFF, 0xF7, 0xFB, 0xFE, 0x65, 0xB1, 0xA9, 0xF1, 0x02, 0x02, 0x02, 0xEB, 0x45, 0x0C, 0x39, 0x46, 0x31, 0xF8, +0x02, 0x3F, 0x32, 0xF8, 0x02, 0x0F, 0x43, 0x40, 0x94, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xE3, 0x07, 0x39, 0xD4, 0x80, 0x23, +0xA4, 0x08, 0x05, 0xF0, 0x01, 0x05, 0x3C, 0xAA, 0x05, 0xEB, 0x44, 0x04, 0x02, 0xEB, 0x44, 0x04, 0x34, 0xF8, 0xD4, 0x2C, +0x53, 0x40, 0x24, 0xF8, 0xD4, 0x3C, 0x3A, 0x46, 0x36, 0xF8, 0x02, 0x3F, 0x32, 0xF8, 0x02, 0x1F, 0xB7, 0x42, 0x83, 0xEA, +0x01, 0x03, 0x33, 0x80, 0xF6, 0xD1, 0x03, 0xA9, 0x10, 0xA8, 0xFF, 0xF7, 0xFB, 0xFC, 0xDD, 0xE9, 0x03, 0x01, 0x3D, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0xA9, 0xF1, 0x02, 0x02, 0x39, 0x46, 0x09, 0xF1, 0x0E, 0x09, 0x31, 0xF8, 0x02, 0x3F, 0x32, 0xF8, +0x02, 0x0F, 0x43, 0x40, 0x91, 0x45, 0x0B, 0x80, 0xF7, 0xD1, 0xDE, 0xE7, 0x08, 0x49, 0x09, 0x48, 0x4F, 0xF4, 0xD6, 0x72, +0xF3, 0xF7, 0x44, 0xF9, 0x00, 0x20, 0x01, 0x46, 0x3D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x19, 0xF8, 0x15, 0x30, 0x43, 0xF4, +0x00, 0x43, 0xC1, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xBC, 0xC2, 0x15, 0x00, +0xE4, 0xC2, 0x15, 0x00, 0x81, 0x04, 0x4F, 0xEA, 0xD0, 0x23, 0xC0, 0xF3, 0xC2, 0x22, 0x0C, 0xD4, 0x13, 0xF0, 0x06, 0x0F, +0x03, 0xF0, 0x06, 0x02, 0x11, 0xD1, 0x00, 0xF0, 0x7F, 0x00, 0x62, 0xB9, 0x03, 0x28, 0x8C, 0xBF, 0x00, 0x20, 0x01, 0x20, +0x70, 0x47, 0x07, 0x2A, 0x0C, 0xD0, 0x03, 0xF0, 0x06, 0x02, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x2A, 0xF2, 0xD0, 0x00, 0x20, +0x70, 0x47, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x2A, 0xF9, 0xD1, 0xEB, 0xE7, 0x13, 0xF0, 0x06, 0x0F, 0x0C, 0xBF, 0x01, 0x20, +0x00, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x40, 0x7F, 0x87, 0xB0, 0x4F, 0xF0, 0xFF, 0x34, 0x09, 0x28, +0x05, 0x94, 0x02, 0xD9, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x89, 0x46, 0xF9, 0x6C, 0xC9, 0x4E, 0x8C, 0x6C, 0x0D, 0x6D, +0x4F, 0xF4, 0x1E, 0x71, 0x01, 0xFB, 0x00, 0x60, 0x90, 0x46, 0x90, 0xF8, 0x22, 0x10, 0xFA, 0x8B, 0x14, 0xF4, 0x00, 0x5F, +0x08, 0xBF, 0x01, 0x23, 0x22, 0xF4, 0x00, 0x54, 0x05, 0xF4, 0x80, 0x05, 0x02, 0xF4, 0x00, 0x52, 0xFF, 0x29, 0x01, 0x95, +0xFC, 0x83, 0x02, 0x92, 0xE0, 0xD0, 0xBD, 0x4A, 0xD0, 0xF8, 0x4C, 0xA1, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, +0x50, 0xDB, 0xBA, 0xF8, 0xB4, 0x10, 0xBA, 0x6C, 0x48, 0x1E, 0x05, 0xAC, 0xC0, 0xB2, 0x01, 0xEB, 0x41, 0x0E, 0x00, 0x90, +0x03, 0x94, 0x0A, 0xEB, 0x8E, 0x0E, 0x02, 0xF1, 0x3C, 0x00, 0x02, 0xF1, 0x4C, 0x0B, 0xA4, 0x46, 0x50, 0xF8, 0x04, 0x6B, +0xC6, 0xF3, 0x0D, 0x06, 0x79, 0xB1, 0x74, 0x46, 0x00, 0x22, 0x02, 0xE0, 0x01, 0x32, 0x8A, 0x42, 0x09, 0xD0, 0x34, 0xF8, +0x02, 0x5C, 0xB5, 0x42, 0xA4, 0xF1, 0x0C, 0x04, 0xF6, 0xD1, 0x00, 0x9C, 0xA2, 0x1A, 0x8C, 0xF8, 0x00, 0x20, 0x00, 0x2B, +0x40, 0xF0, 0xAD, 0x80, 0x83, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0xE3, 0xD1, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, +0xC3, 0xF3, 0x82, 0x03, 0x93, 0x42, 0x27, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x64, 0xD0, 0xBA, 0xF8, 0x92, 0x20, 0xBA, 0xF8, +0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x7E, 0x10, 0xBA, 0xF8, +0x7C, 0x20, 0x1F, 0xFA, 0x89, 0xF9, 0xA9, 0xEB, 0x08, 0x03, 0x0B, 0x44, 0x91, 0x44, 0xAA, 0xF8, 0x7E, 0x30, 0xAA, 0xF8, +0x7C, 0x90, 0x87, 0xE7, 0xBA, 0xF1, 0x00, 0x0F, 0xAB, 0xD1, 0x90, 0x49, 0x90, 0x48, 0x00, 0x93, 0x4F, 0xF4, 0x18, 0x62, +0xF3, 0xF7, 0x64, 0xF8, 0x00, 0x9B, 0xA2, 0xE7, 0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x01, 0x33, 0xAA, 0xF8, +0x90, 0x30, 0x01, 0x9B, 0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x00, 0x2B, 0xD7, 0xD1, 0x02, 0x9B, 0x00, 0x2B, 0x3A, 0xD0, +0x83, 0x4E, 0x85, 0x4D, 0x03, 0x9F, 0x00, 0x24, 0xB9, 0xF1, 0x00, 0x0F, 0x24, 0xD0, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, +0x00, 0xF0, 0xEC, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0x41, 0x81, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, +0x82, 0x02, 0x40, 0xF2, 0x7A, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, +0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x71, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, +0x02, 0x81, 0x01, 0x34, 0x04, 0x2C, 0xD7, 0xD1, 0x00, 0x23, 0x8A, 0xF8, 0x9B, 0x30, 0x3B, 0xE7, 0xBA, 0xF8, 0x92, 0x20, +0xBA, 0xF8, 0x90, 0x30, 0x01, 0x32, 0x01, 0x33, 0xAA, 0xF8, 0x92, 0x20, 0xAA, 0xF8, 0x90, 0x30, 0xC1, 0xE7, 0x66, 0x4E, +0x67, 0x4D, 0x03, 0x9F, 0x1C, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x29, 0xAF, 0x17, 0xF8, 0x01, 0x3B, 0xFF, 0x2B, +0x00, 0xF0, 0xA5, 0x80, 0x00, 0x2C, 0x00, 0xF0, 0xF0, 0x80, 0x03, 0xEB, 0x43, 0x02, 0xB8, 0xF1, 0x01, 0x0F, 0x0A, 0xEB, +0x82, 0x02, 0x40, 0xF2, 0x43, 0x81, 0x92, 0x88, 0x59, 0x00, 0x19, 0x44, 0x0A, 0xEB, 0x81, 0x01, 0x02, 0x32, 0x8A, 0x80, +0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x53, 0x4A, 0x12, 0x68, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, +0xB6, 0x80, 0x01, 0x34, 0x04, 0x2C, 0xD6, 0xD1, 0x02, 0xE7, 0x97, 0xF8, 0x36, 0x30, 0x9A, 0xF8, 0xA3, 0x20, 0xC3, 0xF3, +0x82, 0x03, 0x93, 0x42, 0x38, 0xD0, 0x01, 0x9B, 0x00, 0x2B, 0x69, 0xD1, 0xBA, 0xF8, 0x92, 0x30, 0xBA, 0xF8, 0x90, 0x20, +0x01, 0x33, 0x1F, 0xFA, 0x89, 0xF0, 0xAA, 0xF8, 0x92, 0x30, 0x02, 0x9B, 0x02, 0x44, 0xAA, 0xF8, 0x90, 0x20, 0x00, 0x2B, +0x40, 0xF0, 0x8A, 0x80, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0xE3, 0xAE, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, +0x04, 0x33, 0x3C, 0x4A, 0x5D, 0x88, 0x19, 0x88, 0x14, 0x68, 0xA0, 0xEB, 0x08, 0x02, 0x2A, 0x44, 0x01, 0x44, 0x92, 0xB2, +0x89, 0xB2, 0x5A, 0x80, 0x19, 0x80, 0xB4, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xCE, 0xAE, 0x91, 0x42, 0xBF, 0xF4, +0xCB, 0xAE, 0x33, 0x49, 0x34, 0x48, 0x4F, 0xF4, 0x1F, 0x62, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0xA8, 0xBF, +0xBA, 0xF8, 0x90, 0x30, 0xBA, 0xF8, 0x92, 0x20, 0x1F, 0xFA, 0x89, 0xF0, 0x03, 0x44, 0xAA, 0xF8, 0x90, 0x30, 0x01, 0x9B, +0x01, 0x32, 0xAA, 0xF8, 0x92, 0x20, 0x8B, 0xBB, 0x02, 0x9B, 0x00, 0x2B, 0x52, 0xD1, 0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, +0x00, 0xF0, 0xFD, 0x80, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x04, 0x33, 0xB9, 0xEB, 0x48, 0x0F, 0x9A, 0xF8, 0xA4, 0x20, +0x80, 0xF0, 0xE9, 0x80, 0x01, 0x2A, 0x40, 0xF2, 0xF8, 0x80, 0x02, 0x2A, 0x03, 0xD0, 0x00, 0x2B, 0x3F, 0xF4, 0x9A, 0xAE, +0xB9, 0xE7, 0xDA, 0xF8, 0x00, 0x20, 0xA2, 0xF5, 0x92, 0x32, 0xF8, 0x3A, 0xCA, 0xF8, 0x00, 0x20, 0x00, 0x2B, 0x3F, 0xF4, +0x8F, 0xAE, 0xAE, 0xE7, 0xBA, 0xF8, 0x90, 0x20, 0xBA, 0xF8, 0x92, 0x30, 0x1F, 0xFA, 0x89, 0xF0, 0x02, 0x44, 0x01, 0x33, +0xAA, 0xF8, 0x90, 0x20, 0xAA, 0xF8, 0x92, 0x30, 0x0A, 0xF1, 0x7C, 0x03, 0x9F, 0xE7, 0x00, 0x2C, 0x75, 0xD0, 0xB8, 0xF1, +0x01, 0x0F, 0x7F, 0xF6, 0x79, 0xAE, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x6C, 0xE7, 0x00, 0x2C, 0x00, 0xF0, +0x8C, 0x80, 0xB8, 0xF1, 0x01, 0x0F, 0x7F, 0xF6, 0x2D, 0xAF, 0xA9, 0xF1, 0x02, 0x09, 0xA8, 0xF1, 0x02, 0x08, 0x24, 0xE7, +0x68, 0x65, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xE4, 0xC5, 0x15, 0x00, +0x9D, 0xF8, 0x14, 0x30, 0xFF, 0x2B, 0x3F, 0xF4, 0x19, 0xAF, 0x0C, 0x22, 0x02, 0xFB, 0x03, 0xA3, 0x00, 0x22, 0x04, 0x33, +0x8A, 0xF8, 0x9B, 0x20, 0x71, 0xE7, 0x03, 0xEB, 0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, +0xBF, 0xF4, 0x41, 0xAF, 0x40, 0xF6, 0x61, 0x22, 0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x28, 0xFF, 0x39, 0xE7, 0x03, 0xEB, +0x43, 0x03, 0x0A, 0xEB, 0x83, 0x03, 0x9A, 0x88, 0xDB, 0x88, 0x9A, 0x42, 0xBF, 0xF4, 0xF5, 0xAE, 0x40, 0xF6, 0x33, 0x22, +0x31, 0x46, 0x28, 0x46, 0xF2, 0xF7, 0x18, 0xFF, 0xED, 0xE6, 0xB8, 0xF1, 0x00, 0x0F, 0x6C, 0xD0, 0x03, 0xEB, 0x43, 0x01, +0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, 0x8A, 0x80, +0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x73, 0xD9, 0x59, 0x00, 0x04, 0xE7, 0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x03, 0xEB, +0x43, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x08, 0xF1, 0xFF, 0x38, 0x8A, 0x88, 0x01, 0x32, 0x92, 0xB2, 0xB8, 0xF1, 0x01, 0x0F, +0x8A, 0x80, 0x09, 0xF1, 0xFF, 0x39, 0x19, 0xB2, 0x5B, 0xD9, 0x59, 0x00, 0xB3, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, +0x03, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, 0xCF, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, +0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, +0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, 0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, +0x9A, 0xE6, 0xB8, 0xF1, 0x02, 0x0F, 0x7F, 0xF6, 0xA1, 0xAE, 0xA9, 0xF1, 0x03, 0x09, 0xA8, 0xF1, 0x03, 0x08, 0x01, 0x24, +0x72, 0xE6, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, 0xDF, 0xE7, 0x92, 0x88, 0x1F, 0xFA, 0x88, 0xF8, 0x19, 0xB2, +0x01, 0xEB, 0x41, 0x01, 0x0A, 0xEB, 0x81, 0x01, 0x1F, 0xFA, 0x89, 0xF9, 0xC8, 0x88, 0xA9, 0xEB, 0x08, 0x08, 0x4A, 0x44, +0x40, 0x44, 0x4F, 0xF0, 0x00, 0x09, 0x8A, 0x80, 0xC8, 0x80, 0xC8, 0x46, 0xB2, 0xE6, 0x03, 0xEB, 0x43, 0x02, 0x0A, 0xEB, +0x82, 0x02, 0xA0, 0x46, 0x92, 0x88, 0x19, 0xB2, 0xE6, 0xE7, 0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x01, 0x3A, 0x8A, 0xF8, +0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xB0, 0xAD, 0xCF, 0xE6, 0x02, 0x9B, 0x04, 0xE7, 0x1F, 0xFA, 0x88, 0xF8, 0xB3, 0xE7, +0x1F, 0xFA, 0x88, 0xF8, 0xD4, 0xE7, 0x01, 0x32, 0x8A, 0xF8, 0xA4, 0x20, 0x00, 0x2B, 0x3F, 0xF4, 0xA1, 0xAD, 0xC0, 0xE6, +0x03, 0x88, 0xA3, 0xB1, 0x10, 0xB4, 0x42, 0x88, 0x44, 0x7A, 0x00, 0x21, 0x12, 0x04, 0x01, 0x72, 0xB2, 0xFB, 0xF3, 0xF1, +0x8C, 0xB1, 0x83, 0x88, 0x5D, 0xF8, 0x04, 0x4B, 0x03, 0xEB, 0x43, 0x03, 0x0B, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x83, 0x80, +0x01, 0x23, 0x43, 0x72, 0x70, 0x47, 0x03, 0x7A, 0xFF, 0x2B, 0x1C, 0xBF, 0x01, 0x33, 0x03, 0x72, 0x70, 0x47, 0x9A, 0x42, +0x24, 0xBF, 0x01, 0xF1, 0xFF, 0x33, 0x83, 0x80, 0x4F, 0xF0, 0x01, 0x03, 0x38, 0xBF, 0x84, 0x80, 0x43, 0x72, 0x5D, 0xF8, +0x04, 0x4B, 0x70, 0x47, 0xF8, 0xB5, 0x06, 0x46, 0x88, 0x04, 0x0C, 0x46, 0xC1, 0xF3, 0xC2, 0x25, 0x19, 0xD4, 0xCB, 0x0A, +0x13, 0xF0, 0x06, 0x0F, 0x40, 0xD1, 0xCF, 0xB2, 0x01, 0xF0, 0x7F, 0x05, 0x05, 0xF0, 0xF8, 0xF9, 0x17, 0xF0, 0x7C, 0x0F, +0x5B, 0xD1, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0xE0, 0xB6, 0xF8, 0xAA, 0x30, 0xEB, 0x40, 0xD9, 0x07, 0x59, 0xD4, 0x6B, 0x1E, +0x95, 0x42, 0xDD, 0xB2, 0xF6, 0xD8, 0x20, 0x46, 0xF8, 0xBD, 0x07, 0x2D, 0x47, 0xD0, 0x04, 0x3D, 0x05, 0xF0, 0xE2, 0xF9, +0x04, 0xF0, 0x0F, 0x02, 0x01, 0x2D, 0xF4, 0xD8, 0xDF, 0xE8, 0x05, 0xF0, 0x01, 0x0E, 0x72, 0xB3, 0x53, 0x1E, 0x24, 0xF0, +0x0F, 0x04, 0x96, 0xF8, 0xB1, 0x20, 0x23, 0x43, 0x98, 0xB2, 0x00, 0x2A, 0xE8, 0xD0, 0x40, 0xF4, 0x00, 0x70, 0xF8, 0xBD, +0x0A, 0xB3, 0x24, 0xF0, 0x0F, 0x03, 0x51, 0x1E, 0x0B, 0x43, 0x98, 0xB2, 0x63, 0x04, 0xDD, 0xD5, 0x03, 0x2A, 0x03, 0xD0, +0x96, 0xF8, 0xBD, 0x30, 0x99, 0x42, 0xD7, 0xDD, 0x20, 0xF4, 0x80, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0xC4, 0xF3, 0xC1, 0x05, +0x05, 0xF0, 0xB8, 0xF9, 0x35, 0x44, 0x04, 0xF0, 0x07, 0x03, 0x05, 0xE0, 0x95, 0xF8, 0xA6, 0x20, 0xCB, 0xB2, 0xDA, 0x40, +0xD2, 0x07, 0x24, 0xD4, 0x59, 0x1E, 0x00, 0x2B, 0xF6, 0xD1, 0x96, 0xF8, 0xAE, 0x30, 0x03, 0x2B, 0xBD, 0xD8, 0x43, 0xB3, +0x96, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x43, 0xEA, 0x82, 0x23, 0x03, 0x43, 0x98, 0xB2, 0xF8, 0xBD, 0x05, 0xF0, +0x9B, 0xF9, 0x20, 0x46, 0xB0, 0xE7, 0x96, 0xF8, 0xAD, 0x20, 0x04, 0x2A, 0x38, 0xBF, 0x04, 0x22, 0xA5, 0xE7, 0x24, 0xF0, +0x7F, 0x04, 0x44, 0xEA, 0x05, 0x00, 0x00, 0x2D, 0xA4, 0xD1, 0x40, 0xF4, 0x80, 0x63, 0x98, 0xB2, 0xF8, 0xBD, 0x96, 0xF8, +0xB1, 0x20, 0x24, 0xF0, 0x07, 0x04, 0x44, 0xEA, 0x03, 0x00, 0x00, 0x2A, 0x98, 0xD0, 0x40, 0xF4, 0x00, 0x73, 0x98, 0xB2, +0xF8, 0xBD, 0x4F, 0xF4, 0x80, 0x60, 0xF8, 0xBD, 0x8A, 0x04, 0x30, 0xB4, 0xC1, 0xF3, 0xC2, 0x23, 0x20, 0xD4, 0xCA, 0x0A, +0x12, 0xF0, 0x06, 0x0F, 0x26, 0xD1, 0x11, 0xF0, 0x7C, 0x0F, 0x01, 0xF0, 0x7F, 0x03, 0x71, 0xD1, 0x90, 0xF8, 0xAE, 0x40, +0x03, 0x2C, 0x28, 0xBF, 0x03, 0x24, 0x04, 0xE0, 0xB0, 0xF8, 0xAA, 0x20, 0xDA, 0x40, 0xD5, 0x07, 0x74, 0xD4, 0x5A, 0x1C, +0xA3, 0x42, 0xD3, 0xB2, 0xF6, 0xD3, 0x90, 0xF8, 0xA5, 0x30, 0x01, 0x2B, 0x01, 0xD9, 0xD9, 0x02, 0x89, 0xB2, 0x08, 0x46, +0x30, 0xBC, 0x70, 0x47, 0x07, 0x2B, 0xFA, 0xD0, 0x04, 0x3B, 0x01, 0xF0, 0x0F, 0x02, 0x01, 0x2B, 0xF5, 0xD8, 0xDF, 0xE8, +0x03, 0xF0, 0x15, 0x30, 0xC1, 0xF3, 0xC1, 0x04, 0x90, 0xF8, 0xAC, 0x50, 0x04, 0x44, 0x01, 0xF0, 0x07, 0x03, 0x04, 0xE0, +0x94, 0xF8, 0xA6, 0x20, 0xDA, 0x40, 0xD2, 0x07, 0x45, 0xD4, 0x5A, 0x1C, 0x9D, 0x42, 0xD3, 0xB2, 0xF6, 0xD8, 0x08, 0x46, +0x30, 0xBC, 0x70, 0x47, 0x90, 0xF8, 0xAC, 0x30, 0x93, 0x42, 0xDA, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, +0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x93, 0x42, 0xCF, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x01, 0x32, +0x90, 0xF8, 0xB1, 0x30, 0x11, 0x43, 0x89, 0xB2, 0x00, 0x2B, 0xC6, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0xC3, 0xE7, 0x90, 0xF8, +0xAC, 0x30, 0x93, 0x42, 0xBF, 0xD9, 0xB0, 0xF8, 0xA6, 0x30, 0xC1, 0xF3, 0x02, 0x14, 0x64, 0x00, 0x23, 0x41, 0x03, 0xF0, +0x03, 0x03, 0x5B, 0x00, 0x07, 0x33, 0x93, 0x42, 0xB3, 0xD9, 0x21, 0xF0, 0x0F, 0x01, 0x53, 0x1C, 0x0B, 0x43, 0x99, 0xB2, +0x5B, 0x04, 0xAC, 0xD5, 0x01, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xBD, 0x30, 0x93, 0x42, 0xA6, 0xD8, 0x21, 0xF4, 0x80, 0x41, +0x89, 0xB2, 0xA2, 0xE7, 0x90, 0xF8, 0xAE, 0x40, 0x95, 0xE7, 0x90, 0xF8, 0xB1, 0x20, 0x21, 0xF0, 0x07, 0x01, 0x19, 0x43, +0x00, 0x2A, 0x98, 0xD0, 0x41, 0xF4, 0x00, 0x71, 0x89, 0xB2, 0x94, 0xE7, 0x21, 0xF0, 0x7F, 0x01, 0x19, 0x43, 0x90, 0xE7, +0x2D, 0xE9, 0xF0, 0x4F, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x85, 0xB0, 0x4C, 0x89, 0xE6, 0x0A, 0xC4, 0xF3, +0x80, 0x22, 0x01, 0x92, 0x71, 0x07, 0x4F, 0xEA, 0x54, 0x22, 0x05, 0x46, 0x06, 0xF0, 0x04, 0x03, 0xC4, 0xF3, 0xC2, 0x27, +0x02, 0x92, 0xC4, 0xF3, 0x40, 0x2B, 0xC4, 0xF3, 0xC1, 0x1A, 0x23, 0xD5, 0x07, 0x2F, 0x50, 0xD0, 0xC4, 0xF3, 0x02, 0x19, +0x04, 0xF0, 0x0F, 0x04, 0xDF, 0xF8, 0x70, 0x83, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x22, 0xDA, +0x05, 0x2F, 0x27, 0xD9, 0x40, 0xF2, 0xB5, 0x22, 0xCA, 0x49, 0xCB, 0x48, 0x03, 0x93, 0xF2, 0xF7, 0x0B, 0xFD, 0x95, 0xF8, +0xA5, 0x20, 0x03, 0x9B, 0x05, 0x2A, 0x14, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0xD6, 0x00, 0xD6, 0x00, 0x31, 0x01, 0x31, 0x01, +0xF4, 0x00, 0x45, 0x01, 0x16, 0xF0, 0x06, 0x09, 0x26, 0xD1, 0x04, 0xF0, 0x7F, 0x04, 0xDF, 0xF8, 0x2C, 0x83, 0xD8, 0xF8, +0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x06, 0xDB, 0x05, 0x2F, 0x17, 0xD8, 0xDF, 0xE8, 0x07, 0xF0, 0x22, 0x22, +0x0F, 0x0F, 0x50, 0x91, 0x95, 0xF8, 0xA5, 0x10, 0x05, 0x29, 0xF4, 0xD8, 0xDF, 0xE8, 0x11, 0xF0, 0xBD, 0x00, 0xBD, 0x00, +0x15, 0x01, 0x15, 0x01, 0xD8, 0x00, 0x29, 0x01, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, +0xDF, 0x80, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC4, 0xF3, 0xC1, 0x09, 0x04, 0xF0, 0x07, 0x04, 0xD5, 0xE7, 0x4F, 0xF0, +0x00, 0x09, 0x4C, 0x46, 0xAE, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0x2C, 0x04, 0xD8, 0x95, 0xF8, +0xB2, 0x10, 0x01, 0x29, 0x00, 0xF0, 0x7B, 0x81, 0x00, 0x2A, 0xE6, 0xDA, 0xBB, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x2E, 0x81, +0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x1C, 0x81, 0xB9, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0xDC, 0x81, 0x95, 0xF8, 0xAD, 0x30, +0xA3, 0x42, 0x00, 0xF2, 0xC9, 0x81, 0x95, 0xF8, 0xAE, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xEE, 0x81, 0xB5, 0xF8, 0xAA, 0x30, +0x23, 0xFA, 0x04, 0xF4, 0xE2, 0x07, 0xCA, 0xD4, 0x93, 0x49, 0x95, 0x48, 0x40, 0xF2, 0x06, 0x32, 0x3B, 0xE0, 0xD8, 0xF8, +0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xDA, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0xCB, 0x81, 0x95, 0xF8, +0xB1, 0x30, 0x5B, 0x45, 0xC0, 0xF0, 0x52, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0x3F, 0x82, 0x95, 0xF8, +0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0x2C, 0x82, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0x19, 0x82, 0xB5, 0xF8, +0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x02, 0x13, 0x41, 0x03, 0xF0, 0x03, 0x03, 0x07, 0x33, 0x9C, 0x42, 0x00, 0xF3, 0x82, 0x81, +0x06, 0x2C, 0x00, 0xF0, 0x3E, 0x81, 0x09, 0x2C, 0x97, 0xD1, 0xBA, 0xF1, 0x00, 0x0F, 0x40, 0xF0, 0x4B, 0x82, 0xB9, 0xF1, +0x02, 0x0F, 0x90, 0xD0, 0xB9, 0xF1, 0x05, 0x0F, 0x8D, 0xD0, 0x75, 0x49, 0x77, 0x48, 0x4F, 0xF4, 0x48, 0x72, 0x05, 0xB0, +0xBD, 0xE8, 0xF0, 0x4F, 0xF2, 0xF7, 0x5C, 0xBC, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, +0x7E, 0xAF, 0x02, 0x9B, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0x00, 0xF0, 0x21, 0x82, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, +0xC0, 0xF0, 0x9E, 0x81, 0x95, 0xF8, 0xB0, 0x30, 0x4B, 0x45, 0xC0, 0xF0, 0xD1, 0x81, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, +0xC0, 0xF0, 0xBE, 0x81, 0xB5, 0xF8, 0xA6, 0x30, 0x4F, 0xEA, 0x49, 0x09, 0x43, 0xFA, 0x09, 0xF3, 0x03, 0xF0, 0x03, 0x03, +0x5B, 0x00, 0x07, 0x33, 0x9C, 0x42, 0x7F, 0xF7, 0x5C, 0xAF, 0x5C, 0x49, 0x5F, 0x48, 0x40, 0xF2, 0x2F, 0x32, 0xCC, 0xE7, +0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x36, 0xAF, 0x16, 0xF0, 0x06, 0x0F, 0x40, 0xF0, +0x2A, 0x81, 0x05, 0x2F, 0x3F, 0xF6, 0x49, 0xAF, 0x01, 0xA3, 0x53, 0xF8, 0x27, 0xF0, 0x00, 0xBF, 0xE7, 0x21, 0x15, 0x00, +0xE7, 0x21, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x8D, 0x23, 0x15, 0x00, 0x43, 0x22, 0x15, 0x00, 0xC5, 0x22, 0x15, 0x00, +0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x60, 0xD8, 0x00, 0x2A, 0xBF, 0xF6, +0x14, 0xAF, 0x04, 0x2F, 0x3F, 0xF4, 0x6B, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0x38, 0xAF, 0x42, 0x49, 0x46, 0x48, 0x4F, 0xF4, +0x36, 0x72, 0xF2, 0xF7, 0xF9, 0xFB, 0x06, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x40, 0xF0, 0x64, 0x81, 0x95, 0xF8, 0xB1, 0x30, +0x5B, 0x45, 0xC0, 0xF0, 0x51, 0x81, 0x95, 0xF8, 0xAF, 0x30, 0x53, 0x45, 0xC0, 0xF0, 0xD5, 0x80, 0x95, 0xF8, 0xB0, 0x30, +0x4B, 0x45, 0xC0, 0xF0, 0xC2, 0x80, 0x95, 0xF8, 0xAC, 0x30, 0xA3, 0x42, 0xC0, 0xF0, 0xD9, 0x80, 0x4D, 0x44, 0x95, 0xF8, +0xA6, 0x30, 0x23, 0xFA, 0x04, 0xF4, 0xE3, 0x07, 0x3F, 0xF5, 0x01, 0xAF, 0x2E, 0x49, 0x34, 0x48, 0x40, 0xF2, 0x12, 0x32, +0x71, 0xE7, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x77, 0xD8, 0x00, 0x2A, +0xBF, 0xF6, 0xD7, 0xAE, 0x00, 0x2B, 0xA2, 0xD0, 0x25, 0x49, 0x2C, 0x48, 0x40, 0xF2, 0xCA, 0x22, 0xF2, 0xF7, 0xC0, 0xFB, +0xCD, 0xE6, 0xD8, 0xF8, 0x00, 0x20, 0xB2, 0xF9, 0x00, 0x20, 0x95, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x56, 0xD8, 0x00, 0x2A, +0xBF, 0xF6, 0xC3, 0xAE, 0x05, 0x2F, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x2F, 0x3F, 0xF4, 0xE7, 0xAE, 0x19, 0x49, 0x21, 0x48, +0x40, 0xF2, 0xE7, 0x22, 0xF2, 0xF7, 0xA8, 0xFB, 0xB5, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0xB3, 0xAE, 0x04, 0x2F, 0x3F, 0xF4, +0x0A, 0xAF, 0x13, 0x49, 0x1B, 0x48, 0x4F, 0xF4, 0x37, 0x72, 0xF2, 0xF7, 0x9B, 0xFB, 0xA8, 0xE6, 0x0F, 0x49, 0x19, 0x48, +0x40, 0xF2, 0x02, 0x32, 0xF2, 0xF7, 0x94, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, +0xD7, 0xAE, 0xB4, 0xE6, 0x08, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xF2, 0xF7, 0x86, 0xFB, 0xD8, 0xF8, 0x00, 0x30, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xA8, 0xAE, 0xBA, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0xC5, 0xAE, 0xDF, 0xE7, +0x70, 0x79, 0x15, 0x00, 0x08, 0xC6, 0x15, 0x00, 0xB0, 0xC7, 0x15, 0x00, 0xF0, 0xC8, 0x15, 0x00, 0xA8, 0xC9, 0x15, 0x00, +0xA8, 0xC6, 0x15, 0x00, 0x3C, 0xC8, 0x15, 0x00, 0x48, 0xC6, 0x15, 0x00, 0x04, 0xC7, 0x15, 0x00, 0xE8, 0xC6, 0x15, 0x00, +0x64, 0xC7, 0x15, 0x00, 0x58, 0xC7, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x00, 0x2A, 0xBF, 0xF6, 0x6C, 0xAE, 0x05, 0x2F, +0x3F, 0xF4, 0x05, 0xAF, 0xA9, 0x49, 0xAA, 0x48, 0x40, 0xF2, 0xEB, 0x22, 0xF2, 0xF7, 0x54, 0xFB, 0x61, 0xE6, 0x00, 0x2A, +0xBF, 0xF6, 0x5F, 0xAE, 0xBA, 0x1E, 0x01, 0x2A, 0x7F, 0xF6, 0x54, 0xAF, 0xA2, 0x49, 0xA4, 0x48, 0x40, 0xF2, 0xCE, 0x22, +0xF2, 0xF7, 0x46, 0xFB, 0x53, 0xE6, 0x00, 0x2A, 0xBF, 0xF6, 0x6B, 0xAE, 0x01, 0x9B, 0x00, 0x2B, 0x7F, 0xF4, 0x80, 0xAE, +0x40, 0xF2, 0xFB, 0x22, 0x9A, 0x49, 0x9D, 0x48, 0xF2, 0xF7, 0x38, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x20, +0x72, 0xE6, 0xBA, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x58, 0xAE, 0xB9, 0xF1, 0x03, 0x0F, 0x03, 0xD0, 0xB9, 0xF1, 0x06, 0x0F, +0x7F, 0xF4, 0x51, 0xAE, 0x90, 0x49, 0x94, 0x48, 0x40, 0xF2, 0x1F, 0x32, 0xC1, 0xE6, 0x8E, 0x49, 0x92, 0x48, 0x4F, 0xF4, +0x44, 0x72, 0xF2, 0xF7, 0x1D, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x31, 0xAF, +0x3D, 0xE6, 0x87, 0x49, 0x8C, 0x48, 0x40, 0xF2, 0x0F, 0x32, 0xF2, 0xF7, 0x0F, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1E, 0xAF, 0x2F, 0xE6, 0x80, 0x49, 0x86, 0x48, 0x40, 0xF2, 0x11, 0x32, 0xF2, 0xF7, +0x01, 0xFB, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x1A, 0xAF, 0x21, 0xE6, 0x79, 0x49, +0x80, 0x48, 0x40, 0xF2, 0xC2, 0x22, 0xF2, 0xF7, 0xF3, 0xFA, 0x00, 0xE6, 0x75, 0x49, 0x7E, 0x48, 0x40, 0xF2, 0x1E, 0x32, +0xF2, 0xF7, 0xEC, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x71, 0xAE, 0x0C, 0xE6, +0x6E, 0x49, 0x78, 0x48, 0x4F, 0xF4, 0x41, 0x72, 0xF2, 0xF7, 0xDE, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xFF, 0xF6, 0x2A, 0xAE, 0xFE, 0xE5, 0x67, 0x49, 0x72, 0x48, 0x40, 0xF2, 0x03, 0x32, 0xF2, 0xF7, 0xD0, 0xFA, +0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x17, 0xAE, 0xF0, 0xE5, 0x60, 0x49, 0x6C, 0x48, +0x40, 0xF2, 0x19, 0x32, 0xF2, 0xF7, 0xC2, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, +0x28, 0xAE, 0xE2, 0xE5, 0x59, 0x49, 0x66, 0x48, 0x40, 0xF2, 0x05, 0x32, 0xF2, 0xF7, 0xB4, 0xFA, 0xD8, 0xF8, 0x00, 0x30, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x05, 0xAE, 0xD4, 0xE5, 0x52, 0x49, 0x58, 0x48, 0x4F, 0xF4, 0x4B, 0x72, +0xF2, 0xF7, 0xA6, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x55, 0xAE, 0xC6, 0xE5, +0x4B, 0x49, 0x59, 0x48, 0x40, 0xF2, 0x0E, 0x32, 0xF2, 0xF7, 0x98, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xFF, 0xF6, 0xA2, 0xAE, 0xB8, 0xE5, 0x44, 0x49, 0x50, 0x48, 0x40, 0xF2, 0x0D, 0x32, 0xF2, 0xF7, 0x8A, 0xFA, +0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x8F, 0xAE, 0xAA, 0xE5, 0x3D, 0x49, 0x44, 0x48, +0x40, 0xF2, 0x2E, 0x32, 0xF2, 0xF7, 0x7C, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, +0x35, 0xAE, 0x9C, 0xE5, 0x36, 0x49, 0x3B, 0x48, 0x40, 0xF2, 0x2D, 0x32, 0xF2, 0xF7, 0x6E, 0xFA, 0xD8, 0xF8, 0x00, 0x30, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0x22, 0xAE, 0x8E, 0xE5, 0x2F, 0x49, 0x36, 0x48, 0x40, 0xF2, 0x1D, 0x32, +0xF2, 0xF7, 0x60, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xDA, 0xAD, 0x80, 0xE5, +0x28, 0x49, 0x2D, 0x48, 0x4F, 0xF4, 0x47, 0x72, 0xF2, 0xF7, 0x52, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xFF, 0xF6, 0xC7, 0xAD, 0x72, 0xE5, 0x21, 0x49, 0x27, 0x48, 0x40, 0xF2, 0x1B, 0x32, 0xF2, 0xF7, 0x44, 0xFA, +0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xB4, 0xAD, 0x64, 0xE5, 0x1A, 0x49, 0x28, 0x48, +0x40, 0xF2, 0x1A, 0x32, 0xF2, 0xF7, 0x36, 0xFA, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, +0xA1, 0xAD, 0x56, 0xE5, 0x13, 0x49, 0x22, 0x48, 0x40, 0xF2, 0x2B, 0x32, 0xF2, 0xF7, 0x28, 0xFA, 0xD8, 0xF8, 0x00, 0x30, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xFF, 0xF6, 0xD2, 0xAD, 0x48, 0xE5, 0xBA, 0xF1, 0x02, 0x0F, 0x08, 0xD1, 0xB9, 0xF1, +0x05, 0x0F, 0x7F, 0xF4, 0x42, 0xAD, 0x09, 0x49, 0x18, 0x48, 0x40, 0xF2, 0x21, 0x32, 0xB2, 0xE5, 0xBA, 0xF1, 0x03, 0x0F, +0x7F, 0xF4, 0x39, 0xAD, 0xB9, 0xF1, 0x02, 0x0F, 0x7F, 0xF4, 0x35, 0xAD, 0x02, 0x49, 0x13, 0x48, 0x40, 0xF2, 0x22, 0x32, +0xA5, 0xE5, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xD8, 0x93, 0x15, 0x00, 0x64, 0xC6, 0x15, 0x00, 0x48, 0xC7, 0x15, 0x00, +0xAC, 0xC8, 0x15, 0x00, 0x10, 0xC8, 0x15, 0x00, 0xFC, 0xC7, 0x15, 0x00, 0x24, 0xC8, 0x15, 0x00, 0x28, 0xC6, 0x15, 0x00, +0x64, 0xC8, 0x15, 0x00, 0x80, 0xC7, 0x15, 0x00, 0x74, 0xC7, 0x15, 0x00, 0xD4, 0xC7, 0x15, 0x00, 0x98, 0xC7, 0x15, 0x00, +0xE4, 0xC7, 0x15, 0x00, 0xA0, 0xC9, 0x15, 0x00, 0x34, 0xC9, 0x15, 0x00, 0x68, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0x04, 0x46, 0x04, 0xF0, 0x89, 0xFD, 0x94, 0xF8, 0xA5, 0x10, 0x94, 0xF8, 0xAF, 0x20, 0xCB, 0x02, 0x9B, 0xB2, 0x92, 0xB3, +0x55, 0x1E, 0xED, 0xB2, 0x05, 0x29, 0x2B, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x6D, 0x6D, 0x2F, 0x2F, 0x94, 0x03, 0x94, 0xF8, +0xAD, 0x10, 0x03, 0x29, 0x00, 0xF2, 0xD1, 0x80, 0x06, 0x05, 0x40, 0xF1, 0xCE, 0x80, 0x94, 0xF8, 0xAE, 0x60, 0xB4, 0xF8, +0xAA, 0x20, 0x73, 0x1A, 0x01, 0x33, 0x00, 0xF0, 0x7F, 0x07, 0x97, 0xFB, 0xF3, 0xF5, 0x03, 0xFB, 0x15, 0x73, 0x19, 0x44, +0xC9, 0xB2, 0x22, 0xFA, 0x01, 0xF3, 0x13, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x31, 0x46, 0x00, 0x29, 0x00, 0xF0, 0x3F, 0x81, +0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x63, 0x43, 0xEA, 0x82, 0x23, 0x0B, 0x43, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, +0xF0, 0x81, 0x15, 0x46, 0xCC, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x01, 0xD8, 0x06, 0x05, 0xD5, 0xD4, 0x94, 0xF8, +0xB0, 0x70, 0x94, 0xF8, 0xAC, 0x60, 0x94, 0xF8, 0xB1, 0xC0, 0x01, 0x37, 0xC0, 0xF3, 0xC1, 0x01, 0xB1, 0xFB, 0xF7, 0xFE, +0x07, 0xFB, 0x1E, 0x11, 0x0C, 0x44, 0x06, 0xF1, 0x01, 0x0E, 0x00, 0xF0, 0x07, 0x08, 0x94, 0xF8, 0xA6, 0x70, 0xB8, 0xFB, +0xFE, 0xF4, 0x0E, 0xFB, 0x14, 0x84, 0xE7, 0x40, 0xFF, 0x07, 0x48, 0xBF, 0xE6, 0xB2, 0x52, 0x1B, 0x0C, 0xF1, 0x01, 0x04, +0xC0, 0xF3, 0x40, 0x2C, 0x01, 0x32, 0xC0, 0xF3, 0xC1, 0x10, 0xBC, 0xFB, 0xF4, 0xF7, 0xC9, 0x00, 0x04, 0xFB, 0x17, 0xC4, +0x41, 0xEA, 0x44, 0x21, 0x90, 0xFB, 0xF2, 0xF4, 0x02, 0xFB, 0x14, 0x00, 0x05, 0x44, 0x0B, 0x43, 0x43, 0xEA, 0xC5, 0x13, +0x9B, 0xB2, 0x33, 0x43, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x94, 0xF8, 0xAE, 0x70, 0x94, 0xF8, 0xAD, 0x20, 0xB4, 0xF8, +0xAA, 0x50, 0xB9, 0x1A, 0x01, 0x31, 0x00, 0xF0, 0x7F, 0x0C, 0x9C, 0xFB, 0xF1, 0xF6, 0x01, 0xFB, 0x16, 0xC1, 0x0A, 0x44, +0xD2, 0xB2, 0x25, 0xFA, 0x02, 0xF1, 0x11, 0xF0, 0x01, 0x0F, 0x08, 0xBF, 0x3A, 0x46, 0x13, 0x43, 0x00, 0x2A, 0x00, 0xF0, +0xA2, 0x80, 0x01, 0x3A, 0xD2, 0xB2, 0x02, 0x2A, 0x9E, 0xD8, 0x94, 0xF8, 0xB2, 0x20, 0x00, 0xF4, 0x80, 0x60, 0x40, 0xEA, +0x82, 0x20, 0x03, 0x43, 0x9B, 0xB2, 0x95, 0xE7, 0x94, 0xF8, 0xAD, 0x10, 0x03, 0x29, 0x40, 0xF2, 0x8C, 0x80, 0x94, 0xF8, +0xB0, 0x10, 0xB4, 0xF8, 0xA6, 0x70, 0x94, 0xF8, 0xAC, 0xC0, 0x94, 0xF8, 0xB1, 0x40, 0x4E, 0x1C, 0xC0, 0xF3, 0x02, 0x11, +0xB1, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0x11, 0x4E, 0x00, 0x37, 0x41, 0x07, 0xF0, 0x03, 0x07, 0x0C, 0xF1, 0x01, 0x06, +0x00, 0xF0, 0x0F, 0x0C, 0x07, 0x37, 0xBC, 0xFB, 0xF6, 0xFE, 0x06, 0xFB, 0x1E, 0xCC, 0xBC, 0x45, 0xCE, 0xB2, 0xA2, 0xEB, +0x05, 0x02, 0x40, 0xF3, 0x81, 0x80, 0x02, 0xF1, 0x01, 0x0C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xFC, 0xF2, 0x0C, 0xFB, +0x12, 0xE2, 0x15, 0x44, 0xFF, 0xB2, 0xED, 0xB2, 0x09, 0x2F, 0x40, 0xF0, 0xAE, 0x80, 0x00, 0x2D, 0x40, 0xF0, 0x98, 0x80, +0x02, 0x29, 0x00, 0xF0, 0xC0, 0x80, 0x05, 0x2E, 0x14, 0xBF, 0x4F, 0xF0, 0x08, 0x0C, 0x4F, 0xF0, 0x09, 0x0C, 0x09, 0x01, +0x09, 0xB2, 0x00, 0x25, 0x76, 0xE0, 0x94, 0xF8, 0xB0, 0x70, 0xB4, 0xF8, 0xA6, 0x60, 0x94, 0xF8, 0xAC, 0xC0, 0x79, 0x1C, +0xC0, 0xF3, 0x02, 0x17, 0xB7, 0xFB, 0xF1, 0xFE, 0x01, 0xFB, 0x1E, 0x77, 0x79, 0x00, 0x0E, 0x41, 0x06, 0xF0, 0x03, 0x06, +0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF0, 0x0F, 0x01, 0x76, 0x00, 0x07, 0x36, 0xB1, 0xFB, 0xFC, 0xFE, 0x0C, 0xFB, 0x1E, 0x11, +0xB1, 0x42, 0xC0, 0xF3, 0x41, 0x2C, 0xA2, 0xEB, 0x05, 0x02, 0xC8, 0xBF, 0xF1, 0xB2, 0x02, 0xF1, 0x01, 0x02, 0xC0, 0xF3, +0xC1, 0x1E, 0xD8, 0xBF, 0xC9, 0xB2, 0xBC, 0xF1, 0x03, 0x0F, 0x18, 0xBF, 0x4F, 0xEA, 0x4C, 0x26, 0x9E, 0xFB, 0xF2, 0xFC, +0x02, 0xFB, 0x1C, 0xEC, 0x94, 0xF8, 0xBC, 0x20, 0x65, 0x44, 0x08, 0xBF, 0x4F, 0xF4, 0x80, 0x66, 0xED, 0xB2, 0xEA, 0xB1, +0x02, 0x29, 0x1A, 0xD0, 0x94, 0xF8, 0xBD, 0x20, 0x8A, 0x42, 0x16, 0xD3, 0x94, 0xF8, 0xBE, 0xC0, 0xFA, 0xB2, 0x94, 0x45, +0x11, 0xD3, 0x94, 0xF8, 0xBF, 0x20, 0xAA, 0x42, 0x0D, 0xD3, 0x00, 0xF4, 0x80, 0x42, 0x12, 0xB2, 0x0A, 0xE0, 0x07, 0x05, +0x7F, 0xF5, 0x71, 0xAF, 0xE1, 0xE6, 0x43, 0xF4, 0x80, 0x63, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x22, +0x43, 0xEA, 0x07, 0x13, 0x43, 0xEA, 0xC5, 0x15, 0x29, 0x43, 0x31, 0x43, 0x42, 0xEA, 0x01, 0x03, 0x9B, 0xB2, 0x18, 0x46, +0xBD, 0xE8, 0xF0, 0x81, 0x57, 0x1C, 0xC0, 0xF3, 0xC1, 0x1E, 0x9E, 0xFB, 0xF7, 0xF2, 0x07, 0xFB, 0x12, 0xE2, 0x15, 0x44, +0xBC, 0xF1, 0x06, 0x0F, 0xED, 0xB2, 0x5F, 0xFA, 0x8C, 0xF7, 0x7F, 0xF4, 0x7B, 0xAF, 0x02, 0x2D, 0x20, 0xD0, 0x09, 0x01, +0x09, 0xB2, 0xED, 0x01, 0x01, 0x34, 0xC0, 0xF3, 0x40, 0x20, 0xB0, 0xFB, 0xF4, 0xF2, 0x04, 0xFB, 0x12, 0x00, 0x43, 0xEA, +0x40, 0x23, 0x2B, 0x43, 0x0B, 0x43, 0x4C, 0xEA, 0x03, 0x03, 0x9B, 0xB2, 0x18, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, +0x80, 0x63, 0xC5, 0xE6, 0x02, 0x2D, 0x16, 0xD1, 0x05, 0x29, 0x2D, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, +0x80, 0x75, 0xE1, 0xE7, 0x03, 0x29, 0x16, 0xD0, 0x06, 0x29, 0x14, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0x4F, 0xF4, 0x80, 0x75, +0xD8, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, 0x0F, 0xFA, 0x87, 0xFC, 0xD2, 0xE7, 0x03, 0x2D, 0x1B, 0xD1, 0x02, 0x29, +0x0F, 0xD0, 0x09, 0x01, 0x09, 0xB2, 0xBC, 0x46, 0x4F, 0xF4, 0xC0, 0x75, 0xC8, 0xE7, 0x71, 0x1E, 0xC9, 0xB2, 0x09, 0x01, +0x4F, 0xF0, 0x06, 0x0C, 0x4F, 0xF4, 0x80, 0x75, 0xC0, 0xE7, 0xBC, 0x46, 0x43, 0xE7, 0xBC, 0x46, 0x10, 0x21, 0x4F, 0xF4, +0xC0, 0x75, 0xB9, 0xE7, 0xBC, 0x46, 0x40, 0x21, 0x4F, 0xF4, 0x80, 0x75, 0xB4, 0xE7, 0x09, 0x01, 0x09, 0xB2, 0xED, 0x01, +0xBC, 0x46, 0xAF, 0xE7, 0xB0, 0xF8, 0xB4, 0x30, 0x00, 0x2B, 0x4A, 0xD0, 0x2D, 0xE9, 0xF0, 0x4F, 0x03, 0xF1, 0xFF, 0x3B, +0x1F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x01, 0x0F, 0x85, 0xB0, 0x8A, 0x46, 0x00, 0xF1, 0x10, 0x09, 0x3A, 0xD9, 0x01, 0x25, +0x2F, 0x46, 0x0A, 0xF1, 0x04, 0x04, 0x4E, 0x46, 0x00, 0x21, 0x0D, 0xE0, 0x13, 0x43, 0x04, 0xD1, 0x73, 0x7A, 0x13, 0xB9, +0x73, 0x7D, 0x01, 0x2B, 0x0B, 0xD0, 0x01, 0x35, 0xAF, 0xB2, 0x06, 0xF1, 0x0C, 0x08, 0x5F, 0x45, 0x46, 0x46, 0x20, 0xD2, +0x22, 0x68, 0x54, 0xF8, 0x04, 0x3F, 0x9A, 0x42, 0xEC, 0xD9, 0x0C, 0x22, 0x06, 0xEB, 0x02, 0x08, 0x31, 0x46, 0x01, 0xA8, +0x04, 0xF0, 0x3E, 0xFB, 0x30, 0x46, 0x41, 0x46, 0x0C, 0x22, 0x04, 0xF0, 0x39, 0xFB, 0x0C, 0x22, 0x01, 0xA9, 0x40, 0x46, +0x04, 0xF0, 0x34, 0xFB, 0x01, 0x35, 0x54, 0xE9, 0x01, 0x32, 0x39, 0x46, 0xAF, 0xB2, 0x5F, 0x45, 0x44, 0xF8, 0x04, 0x2C, +0x23, 0x60, 0x46, 0x46, 0xDE, 0xD3, 0x19, 0xB1, 0x8B, 0x46, 0xBB, 0xF1, 0x01, 0x0F, 0xC4, 0xD8, 0x05, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x4F, 0xB0, 0xF8, 0xB4, 0x50, 0x83, 0xB0, 0x06, 0x46, 0x89, 0x46, 0x00, 0x2D, +0x00, 0xF0, 0xE2, 0x80, 0x6F, 0x1E, 0x1F, 0xFA, 0x87, 0xF8, 0x08, 0xEB, 0x48, 0x08, 0x00, 0xF1, 0x0C, 0x03, 0x03, 0xEB, +0x88, 0x08, 0x04, 0x46, 0x4F, 0xF0, 0x00, 0x0A, 0x41, 0xF6, 0x98, 0x1B, 0x60, 0x89, 0xFE, 0xF7, 0xAD, 0xFE, 0x30, 0xB9, +0x63, 0x7B, 0x23, 0xB1, 0x23, 0x89, 0x5B, 0x45, 0x07, 0xD8, 0x4F, 0xF0, 0x01, 0x0A, 0x0C, 0x34, 0x44, 0x45, 0xF1, 0xD1, +0x4F, 0xEA, 0xCA, 0x00, 0x40, 0xB2, 0x96, 0xF8, 0xA2, 0x40, 0x24, 0xF0, 0x08, 0x04, 0x04, 0x43, 0xE4, 0xB2, 0x86, 0xF8, +0xA2, 0x40, 0x14, 0xF0, 0x02, 0x04, 0x09, 0xD1, 0x05, 0xF1, 0x80, 0x43, 0x01, 0x3B, 0xD9, 0xF8, 0x00, 0x20, 0x59, 0xF8, +0x23, 0x30, 0x9A, 0x42, 0x00, 0xF2, 0x9C, 0x80, 0x1F, 0xFA, 0x87, 0xFB, 0xCD, 0xF8, 0x00, 0xB0, 0x4F, 0xF0, 0x02, 0x08, +0x00, 0x9C, 0xA6, 0xF8, 0x88, 0xB0, 0x04, 0xEB, 0x44, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x58, 0x89, 0xFE, 0xF7, 0x7A, 0xFE, +0x63, 0x00, 0x01, 0x93, 0xE0, 0xB9, 0x00, 0x2F, 0x13, 0xDD, 0x82, 0x46, 0x84, 0x46, 0x0C, 0xEB, 0x4C, 0x0C, 0x06, 0xEB, +0x8C, 0x04, 0x60, 0x89, 0xFE, 0xF7, 0x6C, 0xFE, 0x0A, 0xF1, 0x01, 0x03, 0x1F, 0xFA, 0x83, 0xFA, 0xD4, 0x46, 0x10, 0xB1, +0x4F, 0xF0, 0x00, 0x03, 0xA3, 0x73, 0xBA, 0x45, 0xED, 0xDB, 0xDD, 0xE9, 0x00, 0x23, 0x13, 0x44, 0x06, 0xEB, 0x83, 0x04, +0x01, 0x23, 0xA3, 0x73, 0xA8, 0x45, 0xA6, 0xF8, 0x8A, 0xB0, 0x76, 0xD2, 0xA5, 0xEB, 0x08, 0x03, 0x03, 0xEB, 0x43, 0x03, +0x06, 0xEB, 0x83, 0x03, 0x03, 0xE0, 0x1F, 0xFA, 0x80, 0xF8, 0xA8, 0x45, 0x6B, 0xD0, 0x99, 0x7B, 0x08, 0xF1, 0x01, 0x00, +0x0C, 0x3B, 0x00, 0x29, 0xF5, 0xD0, 0xA5, 0xEB, 0x08, 0x00, 0x08, 0xF1, 0x01, 0x08, 0x1F, 0xFA, 0x88, 0xF8, 0x80, 0xB2, +0x45, 0x45, 0xA6, 0xF8, 0x8A, 0x00, 0x58, 0xD9, 0xA5, 0xEB, 0x08, 0x05, 0xA7, 0xEB, 0x08, 0x08, 0x4F, 0xEA, 0x18, 0x48, +0x05, 0xEB, 0x45, 0x03, 0x4F, 0xEA, 0x08, 0x48, 0x06, 0xEB, 0x83, 0x03, 0x02, 0xE0, 0x01, 0x3D, 0x45, 0x45, 0x48, 0xD0, +0x99, 0x7B, 0x0C, 0x3B, 0x00, 0x29, 0xF8, 0xD0, 0x05, 0xEB, 0x45, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x59, 0xF8, 0x25, 0x20, +0xB3, 0xF8, 0x08, 0xE0, 0x30, 0xB3, 0x31, 0x46, 0x00, 0x23, 0x4F, 0xF2, 0x32, 0x38, 0x0C, 0xE0, 0x59, 0xF8, 0x23, 0x70, +0x97, 0x42, 0x02, 0xD3, 0xA6, 0x46, 0x3A, 0x46, 0x1D, 0x46, 0x01, 0x33, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, 0x0C, 0x01, +0x14, 0xD9, 0x8C, 0x7B, 0x9F, 0xB2, 0x00, 0x2C, 0xF5, 0xD0, 0x5F, 0x45, 0xF3, 0xD0, 0x0C, 0x89, 0x44, 0x45, 0xE9, 0xD8, +0x74, 0x45, 0xEE, 0xD3, 0x59, 0xF8, 0x23, 0x20, 0x1D, 0x46, 0x01, 0x33, 0xA6, 0x46, 0x9C, 0xB2, 0xA0, 0x42, 0x01, 0xF1, +0x0C, 0x01, 0xEA, 0xD8, 0x00, 0x23, 0xA6, 0xF8, 0x8C, 0x50, 0xA6, 0xF8, 0x8E, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x07, 0xEB, 0x47, 0x03, 0x06, 0xEB, 0x83, 0x03, 0x5B, 0x7B, 0x00, 0x2B, 0x3F, 0xF4, 0x5C, 0xAF, 0x00, 0x94, 0xA3, 0x46, +0x4F, 0xF0, 0x01, 0x08, 0x5C, 0xE7, 0x05, 0x46, 0xB8, 0xE7, 0x5D, 0x46, 0x58, 0x46, 0xB5, 0xE7, 0x28, 0x46, 0x4F, 0xF0, +0xFF, 0x37, 0x38, 0xE7, 0xC1, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x5B, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x03, 0x27, 0x27, +0x0B, 0x32, 0xB0, 0xF8, 0xAA, 0x00, 0x01, 0xF0, 0x7F, 0x01, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xC1, 0xF3, +0x02, 0x12, 0xB0, 0xF8, 0xA6, 0x00, 0x53, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x03, +0x83, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x06, 0x2B, 0xC1, 0xF3, 0xC1, 0x11, 0x24, 0xD0, 0x09, 0x2B, 0x24, 0xD1, +0x21, 0xBB, 0x02, 0x2A, 0x21, 0xD0, 0x05, 0x2A, 0x18, 0xBF, 0x00, 0x20, 0x70, 0x47, 0xC1, 0xF3, 0xC1, 0x03, 0x18, 0x44, +0x01, 0xF0, 0x07, 0x01, 0x90, 0xF8, 0xA6, 0x00, 0xC8, 0x40, 0x00, 0xF0, 0x01, 0x00, 0x70, 0x47, 0xB0, 0xF8, 0xA6, 0x00, +0xC1, 0xF3, 0x02, 0x13, 0x5B, 0x00, 0x18, 0x41, 0x00, 0xF0, 0x03, 0x00, 0x40, 0x00, 0x07, 0x30, 0x01, 0xF0, 0x0F, 0x01, +0x81, 0x42, 0xCC, 0xBF, 0x00, 0x20, 0x01, 0x20, 0x70, 0x47, 0x02, 0x29, 0x06, 0xD0, 0x70, 0x47, 0x02, 0x29, 0x09, 0xD1, +0x05, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x03, 0x2A, 0x09, 0xD0, 0x06, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, +0x03, 0x29, 0xF0, 0xD1, 0x02, 0x2A, 0x08, 0xBF, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0xEA, 0xE7, 0x01, 0x20, 0x70, 0x47, +0x2D, 0xE9, 0xF0, 0x4F, 0x82, 0x46, 0xB0, 0xF8, 0x88, 0x70, 0xB0, 0xF8, 0x8A, 0x00, 0x9A, 0xF8, 0xAD, 0x30, 0x9A, 0xF8, +0xAE, 0x60, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x47, 0x07, 0x83, 0xB0, 0x0A, 0xEB, 0x80, 0x0C, 0x0A, 0xEB, 0x87, 0x07, +0x14, 0x46, 0x0D, 0x46, 0x08, 0x46, 0x52, 0x00, 0x4F, 0xF0, 0xFF, 0x31, 0x7F, 0x89, 0xBC, 0xF8, 0x0A, 0x80, 0x00, 0x93, +0xCD, 0xF7, 0x86, 0xF9, 0x00, 0x2C, 0x7E, 0xD0, 0x00, 0x9B, 0xA6, 0xEB, 0x03, 0x09, 0x01, 0x3C, 0x09, 0xF1, 0x01, 0x03, +0xE4, 0xB2, 0x01, 0x93, 0x4F, 0xF0, 0x00, 0x0B, 0x5F, 0xFA, 0x8B, 0xF3, 0x05, 0x2B, 0x5E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, +0x59, 0x41, 0x32, 0x23, 0x13, 0x03, 0x41, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xF9, 0xFF, 0x80, 0x45, 0x81, 0x46, 0x52, 0xD0, +0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x5E, 0xFF, 0x00, 0x28, 0x4C, 0xD0, 0xA5, 0xF8, 0x0A, 0x90, 0x49, 0xE0, 0x41, 0x46, +0x50, 0x46, 0xFF, 0xF7, 0x77, 0xF8, 0x80, 0x45, 0x81, 0x46, 0x42, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x4E, 0xFF, +0x00, 0x28, 0x3C, 0xD0, 0xA5, 0xF8, 0x08, 0x90, 0x39, 0xE0, 0x39, 0x46, 0x50, 0x46, 0xFE, 0xF7, 0xD9, 0xFF, 0xB8, 0x42, +0x81, 0x46, 0x32, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x3E, 0xFF, 0x68, 0xB3, 0xA5, 0xF8, 0x06, 0x90, 0x2A, 0xE0, +0x39, 0x46, 0x50, 0x46, 0xFF, 0xF7, 0x58, 0xF8, 0xB8, 0x42, 0x81, 0x46, 0x23, 0xD0, 0x01, 0x46, 0x50, 0x46, 0xFF, 0xF7, +0x2F, 0xFF, 0xF0, 0xB1, 0xA5, 0xF8, 0x04, 0x90, 0x1B, 0xE0, 0x00, 0x9B, 0x03, 0x2B, 0x03, 0xD8, 0x9A, 0xF8, 0xA2, 0x30, +0x19, 0x07, 0x3B, 0xD4, 0xC7, 0xF3, 0xC2, 0x23, 0x05, 0x2B, 0x4F, 0xEA, 0xD7, 0x22, 0x23, 0xD0, 0x12, 0xF0, 0x06, 0x0F, +0x0B, 0xD0, 0x9A, 0xF8, 0xB1, 0x30, 0x01, 0x2B, 0x07, 0xD1, 0x87, 0xF4, 0x00, 0x73, 0x6B, 0x80, 0x03, 0xE0, 0x50, 0x46, +0xFF, 0xF7, 0x1E, 0xFC, 0x28, 0x80, 0x03, 0x2E, 0x09, 0xD8, 0x35, 0xF8, 0x1B, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, +0x04, 0xBF, 0x46, 0xF4, 0x80, 0x63, 0x25, 0xF8, 0x1B, 0x30, 0x5C, 0x45, 0x0B, 0xF1, 0x01, 0x03, 0x01, 0xD0, 0x9B, 0x46, +0x8A, 0xE7, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x1A, 0x4A, 0xC7, 0xF3, 0x41, 0x23, 0x01, 0x33, 0xA2, 0xFB, 0x03, 0x21, +0x21, 0xF0, 0x01, 0x02, 0x02, 0xEB, 0x51, 0x02, 0x27, 0xF4, 0xC0, 0x67, 0x9B, 0x1A, 0x47, 0xEA, 0x43, 0x23, 0x6B, 0x80, +0xBF, 0xB2, 0xD8, 0xE7, 0x04, 0xF0, 0x82, 0xF9, 0x01, 0x99, 0x00, 0xF0, 0x7F, 0x02, 0x92, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, +0x13, 0x23, 0x00, 0x9A, 0x13, 0x44, 0xBA, 0xF8, 0xAA, 0x20, 0xDB, 0xB2, 0xDA, 0x40, 0xD2, 0x07, 0x0F, 0xD5, 0x00, 0x2B, +0x08, 0xBF, 0x33, 0x46, 0x5A, 0x1E, 0x02, 0x2A, 0x6B, 0x80, 0xCC, 0xD8, 0x9A, 0xF8, 0xB2, 0x10, 0x00, 0xF4, 0x80, 0x62, +0x42, 0xEA, 0x81, 0x22, 0x13, 0x43, 0x6B, 0x80, 0xC3, 0xE7, 0x33, 0x46, 0xF0, 0xE7, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, +0x2D, 0xE9, 0xF0, 0x47, 0x05, 0x46, 0x84, 0xB0, 0x01, 0xA9, 0x06, 0x22, 0xFF, 0xF7, 0x1C, 0xFF, 0xB5, 0xF8, 0xB4, 0x10, +0x01, 0x29, 0x30, 0xD9, 0x00, 0x26, 0x01, 0x24, 0xB0, 0x46, 0xA1, 0x46, 0x4F, 0xF6, 0xFF, 0x77, 0x18, 0xE0, 0xB5, 0xF8, +0x88, 0x20, 0xA2, 0x42, 0x21, 0xD0, 0xB5, 0xF8, 0x8A, 0x20, 0xA2, 0x42, 0x1D, 0xD0, 0xB5, 0xF8, 0x8C, 0x20, 0xA2, 0x42, +0x19, 0xD0, 0x05, 0x2E, 0x17, 0xD8, 0x04, 0xAA, 0x02, 0xEB, 0x46, 0x02, 0x32, 0xF8, 0x0C, 0xEC, 0xBE, 0x45, 0x17, 0xD1, +0xA1, 0x42, 0x06, 0xF1, 0x01, 0x06, 0x10, 0xD9, 0x04, 0xEB, 0x44, 0x03, 0x05, 0xEB, 0x83, 0x03, 0x4F, 0xEA, 0x44, 0x0C, +0xB3, 0xF9, 0x08, 0x20, 0x00, 0x2A, 0xDC, 0xDA, 0x1A, 0x7B, 0x0A, 0x2A, 0xD9, 0xD8, 0x01, 0x34, 0xA4, 0xB2, 0xA1, 0x42, +0xEE, 0xD8, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x59, 0xB1, 0x2A, 0x46, 0x00, 0x20, 0xB2, 0xF8, 0x0A, 0xA0, 0xF2, 0x45, +0x00, 0xF1, 0x01, 0x00, 0x02, 0xF1, 0x0C, 0x02, 0xDC, 0xD0, 0x88, 0x42, 0xF5, 0xD1, 0x0C, 0xEB, 0x04, 0x02, 0x05, 0xEB, +0x82, 0x02, 0xA3, 0xF8, 0x0A, 0xE0, 0xA3, 0xF8, 0x08, 0x80, 0x21, 0x46, 0x82, 0xF8, 0x0D, 0x80, 0x28, 0x46, 0xA3, 0xF8, +0x04, 0x80, 0xA3, 0xF8, 0x06, 0x80, 0x01, 0x34, 0x82, 0xF8, 0x0C, 0x80, 0x82, 0xF8, 0x0E, 0x90, 0xFF, 0xF7, 0x12, 0xF8, +0xA4, 0xB2, 0xB5, 0xF8, 0xB4, 0x10, 0xBF, 0xE7, 0x30, 0xB4, 0x90, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, 0x8C, 0x80, +0xDF, 0xE8, 0x03, 0xF0, 0x36, 0x36, 0x03, 0x03, 0x70, 0x57, 0x90, 0xF8, 0xAF, 0x50, 0x90, 0xF8, 0xB1, 0x20, 0x90, 0xF8, +0xB0, 0x30, 0x90, 0xF8, 0xA6, 0x40, 0x01, 0x35, 0x95, 0x40, 0x03, 0xFB, 0x05, 0x55, 0xAD, 0xB2, 0x08, 0x21, 0x00, 0x23, +0x04, 0xF0, 0x01, 0x02, 0x12, 0xFB, 0x05, 0xF2, 0x13, 0x44, 0x01, 0x39, 0x9B, 0xB2, 0x4F, 0xEA, 0x54, 0x04, 0xF5, 0xD1, +0xB0, 0xF8, 0xAA, 0x20, 0x90, 0xF8, 0xB2, 0x10, 0xC2, 0xF3, 0x80, 0x04, 0xC2, 0xF3, 0x40, 0x00, 0xC1, 0xF1, 0x01, 0x01, +0x20, 0x44, 0x88, 0x40, 0x02, 0xF0, 0x01, 0x04, 0xC2, 0xF3, 0xC0, 0x02, 0x20, 0x44, 0x8A, 0x40, 0x10, 0x44, 0x18, 0x44, +0x80, 0xB2, 0x0A, 0x28, 0x28, 0xBF, 0x0A, 0x20, 0x30, 0xBC, 0x70, 0x47, 0xB0, 0xF8, 0xAA, 0x10, 0x90, 0xF8, 0xB2, 0x30, +0xC1, 0xF3, 0x80, 0x02, 0xC1, 0xF3, 0x40, 0x00, 0xC3, 0xF1, 0x01, 0x03, 0x10, 0x44, 0x98, 0x40, 0x01, 0xF0, 0x01, 0x04, +0xC1, 0xF3, 0xC0, 0x02, 0x02, 0xFA, 0x03, 0xF3, 0x20, 0x44, 0x13, 0xFA, 0x80, 0xF0, 0x80, 0xB2, 0x04, 0x23, 0x41, 0xFA, +0x03, 0xF2, 0x02, 0xF0, 0x01, 0x02, 0x01, 0x33, 0x10, 0x44, 0x0C, 0x2B, 0x80, 0xB2, 0xF6, 0xD1, 0xD9, 0xE7, 0x90, 0xF8, +0xB1, 0x30, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x40, 0x90, 0xF8, 0xB0, 0x10, 0x58, 0x1C, 0x02, 0xF0, 0x03, 0x03, +0x04, 0xFB, 0x00, 0x00, 0x01, 0x2B, 0x01, 0xFB, 0x00, 0x00, 0x1F, 0xD0, 0x02, 0x2B, 0x14, 0xBF, 0x08, 0x23, 0x0A, 0x23, +0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xC0, 0xE7, 0xB0, 0xF8, 0xA6, 0x20, 0x90, 0xF8, 0xAF, 0x30, 0x90, 0xF8, 0xB1, 0x40, +0x90, 0xF8, 0xB0, 0x10, 0x02, 0xF0, 0x03, 0x02, 0x01, 0x33, 0x01, 0x3A, 0x03, 0xFA, 0x04, 0xF0, 0x01, 0x2A, 0x8C, 0xBF, +0x08, 0x23, 0x09, 0x23, 0x01, 0xFB, 0x00, 0x00, 0x10, 0xFB, 0x03, 0xF0, 0x80, 0xB2, 0xA8, 0xE7, 0x09, 0x23, 0xE1, 0xE7, +0x00, 0x20, 0xA7, 0xE7, 0x2D, 0xE9, 0xF8, 0x4F, 0xB0, 0xF8, 0xB4, 0x40, 0x05, 0x46, 0x00, 0x2C, 0x00, 0xF0, 0xF4, 0x80, +0x04, 0xF1, 0xFF, 0x38, 0x1F, 0xFA, 0x88, 0xF1, 0x01, 0xEB, 0x41, 0x03, 0x00, 0xF1, 0x0C, 0x01, 0x01, 0xEB, 0x83, 0x01, +0x4F, 0xF6, 0xFF, 0x76, 0x03, 0x46, 0x00, 0x22, 0x01, 0x20, 0x5E, 0x81, 0x9A, 0x80, 0xDA, 0x80, 0x1A, 0x81, 0x1A, 0x73, +0x5A, 0x73, 0x98, 0x73, 0x0C, 0x33, 0x99, 0x42, 0xF5, 0xD1, 0xC1, 0x46, 0x95, 0xF8, 0xA5, 0x30, 0x05, 0x2B, 0x00, 0xF2, +0xD9, 0x80, 0xDF, 0xE8, 0x03, 0xF0, 0x4E, 0x4E, 0x03, 0x03, 0x8A, 0x5E, 0x95, 0xF8, 0xAD, 0x20, 0xDB, 0x02, 0x00, 0x2A, +0x00, 0xF0, 0xC7, 0x80, 0x99, 0xB2, 0x95, 0xF8, 0xB0, 0x20, 0x69, 0x81, 0xA9, 0x18, 0x95, 0xF8, 0xB1, 0x60, 0x91, 0xF8, +0xA6, 0x70, 0x95, 0xF8, 0xAF, 0x00, 0x43, 0xEA, 0x46, 0x23, 0xB7, 0xFA, 0x87, 0xF7, 0xC7, 0xF1, 0x1F, 0x07, 0x43, 0xEA, +0xC0, 0x13, 0xFF, 0xB2, 0x43, 0xEA, 0xC2, 0x03, 0x3B, 0x43, 0x9F, 0xB2, 0x09, 0xEB, 0x49, 0x09, 0x05, 0xEB, 0x89, 0x03, +0x01, 0x26, 0x46, 0x45, 0x5F, 0x81, 0x80, 0xF2, 0x9B, 0x80, 0x28, 0x46, 0xFF, 0xF7, 0x7E, 0xFA, 0xB5, 0xF8, 0xB4, 0x40, +0x00, 0x2C, 0x00, 0xF0, 0x87, 0x80, 0x2B, 0x46, 0x00, 0x22, 0x02, 0xE0, 0xA2, 0x42, 0x00, 0xF0, 0x81, 0x80, 0x59, 0x89, +0x81, 0x42, 0x02, 0xF1, 0x01, 0x02, 0x03, 0xF1, 0x0C, 0x03, 0xF5, 0xD1, 0x01, 0x3C, 0xA6, 0x42, 0xE7, 0xDB, 0x00, 0x24, +0xA1, 0xB2, 0x28, 0x46, 0xFE, 0xF7, 0x0A, 0xFF, 0xB5, 0xF8, 0xB4, 0x30, 0x01, 0x34, 0x9C, 0x42, 0xF6, 0xD3, 0xBD, 0xE8, +0xF8, 0x8F, 0x95, 0xF8, 0xAD, 0x20, 0x00, 0x2A, 0x7A, 0xD0, 0x92, 0xB2, 0x95, 0xF8, 0xB2, 0x10, 0x95, 0xF8, 0xAE, 0x70, +0x6A, 0x81, 0xDB, 0x02, 0x43, 0xEA, 0x81, 0x23, 0x3B, 0x43, 0x9F, 0xB2, 0xC2, 0xE7, 0x95, 0xF8, 0xAD, 0x30, 0x00, 0x2B, +0x67, 0xD0, 0x95, 0xF8, 0xBC, 0x30, 0x00, 0x2B, 0x0C, 0xBF, 0x4F, 0xF4, 0x28, 0x52, 0x4F, 0xF4, 0xD4, 0x42, 0x95, 0xF8, +0xB0, 0x30, 0xB5, 0xF8, 0xA6, 0x60, 0x6A, 0x81, 0x5A, 0x00, 0x16, 0x41, 0x95, 0xF8, 0xAF, 0xA0, 0x06, 0xF0, 0x03, 0x06, +0x1B, 0x01, 0x76, 0x00, 0x07, 0x36, 0x43, 0xEA, 0xCA, 0x1A, 0x4A, 0xEA, 0x06, 0x07, 0x47, 0xF4, 0x20, 0x57, 0x39, 0x46, +0x28, 0x46, 0xFF, 0xF7, 0x1B, 0xFD, 0x01, 0x3E, 0xF3, 0xB2, 0xB6, 0xB2, 0x00, 0x28, 0x99, 0xD1, 0x06, 0x2B, 0xF0, 0xD1, +0x96, 0xE7, 0x95, 0xF8, 0xB0, 0xA0, 0xB5, 0xF8, 0xA6, 0xB0, 0x95, 0xF8, 0xAF, 0x60, 0x95, 0xF8, 0xB1, 0x30, 0x4F, 0xEA, +0x4A, 0x02, 0x4B, 0xFA, 0x02, 0xFB, 0xF6, 0x01, 0x46, 0xEA, 0x43, 0x26, 0x0B, 0xF0, 0x03, 0x0B, 0x4F, 0xF4, 0x00, 0x53, +0x4F, 0xEA, 0x0A, 0x1A, 0x0B, 0xF1, 0x07, 0x0B, 0x36, 0xB2, 0x6B, 0x81, 0x4A, 0xEA, 0x0B, 0x07, 0x37, 0x43, 0x47, 0xF4, +0x00, 0x57, 0xBF, 0xB2, 0x39, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0xF0, 0xFC, 0x0B, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xF3, +0x1F, 0xFA, 0x8B, 0xFB, 0x00, 0x28, 0x7F, 0xF4, 0x6B, 0xAF, 0x06, 0x2B, 0xEA, 0xD1, 0x67, 0xE7, 0x06, 0xEB, 0x46, 0x03, +0x01, 0x36, 0x05, 0xEB, 0x83, 0x03, 0xB6, 0xB2, 0x04, 0xF1, 0xFF, 0x38, 0x46, 0x45, 0x58, 0x81, 0xFF, 0xF6, 0x65, 0xAF, +0x00, 0x2C, 0x7F, 0xF4, 0x7A, 0xAF, 0xBD, 0xE8, 0xF8, 0x8F, 0x4F, 0xF4, 0x80, 0x62, 0x9C, 0xE7, 0x4F, 0xF4, 0x80, 0x62, +0x82, 0xE7, 0x4F, 0xF4, 0x80, 0x61, 0x36, 0xE7, 0x4F, 0xF0, 0xFF, 0x39, 0xC8, 0x46, 0x21, 0xE7, 0x00, 0x27, 0x6F, 0x81, +0x46, 0xE7, 0x00, 0xBF, 0x90, 0xF8, 0xAD, 0x30, 0x0B, 0x2B, 0xF0, 0xB4, 0x0C, 0xD9, 0x90, 0xF8, 0xA2, 0x20, 0x04, 0x23, +0x01, 0x24, 0x22, 0xF0, 0x04, 0x02, 0x13, 0x43, 0x80, 0xF8, 0xA2, 0x30, 0x01, 0xB1, 0x0C, 0x70, 0xF0, 0xBC, 0x70, 0x47, +0xB0, 0xF8, 0x88, 0x30, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, +0x04, 0xD1, 0x00, 0x23, 0x90, 0xF8, 0xA2, 0x20, 0x1C, 0x46, 0xE6, 0xE7, 0xB0, 0xF8, 0x8A, 0x30, 0x03, 0xEB, 0x43, 0x03, +0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xEF, 0xD0, 0xB0, 0xF8, 0x8C, 0x30, 0x03, 0xEB, +0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0xDB, 0x12, 0x13, 0xF0, 0x06, 0x0F, 0xE4, 0xD0, 0x90, 0xF8, 0xA2, 0x20, +0x12, 0xF0, 0x20, 0x04, 0x20, 0xD1, 0x90, 0xF8, 0xA4, 0x30, 0x44, 0x33, 0x30, 0xF8, 0x13, 0x30, 0x03, 0xEB, 0x43, 0x03, +0x00, 0xEB, 0x83, 0x05, 0x6B, 0x89, 0x13, 0xF4, 0x00, 0x5F, 0x4F, 0xEA, 0xD3, 0x27, 0xC3, 0xF3, 0xC2, 0x26, 0x12, 0xD1, +0x17, 0xF0, 0x06, 0x0F, 0x1D, 0xD1, 0x03, 0xF0, 0x7F, 0x03, 0x02, 0x2B, 0x15, 0xD9, 0x2D, 0x89, 0x40, 0xF2, 0x8E, 0x23, +0x9D, 0x42, 0x86, 0xBF, 0x01, 0x24, 0x04, 0x23, 0x00, 0x23, 0xAA, 0xE7, 0x04, 0x23, 0x01, 0x24, 0xA7, 0xE7, 0x07, 0x2E, +0x07, 0xD0, 0x03, 0xF0, 0x0F, 0x06, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0x2E, 0xEB, 0xD8, 0x00, 0x2B, 0xE9, 0xD1, 0x2D, 0x89, +0x41, 0xF6, 0x98, 0x13, 0xE8, 0xE7, 0x03, 0xF0, 0x07, 0x06, 0xC3, 0xF3, 0xC1, 0x03, 0xF2, 0xE7, 0xF8, 0xB5, 0x90, 0xF8, +0xA2, 0x60, 0x16, 0xF0, 0x10, 0x05, 0x04, 0x46, 0x35, 0xD0, 0xB0, 0xF8, 0xB4, 0x00, 0x00, 0x28, 0x5F, 0xD0, 0xB4, 0xF8, +0xBA, 0x70, 0x00, 0x23, 0x02, 0xE0, 0x82, 0x42, 0xCB, 0xB2, 0x46, 0xD2, 0x03, 0xEB, 0x43, 0x02, 0x04, 0xEB, 0x82, 0x02, +0x59, 0x1C, 0x55, 0x89, 0xBD, 0x42, 0xCA, 0xB2, 0xF3, 0xD1, 0x9A, 0xB2, 0xA4, 0xF8, 0x88, 0x20, 0xA4, 0xF8, 0x8A, 0x20, +0xA4, 0xF8, 0x8C, 0x20, 0x01, 0x38, 0x80, 0xB2, 0x04, 0xF1, 0x0C, 0x03, 0x00, 0xEB, 0x40, 0x00, 0x03, 0xEB, 0x80, 0x00, +0x00, 0x22, 0x23, 0x46, 0x9A, 0x80, 0xDA, 0x80, 0x0C, 0x33, 0x98, 0x42, 0xFA, 0xD1, 0x26, 0xF0, 0x30, 0x06, 0x46, 0xF0, +0x20, 0x06, 0x00, 0x23, 0x84, 0xF8, 0xA2, 0x60, 0x84, 0xF8, 0x9B, 0x30, 0x01, 0x25, 0x28, 0x46, 0xF8, 0xBD, 0x90, 0xF8, +0x88, 0x00, 0x0C, 0x23, 0x03, 0xFB, 0x00, 0x40, 0x04, 0x30, 0xFE, 0xF7, 0x73, 0xFC, 0xB4, 0xF8, 0xB4, 0x30, 0x00, 0x2B, +0xF1, 0xD0, 0x01, 0x3B, 0x9A, 0xB2, 0x02, 0xEB, 0x42, 0x03, 0x04, 0xF1, 0x0C, 0x02, 0x02, 0xEB, 0x83, 0x02, 0x2B, 0x46, +0xA3, 0x80, 0xE3, 0x80, 0x0C, 0x34, 0x94, 0x42, 0xFA, 0xD1, 0x28, 0x46, 0xF8, 0xBD, 0xC1, 0xD1, 0x01, 0x38, 0xC3, 0xB2, +0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xC2, 0xB2, 0x00, 0x21, 0x5F, 0x81, 0x19, 0x81, 0xA4, 0xF8, 0x88, 0x20, +0xA4, 0xF8, 0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0xB4, 0xF8, 0xBA, 0x20, 0xA4, 0xF8, 0xFE, 0x2B, 0x4F, 0xF0, +0xFF, 0x11, 0xFF, 0x22, 0xA4, 0xF8, 0xFC, 0x0B, 0xC4, 0xF8, 0x88, 0x10, 0xA4, 0xF8, 0x8C, 0x20, 0xB7, 0xE7, 0x00, 0xBF, +0xC2, 0x6C, 0x12, 0x69, 0xC2, 0xF3, 0x07, 0x21, 0xC2, 0xF3, 0x00, 0x42, 0x0A, 0x44, 0x00, 0x23, 0x01, 0x31, 0xFE, 0xF7, +0xC9, 0xB9, 0x00, 0xBF, 0x8A, 0x1A, 0x01, 0x23, 0xFE, 0xF7, 0xC4, 0xB9, 0xC3, 0x88, 0x99, 0x04, 0x30, 0xB4, 0xC3, 0xF3, +0xC2, 0x22, 0x11, 0xD4, 0xD9, 0x0A, 0x11, 0xF0, 0x06, 0x0F, 0x4A, 0xD1, 0x13, 0xF0, 0x7C, 0x0F, 0x03, 0xF0, 0x7F, 0x02, +0x5D, 0xD1, 0xC3, 0xF3, 0x80, 0x23, 0x43, 0xEA, 0x42, 0x02, 0x3D, 0x4B, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, 0x70, 0x47, +0x07, 0x2A, 0x37, 0xD0, 0x51, 0x1F, 0x03, 0xF0, 0x0F, 0x04, 0x01, 0x29, 0x37, 0xD8, 0xDF, 0xE8, 0x01, 0xF0, 0x01, 0x1B, +0xC3, 0xF3, 0x00, 0x21, 0x4A, 0x00, 0x11, 0x44, 0x06, 0x22, 0x12, 0xFB, 0x04, 0x12, 0xC3, 0xF3, 0x41, 0x21, 0x0A, 0x44, +0x31, 0x49, 0x51, 0xF8, 0x22, 0x00, 0xC3, 0xF3, 0xC0, 0x11, 0xC3, 0xF3, 0x02, 0x12, 0xC3, 0xF3, 0x80, 0x33, 0xC8, 0x40, +0x01, 0x32, 0x30, 0xBC, 0xB0, 0xFB, 0xF2, 0xF0, 0x98, 0x40, 0x70, 0x47, 0x00, 0x7A, 0x00, 0xF0, 0x07, 0x00, 0x02, 0x28, +0x31, 0xD8, 0x28, 0x49, 0xC3, 0xF3, 0x41, 0x25, 0x03, 0x22, 0x51, 0xF8, 0x20, 0x10, 0x12, 0xFB, 0x04, 0x52, 0xC3, 0xF3, +0x02, 0x10, 0x01, 0x30, 0x51, 0xF8, 0x22, 0x30, 0xB3, 0xFB, 0xF0, 0xF0, 0x30, 0xBC, 0x70, 0x47, 0x00, 0x20, 0x30, 0xBC, +0x70, 0x47, 0x03, 0xF0, 0x07, 0x04, 0xC3, 0xF3, 0x40, 0x20, 0xC3, 0xF3, 0xC1, 0x11, 0x40, 0xEA, 0x41, 0x01, 0x41, 0xEA, +0xC4, 0x04, 0x04, 0x2A, 0x19, 0x49, 0x14, 0xBF, 0xC3, 0xF3, 0xC1, 0x03, 0xC3, 0xF3, 0x02, 0x13, 0x51, 0xF8, 0x24, 0x00, +0x01, 0x33, 0x30, 0xBC, 0xB0, 0xFB, 0xF3, 0xF0, 0x70, 0x47, 0x14, 0x4B, 0x04, 0x3A, 0x30, 0xBC, 0x53, 0xF8, 0x22, 0x00, +0x70, 0x47, 0xC2, 0x1E, 0xC2, 0xF3, 0x46, 0x01, 0x02, 0xF0, 0xFE, 0x00, 0x08, 0x44, 0x06, 0x21, 0x11, 0xFB, 0x04, 0x04, +0xC3, 0xF3, 0x41, 0x21, 0x0C, 0x44, 0x08, 0x49, 0x51, 0xF8, 0x24, 0x00, 0xC3, 0xF3, 0x02, 0x13, 0x02, 0xF0, 0x01, 0x02, +0x59, 0x1C, 0x30, 0xBC, 0x20, 0xFA, 0x02, 0xF3, 0xB3, 0xFB, 0xF1, 0xF0, 0x70, 0x47, 0x00, 0xBF, 0x54, 0xCC, 0x15, 0x00, +0x74, 0xCC, 0x15, 0x00, 0xA4, 0xD0, 0x15, 0x00, 0x44, 0xCF, 0x15, 0x00, 0x84, 0xD0, 0x15, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, +0xB0, 0xF8, 0x96, 0x30, 0x90, 0xF8, 0xA2, 0x80, 0x90, 0xF8, 0xA5, 0x60, 0x03, 0xEB, 0x83, 0x03, 0x5B, 0x00, 0xA0, 0xF8, +0x98, 0x30, 0x07, 0x46, 0x03, 0xF0, 0xB8, 0xFD, 0xB7, 0xF8, 0xB4, 0x10, 0x80, 0xB2, 0xB0, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, +0x13, 0x00, 0x00, 0x29, 0x77, 0xD0, 0xB7, 0xF8, 0x88, 0xC0, 0x83, 0xB2, 0x08, 0xF0, 0x02, 0x08, 0x00, 0x20, 0x4F, 0xF2, +0x33, 0x3E, 0x03, 0x44, 0xB3, 0xFB, 0xF1, 0xF5, 0x01, 0xFB, 0x15, 0x35, 0x05, 0xEB, 0x45, 0x02, 0x92, 0x00, 0xAB, 0xB2, +0x07, 0xEB, 0x02, 0x0A, 0x9C, 0x45, 0x02, 0xF1, 0x04, 0x02, 0x00, 0xF1, 0x01, 0x00, 0x07, 0xEB, 0x02, 0x04, 0x4F, 0xEA, +0x45, 0x09, 0x58, 0xD0, 0xBA, 0xF8, 0x08, 0x20, 0x72, 0x45, 0x54, 0xD8, 0xB8, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0xBA, 0xF8, +0x0A, 0x20, 0xD2, 0x12, 0x12, 0xF0, 0x06, 0x0F, 0x4B, 0xD0, 0x01, 0x2E, 0x42, 0xD9, 0x0C, 0xEB, 0x4C, 0x0C, 0x07, 0xEB, +0x8C, 0x0C, 0xBC, 0xF8, 0x0A, 0x30, 0x98, 0x04, 0x4F, 0xEA, 0xD3, 0x26, 0xC3, 0xF3, 0xC2, 0x22, 0x47, 0xD4, 0x16, 0xF0, +0x06, 0x06, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x06, 0xE3, 0x88, 0x99, 0x04, 0x4F, 0xEA, 0xD3, 0x28, 0xC3, 0xF3, 0xC2, 0x22, +0x36, 0xD4, 0x18, 0xF0, 0x06, 0x08, 0x01, 0xD0, 0xC3, 0xF3, 0xC1, 0x08, 0xB7, 0xF8, 0x8A, 0x00, 0x00, 0xEB, 0x40, 0x00, +0x07, 0xEB, 0x80, 0x00, 0xA9, 0x44, 0x04, 0x30, 0x07, 0xEB, 0x89, 0x09, 0xFF, 0xF7, 0xFA, 0xFE, 0x99, 0xF8, 0x0D, 0x30, +0x82, 0x46, 0x5B, 0xBB, 0xB7, 0xF8, 0x96, 0xB0, 0x20, 0x46, 0xFF, 0xF7, 0xF1, 0xFE, 0x50, 0x45, 0x81, 0x46, 0x0D, 0xD3, +0x01, 0x3E, 0x46, 0x45, 0x23, 0xD2, 0x23, 0x7A, 0x5B, 0x45, 0x10, 0xD3, 0x97, 0xF8, 0x9A, 0x30, 0x01, 0x33, 0xDB, 0xB2, +0x02, 0x2B, 0x87, 0xF8, 0x9A, 0x30, 0x29, 0xD8, 0x01, 0x20, 0x87, 0xF8, 0xA0, 0x50, 0x87, 0xF8, 0x9B, 0x00, 0xBD, 0xE8, +0xF8, 0x8F, 0x88, 0x42, 0x8F, 0xD1, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x07, 0x2A, 0x18, 0xD0, 0xC3, 0xF3, 0x02, 0x18, +0xC8, 0xE7, 0x07, 0x2A, 0x11, 0xD0, 0xC3, 0xF3, 0x02, 0x16, 0xB7, 0xE7, 0x4F, 0xF0, 0x20, 0x0B, 0xD2, 0xE7, 0xB7, 0xF8, +0x8C, 0x00, 0x00, 0xEB, 0x40, 0x00, 0x07, 0xEB, 0x80, 0x00, 0x04, 0x30, 0xFF, 0xF7, 0xBE, 0xFE, 0x81, 0x45, 0xDB, 0xD3, +0xCF, 0xE7, 0x00, 0x26, 0xA6, 0xE7, 0x4F, 0xF0, 0x00, 0x08, 0xAF, 0xE7, 0x0F, 0x2B, 0x84, 0xBF, 0x0F, 0x23, 0x87, 0xF8, +0x9A, 0x30, 0xD8, 0xE7, 0x90, 0xF8, 0xA2, 0x30, 0x99, 0x06, 0x1F, 0xD4, 0x10, 0xB5, 0x90, 0xF8, 0x9B, 0x20, 0x04, 0x46, +0xC2, 0xB9, 0xB0, 0xF8, 0x98, 0x20, 0x92, 0xB9, 0x5A, 0x06, 0x0B, 0xD5, 0xB0, 0xF8, 0xB4, 0x20, 0x09, 0x2A, 0x03, 0xD9, +0xFF, 0xF7, 0x9E, 0xFB, 0x94, 0xF8, 0xA2, 0x30, 0x23, 0xF0, 0x40, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0x20, 0x46, 0xBD, 0xE8, +0x10, 0x40, 0xFF, 0xF7, 0x29, 0xBF, 0x01, 0x3A, 0xA0, 0xF8, 0x98, 0x20, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x20, 0x70, 0x47, +0x2D, 0xE9, 0xF0, 0x41, 0x29, 0x4F, 0x2A, 0x4E, 0xD7, 0xF8, 0x00, 0x80, 0x4F, 0xF4, 0x1E, 0x73, 0xB8, 0xF9, 0x00, 0x20, +0x03, 0xFB, 0x00, 0x63, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x8A, 0xB0, 0x04, 0x46, 0x20, 0xDB, 0x28, 0x46, 0xFF, 0xF7, +0xDF, 0xFB, 0xA5, 0xF8, 0xB4, 0x00, 0xB8, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x22, 0xDB, 0x28, 0x46, 0xFF, 0xF7, 0x6A, 0xFC, +0x69, 0x46, 0x28, 0x46, 0xFF, 0xF7, 0x3C, 0xF9, 0x28, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0x66, 0xFD, 0x4F, 0xF4, 0x1E, 0x70, +0x00, 0xFB, 0x04, 0x64, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x84, 0xF8, 0x56, 0x31, 0x0A, 0xB0, 0xBD, 0xE8, +0xF0, 0x81, 0x00, 0x2D, 0xDC, 0xD1, 0x12, 0x49, 0x12, 0x48, 0x40, 0xF6, 0xAF, 0x42, 0xF1, 0xF7, 0x03, 0xF9, 0xD7, 0xF8, +0x00, 0x80, 0xD3, 0xE7, 0x40, 0xB1, 0x0A, 0x28, 0xD9, 0xD9, 0x0C, 0x49, 0x0D, 0x48, 0x40, 0xF6, 0xB4, 0x42, 0xF1, 0xF7, +0xF7, 0xF8, 0xD2, 0xE7, 0x08, 0x49, 0x0B, 0x48, 0x40, 0xF6, 0xB3, 0x42, 0xF1, 0xF7, 0xF0, 0xF8, 0x3B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xC7, 0xDA, 0xB5, 0xF8, 0xB4, 0x00, 0xE8, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0xDF, 0xF8, 0xBC, 0x80, 0x29, 0x4D, 0xD8, 0xF8, 0x00, 0x40, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x00, 0x53, 0x07, 0x46, +0xB4, 0xF9, 0x00, 0x00, 0xD3, 0xF8, 0x4C, 0x41, 0x00, 0x28, 0x0D, 0x46, 0x16, 0x46, 0x20, 0xDB, 0x94, 0xF8, 0xAF, 0x30, +0xAB, 0x42, 0x39, 0xD0, 0xD8, 0xF8, 0x00, 0x30, 0x84, 0xF8, 0xAF, 0x50, 0xB3, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x26, 0xDB, +0x84, 0xF8, 0xB0, 0x60, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x17, 0xDB, 0x94, 0xF8, 0xA2, 0x30, 0x9A, 0x06, 0x05, 0xD5, +0x63, 0xF0, 0x7F, 0x03, 0x84, 0xF8, 0xA2, 0x30, 0xBD, 0xE8, 0xF0, 0x81, 0x38, 0x46, 0xBD, 0xE8, 0xF0, 0x41, 0xFF, 0xF7, +0x69, 0xBF, 0x00, 0x2C, 0xDC, 0xD1, 0x11, 0x49, 0x11, 0x48, 0x40, 0xF6, 0xCC, 0x42, 0xF1, 0xF7, 0x9F, 0xF8, 0xD5, 0xE7, +0x07, 0x2E, 0xE5, 0xD9, 0x0C, 0x49, 0x0E, 0x48, 0x40, 0xF6, 0xD4, 0x42, 0xF1, 0xF7, 0x96, 0xF8, 0xDE, 0xE7, 0x03, 0x2D, +0xD6, 0xD9, 0x08, 0x49, 0x0A, 0x48, 0x40, 0xF6, 0xD2, 0x42, 0xF1, 0xF7, 0x8D, 0xF8, 0xD8, 0xF8, 0x00, 0x30, 0xCD, 0xE7, +0x94, 0xF8, 0xB0, 0x30, 0xB3, 0x42, 0xC1, 0xD1, 0xD6, 0xE7, 0x00, 0xBF, 0x68, 0x65, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x68, 0x8E, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x4D, 0x4B, 0x8D, 0xB0, 0x1A, 0x68, 0x01, 0x90, 0x04, 0x46, 0x4C, 0x48, 0xB2, 0xF9, 0x00, 0x20, 0x4F, 0xF4, 0x1E, 0x73, +0x03, 0xFB, 0x04, 0x03, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0xB1, 0x0C, 0x46, 0x79, 0xDB, 0x9B, 0xF8, 0xB2, 0x20, 0xA2, 0x42, +0x72, 0xD0, 0x8B, 0xF8, 0xB2, 0x40, 0x00, 0x2C, 0x6E, 0xD0, 0x9B, 0xF8, 0xA2, 0x20, 0x12, 0xF0, 0x20, 0x07, 0x76, 0xD1, +0xBB, 0xF8, 0xB4, 0x90, 0xB8, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0x15, 0xD1, 0x4D, 0xE0, 0x25, 0x44, 0x0C, 0xAB, 0x01, 0x37, +0x0B, 0xEB, 0x85, 0x05, 0x03, 0xEB, 0x84, 0x04, 0xB8, 0xB2, 0x4F, 0xF0, 0x01, 0x03, 0x81, 0x45, 0xAB, 0x73, 0xA6, 0xF8, +0x0A, 0xA0, 0xA6, 0xF8, 0x08, 0x80, 0x85, 0xF8, 0x0D, 0x80, 0x44, 0xF8, 0x28, 0x8C, 0x38, 0xD9, 0xBC, 0xB2, 0x04, 0xEB, +0x44, 0x06, 0x0B, 0xEB, 0x86, 0x06, 0x65, 0x00, 0xB6, 0xF8, 0x0A, 0xA0, 0x50, 0x46, 0xFD, 0xF7, 0x19, 0xFF, 0x00, 0x28, +0xDD, 0xD0, 0x4A, 0xF4, 0x80, 0x6A, 0xB9, 0xF1, 0x00, 0x0F, 0x16, 0xD0, 0x58, 0x46, 0x4F, 0xF0, 0x00, 0x0C, 0x01, 0xE0, +0xCC, 0x45, 0xD2, 0xD0, 0xB0, 0xF8, 0x0A, 0xE0, 0xD6, 0x45, 0x0C, 0xF1, 0x01, 0x0C, 0x00, 0xF1, 0x0C, 0x00, 0xF5, 0xD1, +0x58, 0x46, 0xFE, 0xF7, 0x37, 0xFE, 0xBB, 0xF8, 0xB4, 0x90, 0x82, 0x46, 0xB9, 0xF1, 0x00, 0x0F, 0xE8, 0xD1, 0x28, 0x19, +0x0C, 0xAB, 0x0B, 0xEB, 0x80, 0x00, 0x03, 0xEB, 0x84, 0x04, 0x01, 0x25, 0x85, 0x73, 0xA6, 0xF8, 0x0A, 0xA0, 0xA6, 0xF8, +0x08, 0x90, 0x80, 0xF8, 0x0D, 0x90, 0x44, 0xF8, 0x28, 0x9C, 0x02, 0xA9, 0x58, 0x46, 0xFE, 0xF7, 0xCF, 0xFF, 0x02, 0xA9, +0x58, 0x46, 0xFF, 0xF7, 0x1B, 0xF8, 0x01, 0x9A, 0x11, 0x46, 0x10, 0x4A, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x01, 0x29, +0x99, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x01, 0x03, 0x89, 0xF8, 0x56, 0x31, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBB, 0xF1, +0x00, 0x0F, 0x82, 0xD1, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF6, 0xEA, 0x42, 0xF0, 0xF7, 0xE2, 0xFF, 0x7B, 0xE7, 0x62, 0xF0, +0x7F, 0x02, 0x8B, 0xF8, 0xA2, 0x20, 0x0D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0xB0, 0xF8, 0x54, 0x21, 0x03, 0x29, 0x9A, 0xBF, 0x02, 0xF4, 0x80, 0x62, +0x12, 0xB2, 0x00, 0x22, 0x10, 0xB4, 0x42, 0xEA, 0x01, 0x03, 0xD0, 0xF8, 0x48, 0x41, 0x43, 0xF0, 0x00, 0x53, 0xC4, 0xE9, +0x05, 0x33, 0xC4, 0xE9, 0x07, 0x33, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x90, 0xF8, 0xA5, 0x30, 0xC1, 0xF3, 0xC2, 0x22, +0x93, 0x42, 0x13, 0xD3, 0x05, 0x2B, 0x70, 0xB5, 0x4F, 0xEA, 0xD1, 0x24, 0x11, 0xD0, 0x04, 0x2B, 0x29, 0xD0, 0x02, 0x3B, +0x01, 0x2B, 0x12, 0xD8, 0x14, 0xF0, 0x06, 0x03, 0x04, 0xF0, 0x06, 0x05, 0x26, 0xD1, 0x90, 0xF8, 0xAD, 0x20, 0x03, 0x2A, +0x1B, 0xD8, 0x0D, 0xE0, 0x00, 0x23, 0x18, 0x46, 0x70, 0x47, 0x05, 0x2A, 0x03, 0xD0, 0x90, 0xF8, 0xAD, 0x30, 0x03, 0x2B, +0x15, 0xD8, 0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0x13, 0xD1, 0x4A, 0x05, 0xC1, 0xF3, 0x80, 0x23, 0x03, 0xD4, +0x90, 0xF8, 0xB2, 0x20, 0x01, 0x2A, 0x04, 0xD0, 0xFF, 0xF7, 0x9A, 0xF8, 0x03, 0x1E, 0x18, 0xBF, 0x01, 0x23, 0x18, 0x46, +0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD0, 0x00, 0x23, 0x18, 0x46, 0x70, 0xBD, 0x04, 0x2A, 0x1A, 0xD9, 0x90, 0xF8, 0xAF, 0x60, +0xC1, 0xF3, 0xC1, 0x13, 0x9E, 0x42, 0xF4, 0xD3, 0x63, 0x07, 0x08, 0xD5, 0x07, 0x2A, 0xE7, 0xD0, 0xC1, 0xF3, 0x02, 0x13, +0x90, 0xF8, 0xB0, 0x20, 0x9A, 0x42, 0xEA, 0xD3, 0xE0, 0xE7, 0x00, 0x2D, 0xDE, 0xD0, 0xC1, 0xF3, 0xC1, 0x03, 0xF5, 0xE7, +0x14, 0xF0, 0x06, 0x0F, 0x04, 0xF0, 0x06, 0x05, 0xCE, 0xD0, 0x8E, 0x05, 0xE2, 0xD5, 0x90, 0xF8, 0xB1, 0x30, 0x00, 0x2B, +0xD5, 0xD0, 0xDD, 0xE7, 0x01, 0xEB, 0x41, 0x01, 0x00, 0xEB, 0x81, 0x03, 0x2D, 0xE9, 0xF0, 0x47, 0x1F, 0x89, 0x80, 0x46, +0x41, 0xF6, 0x98, 0x10, 0x87, 0x42, 0x38, 0xD9, 0xB3, 0xF8, 0x0A, 0x90, 0xD8, 0xF8, 0x94, 0xA0, 0x48, 0x46, 0x15, 0x46, +0x8C, 0x00, 0xFD, 0xF7, 0x2F, 0xFE, 0x08, 0xB3, 0x00, 0x26, 0x20, 0x1D, 0x40, 0x44, 0xFF, 0xF7, 0x8D, 0xFC, 0x2D, 0x4A, +0x4F, 0xF4, 0x7A, 0x73, 0x30, 0x44, 0x03, 0xFB, 0x07, 0xF3, 0xB3, 0xFB, 0xF0, 0xF3, 0x02, 0xFB, 0x03, 0xF3, 0x18, 0x0C, +0x75, 0xB1, 0x43, 0xF2, 0x32, 0x33, 0x9F, 0x42, 0x1C, 0xD9, 0x44, 0xF6, 0xCB, 0x43, 0x9F, 0x42, 0x21, 0xD8, 0x24, 0x4B, +0x5A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x20, 0x4E, 0x21, 0x4B, +0xC9, 0xF3, 0xC2, 0x29, 0x4F, 0xEA, 0x1A, 0x4A, 0xB9, 0xF1, 0x06, 0x0F, 0x08, 0xBF, 0x1E, 0x46, 0xB6, 0xFB, 0xFA, 0xF6, +0xD1, 0xE7, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x17, 0x4B, 0x1A, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, +0x44, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0x46, 0xF2, 0x65, 0x63, 0x9F, 0x42, 0x0A, 0xD9, 0xB7, 0xF5, 0x00, 0x4F, 0x0F, 0xD2, +0x0F, 0x4B, 0xDA, 0x78, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xD5, 0xE7, 0x0B, 0x4B, 0x9A, 0x78, +0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xCD, 0xE7, 0x49, 0xF6, 0x98, 0x13, 0x9F, 0x42, 0x06, 0x4B, +0x94, 0xBF, 0x1A, 0x79, 0x5A, 0x79, 0xA2, 0xFB, 0x00, 0x34, 0xD8, 0x09, 0x40, 0xEA, 0x44, 0x60, 0xC0, 0xE7, 0x00, 0xBF, +0xB0, 0xE2, 0x0D, 0x00, 0x54, 0x25, 0x17, 0x00, 0x90, 0x53, 0x03, 0x00, 0x10, 0x09, 0x05, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, +0x8F, 0xB0, 0x00, 0xF1, 0x88, 0x09, 0x02, 0xAD, 0x01, 0x91, 0x04, 0x46, 0x4A, 0x46, 0x07, 0x46, 0x00, 0xF1, 0x90, 0x06, +0x29, 0x46, 0x32, 0xF8, 0x02, 0x3B, 0x03, 0xEB, 0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0xB2, 0x42, 0x5B, 0x89, 0x21, 0xF8, +0x02, 0x3B, 0xF4, 0xD1, 0xB4, 0xF8, 0x92, 0x10, 0x71, 0xB1, 0xD4, 0xF8, 0x94, 0x20, 0xB4, 0xF8, 0x90, 0x30, 0x02, 0xEB, +0x42, 0x02, 0x1B, 0x04, 0x93, 0xFB, 0xF1, 0xF3, 0x13, 0x44, 0xC3, 0xF3, 0x98, 0x03, 0x00, 0x22, 0xC4, 0xE9, 0x24, 0x23, +0x04, 0xF1, 0x7C, 0x00, 0xFE, 0xF7, 0x2A, 0xF8, 0xB4, 0xF8, 0xB4, 0x00, 0x00, 0x21, 0xA4, 0xF8, 0x7C, 0x10, 0xA4, 0xF8, +0x7E, 0x10, 0x84, 0xF8, 0x9A, 0x10, 0x00, 0x28, 0x74, 0xD0, 0x01, 0x38, 0x05, 0xAB, 0x80, 0xB2, 0x0D, 0xF1, 0x10, 0x0A, +0x03, 0xEB, 0x80, 0x00, 0x52, 0x46, 0x23, 0x46, 0x4F, 0xF0, 0x01, 0x0C, 0x42, 0xF8, 0x04, 0x1B, 0x82, 0x42, 0x83, 0xF8, +0x0E, 0xC0, 0x03, 0xF1, 0x0C, 0x03, 0xF7, 0xD1, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x14, 0xD0, +0x32, 0x4B, 0x20, 0x46, 0xD3, 0xF8, 0x6C, 0x32, 0x98, 0x47, 0x39, 0xF8, 0x02, 0x3B, 0x35, 0xF8, 0x02, 0x2B, 0x03, 0xEB, +0x43, 0x03, 0x04, 0xEB, 0x83, 0x03, 0x5B, 0x89, 0x93, 0x42, 0x47, 0xD1, 0xB1, 0x45, 0xF2, 0xD1, 0x0F, 0xB0, 0xBD, 0xE8, +0xF0, 0x8F, 0x4F, 0xF0, 0x00, 0x08, 0x1F, 0xFA, 0x88, 0xFB, 0x0B, 0xEB, 0x4B, 0x00, 0x04, 0xEB, 0x80, 0x00, 0x04, 0x30, +0xFD, 0xF7, 0xE6, 0xFF, 0x01, 0x22, 0x5F, 0xFA, 0x88, 0xF1, 0x20, 0x46, 0x90, 0x44, 0xFF, 0xF7, 0x09, 0xFF, 0xB4, 0xF8, +0xB4, 0x10, 0x0E, 0xAB, 0x03, 0xEB, 0x8B, 0x0B, 0x1F, 0xFA, 0x88, 0xF2, 0x91, 0x42, 0x4B, 0xF8, 0x28, 0x0C, 0xE4, 0xD8, +0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x26, 0xFE, 0x51, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x72, 0xFE, 0x01, 0x9B, 0xCB, 0xB9, +0x94, 0xF8, 0xA2, 0x20, 0xB4, 0xF8, 0xB4, 0x30, 0x42, 0xF0, 0x40, 0x02, 0x84, 0xF8, 0xA2, 0x20, 0x83, 0xB1, 0x01, 0x3B, +0x9B, 0xB2, 0x03, 0xEB, 0x43, 0x02, 0xDD, 0xF8, 0x04, 0x80, 0x04, 0xF1, 0x0C, 0x03, 0x03, 0xEB, 0x82, 0x03, 0xA7, 0xF8, +0x04, 0x80, 0xA7, 0xF8, 0x06, 0x80, 0x0C, 0x37, 0x9F, 0x42, 0xF8, 0xD1, 0x00, 0x20, 0xAC, 0xE7, 0x01, 0x20, 0x0F, 0xB0, +0xBD, 0xE8, 0xF0, 0x8F, 0xB4, 0xF8, 0xBA, 0x20, 0x4F, 0xF6, 0xFF, 0x73, 0x9A, 0x42, 0x9D, 0xD1, 0x0D, 0xF1, 0x10, 0x0A, +0xCC, 0xE7, 0x00, 0xBF, 0x88, 0x1A, 0x17, 0x00, 0x38, 0xB5, 0x23, 0x4B, 0x23, 0x4A, 0x1B, 0x68, 0x4F, 0xF4, 0x1E, 0x71, +0xB3, 0xF9, 0x00, 0x30, 0x01, 0xFB, 0x00, 0x20, 0x00, 0x2B, 0xD0, 0xF8, 0x4C, 0x41, 0x2F, 0xDB, 0x20, 0x46, 0xFF, 0xF7, +0x5D, 0xF9, 0xB4, 0xF8, 0xB4, 0x30, 0x59, 0x1E, 0x9A, 0x1E, 0x21, 0xEA, 0xE1, 0x71, 0x03, 0x3B, 0x22, 0xEA, 0xE2, 0x72, +0x23, 0xEA, 0xE3, 0x73, 0x00, 0x25, 0x4F, 0xF4, 0x80, 0x30, 0xA4, 0xF8, 0x88, 0x10, 0x4F, 0xF6, 0xFF, 0x71, 0xA4, 0xF8, +0x8A, 0x20, 0xA4, 0xF8, 0x8C, 0x30, 0xC4, 0xF8, 0x94, 0x00, 0xA4, 0xF8, 0xBA, 0x10, 0xA4, 0xF8, 0x8E, 0x50, 0x84, 0xF8, +0xA2, 0x50, 0x01, 0x21, 0x20, 0x46, 0xFF, 0xF7, 0x13, 0xFF, 0x94, 0xF8, 0xB4, 0x30, 0x84, 0xF8, 0x9B, 0x50, 0x04, 0x3B, +0x05, 0x22, 0x84, 0xF8, 0xA0, 0x30, 0xA4, 0xF8, 0x98, 0x20, 0x38, 0xBD, 0x00, 0x2C, 0xCD, 0xD1, 0x05, 0x49, 0x06, 0x48, +0x40, 0xF6, 0x76, 0x02, 0xF0, 0xF7, 0xDE, 0xFD, 0xC6, 0xE7, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xDF, 0xF8, 0xC4, 0xA3, 0x90, 0xF8, 0x23, 0x70, +0xDA, 0xF8, 0x00, 0x30, 0xD0, 0xF8, 0x48, 0x81, 0xB3, 0xF9, 0x00, 0x30, 0x8B, 0xB0, 0x07, 0xF1, 0x10, 0x02, 0xD2, 0xB2, +0x00, 0x2B, 0x04, 0x46, 0x06, 0x92, 0xC0, 0xF2, 0xA9, 0x81, 0xDA, 0x4D, 0x07, 0xEB, 0x47, 0x03, 0x05, 0xEB, 0x83, 0x1B, +0xC4, 0xF8, 0x4C, 0xB1, 0x9B, 0x01, 0x04, 0x93, 0xCD, 0xF7, 0xB4, 0xF9, 0x83, 0x03, 0x05, 0x93, 0xCD, 0xF7, 0xB0, 0xF9, +0x4F, 0xF0, 0x01, 0x09, 0x01, 0x30, 0x09, 0xFA, 0x00, 0xF9, 0x00, 0x21, 0x58, 0x46, 0xC0, 0x22, 0xCC, 0xF7, 0xBE, 0xF8, +0x61, 0x68, 0x11, 0xF0, 0x02, 0x01, 0x09, 0xF1, 0xFF, 0x39, 0x00, 0xF0, 0x9D, 0x80, 0x00, 0x21, 0x04, 0xF1, 0xB8, 0x00, +0xF3, 0xF7, 0xB4, 0xFB, 0x63, 0x68, 0xAB, 0xF8, 0xAA, 0x00, 0x98, 0x06, 0x4F, 0xEA, 0x47, 0x06, 0x00, 0xF1, 0x30, 0x82, +0x58, 0x07, 0x40, 0xF1, 0xA3, 0x81, 0xC3, 0x4B, 0x07, 0x93, 0x04, 0x23, 0xB4, 0xF8, 0xEC, 0x00, 0x8B, 0xF8, 0xA5, 0x30, +0xCD, 0xF8, 0x24, 0xB0, 0xF3, 0xF7, 0xBA, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0xB4, 0xFA, +0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xC0, 0x83, 0x07, 0x9B, 0xB4, 0xF8, 0xEC, 0x00, 0x19, 0x8F, 0xF3, 0xF7, 0xCA, 0xFB, +0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0xEC, 0x00, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, +0x7D, 0xFA, 0x07, 0x9A, 0x03, 0x46, 0x10, 0x8F, 0x08, 0x93, 0xF3, 0xF7, 0x77, 0xFA, 0x08, 0x9B, 0x09, 0x9A, 0x98, 0x42, +0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, +0x91, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, 0x80, 0xB2, +0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x96, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, +0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x6D, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, +0xF3, 0xF7, 0x92, 0xFA, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xC0, 0xF2, 0x4E, 0x83, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, +0xB2, 0x20, 0xCD, 0xF7, 0xD1, 0xF8, 0x00, 0x28, 0x40, 0xF0, 0x04, 0x83, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, +0x01, 0x2B, 0x00, 0xF0, 0xD4, 0x83, 0x02, 0x2B, 0x00, 0xF0, 0xD9, 0x83, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, +0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x88, 0xE1, 0x04, 0xF1, 0xB8, 0x00, 0xF3, 0xF7, 0x18, 0xFB, 0x07, 0xEB, 0x47, 0x03, +0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x4D, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, +0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x4F, 0xEA, 0x47, 0x06, 0xC0, 0xF2, 0xBC, 0x80, 0xF3, 0x19, +0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x47, 0xFA, 0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, +0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x9E, 0x80, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, +0xFF, 0x21, 0x83, 0xF8, 0xAC, 0x10, 0x94, 0xF8, 0x2D, 0x11, 0x83, 0xF8, 0xAF, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xC0, 0xF2, 0x83, 0x80, 0xB4, 0xF8, 0x54, 0x11, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC1, 0xF3, 0x80, 0x21, 0x83, 0xF8, +0xB2, 0x10, 0x58, 0x46, 0x07, 0x92, 0xFE, 0xF7, 0x71, 0xFF, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x9A, 0xA3, 0xF8, +0xB4, 0x00, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0xC0, 0xF2, 0x8D, 0x80, 0x3E, 0x44, 0x05, 0xEB, 0x86, 0x1A, 0x94, 0xF8, +0x23, 0x30, 0x9A, 0xF8, 0xAF, 0x70, 0x9A, 0xF8, 0xB1, 0x00, 0x9A, 0xF8, 0xB2, 0x10, 0x9A, 0xF8, 0xA5, 0x20, 0xCD, 0xE9, +0x02, 0x07, 0xCD, 0xE9, 0x00, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0x4B, 0x4A, 0x4B, 0x49, 0xF0, 0xF7, 0x6F, 0xFA, 0xBA, 0xF8, +0xB4, 0x00, 0x9A, 0xF8, 0xAE, 0x10, 0x9A, 0xF8, 0xAD, 0x20, 0x9A, 0xF8, 0xAC, 0x30, 0xCD, 0xE9, 0x02, 0x10, 0xCD, 0xE9, +0x00, 0x32, 0x45, 0x49, 0x42, 0x4A, 0x9A, 0xF8, 0xB0, 0x30, 0x4F, 0xF4, 0x80, 0x50, 0xF0, 0xF7, 0x5B, 0xFA, 0x94, 0xF8, +0x23, 0x00, 0xFF, 0xF7, 0x5D, 0xFE, 0x04, 0x99, 0x88, 0x31, 0xB0, 0x01, 0x29, 0x44, 0x08, 0xF1, 0x14, 0x02, 0x08, 0xF1, +0x24, 0x07, 0x31, 0xF8, 0x02, 0x3B, 0xDB, 0xB2, 0x03, 0xEB, 0x43, 0x03, 0x00, 0xEB, 0x83, 0x03, 0x2B, 0x44, 0x5B, 0x89, +0x43, 0xF0, 0x80, 0x43, 0x42, 0xF8, 0x04, 0x3B, 0x97, 0x42, 0xF0, 0xD1, 0x58, 0x46, 0x00, 0x21, 0xFF, 0xF7, 0xB4, 0xF8, +0x32, 0x4A, 0x06, 0x99, 0x12, 0x69, 0xD4, 0xF8, 0x48, 0x31, 0x31, 0x4F, 0x31, 0x48, 0xB6, 0x01, 0x89, 0x02, 0xAA, 0x51, +0xA2, 0x69, 0x05, 0x9D, 0xC8, 0xF8, 0x0C, 0x10, 0x4F, 0xF4, 0x08, 0x51, 0xC8, 0xE9, 0x01, 0x59, 0xC8, 0xF8, 0x00, 0x70, +0xC8, 0xF8, 0x10, 0x00, 0xC3, 0xE9, 0x0D, 0x12, 0x94, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x11, 0x03, 0x84, 0xF8, 0x56, 0x31, +0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x29, 0x3F, 0xF4, 0x7A, 0xAF, 0x40, 0xF6, 0x21, 0x42, 0x22, 0x49, 0x23, 0x48, +0xF0, 0xF7, 0x3C, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x70, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x5F, 0xAF, 0x40, 0xF6, 0x1E, 0x42, +0x1C, 0x49, 0x1E, 0x48, 0xF0, 0xF7, 0x30, 0xFC, 0xDA, 0xF8, 0x00, 0x20, 0x55, 0xE7, 0x0B, 0x28, 0x7F, 0xF6, 0x41, 0xAF, +0x17, 0x49, 0x1A, 0x48, 0x40, 0xF6, 0x1C, 0x42, 0xF0, 0xF7, 0x24, 0xFC, 0x39, 0xE7, 0x00, 0x28, 0x00, 0xF0, 0xFE, 0x81, +0x0A, 0x28, 0x7F, 0xF6, 0x6D, 0xAF, 0x11, 0x49, 0x14, 0x48, 0x40, 0xF6, 0x28, 0x42, 0xF0, 0xF7, 0x17, 0xFC, 0x65, 0xE7, +0x09, 0x2F, 0x7F, 0xF6, 0x54, 0xAE, 0x0C, 0x49, 0x10, 0x48, 0x40, 0xF6, 0xEB, 0x22, 0xF0, 0xF7, 0x0D, 0xFC, 0x94, 0xF8, +0x23, 0x70, 0x4A, 0xE6, 0xF4, 0xE7, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x4C, 0xCC, 0x15, 0x00, 0xC4, 0xCB, 0x15, 0x00, +0x08, 0xCC, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x1E, 0xAB, 0xDC, 0xBA, 0x04, 0x07, 0xFF, 0xFF, 0x70, 0x79, 0x15, 0x00, +0xA8, 0xCB, 0x15, 0x00, 0x84, 0xCB, 0x15, 0x00, 0x60, 0xCB, 0x15, 0x00, 0x0C, 0xCA, 0x15, 0x00, 0x64, 0xCA, 0x15, 0x00, +0x38, 0x36, 0x17, 0x00, 0x04, 0xF1, 0xCB, 0x03, 0x02, 0x21, 0x18, 0x46, 0x8B, 0xF8, 0xA5, 0x10, 0x09, 0x93, 0xCD, 0xF8, +0x20, 0xB0, 0xF3, 0xF7, 0x2B, 0xF9, 0x01, 0x46, 0xD9, 0x48, 0x07, 0x91, 0xF3, 0xF7, 0x26, 0xF9, 0x07, 0x99, 0x08, 0x9A, +0x09, 0x9B, 0x88, 0x42, 0x28, 0xBF, 0x08, 0x46, 0xDA, 0xF8, 0x00, 0x10, 0x82, 0xF8, 0xB0, 0x00, 0xB1, 0xF9, 0x00, 0x20, +0x00, 0x2A, 0xC0, 0xF2, 0x41, 0x82, 0x04, 0x9A, 0x02, 0xF1, 0xA6, 0x00, 0x19, 0x46, 0x04, 0x22, 0x28, 0x44, 0x02, 0xF0, +0x6B, 0xFE, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xFF, 0x22, 0xB3, 0xF8, 0xAA, 0x00, 0x83, 0xF8, 0xA6, 0x20, 0x20, 0xF4, +0x7F, 0x60, 0x07, 0x22, 0x80, 0xB2, 0x83, 0xF8, 0xAC, 0x20, 0xA3, 0xF8, 0xAA, 0x00, 0x07, 0x93, 0xF3, 0xF7, 0x0A, 0xF9, +0x07, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x0F, 0x82, +0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x07, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x06, 0xF9, 0x07, 0x9B, 0xDA, 0xF8, +0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xF0, 0x81, 0xB4, 0xF8, 0x54, 0x21, +0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, 0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0x45, 0xFF, 0x00, 0x28, +0x40, 0xF0, 0x88, 0x81, 0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, +0x14, 0xBF, 0x40, 0xF6, 0xB5, 0x72, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0xF1, 0x19, 0x05, 0xEB, 0x81, 0x11, +0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0x81, 0xF8, 0xAF, 0x30, 0xB2, 0xF9, 0x00, 0x10, 0x00, 0x29, 0xC0, 0xF2, +0x31, 0x81, 0x03, 0x2B, 0x3F, 0xF6, 0xA9, 0xAE, 0xDF, 0xE8, 0x13, 0xF0, 0x26, 0x01, 0x20, 0x01, 0x15, 0x01, 0x04, 0x01, +0x05, 0x23, 0x94, 0xF8, 0x22, 0x10, 0xB4, 0xF8, 0x06, 0x01, 0x8B, 0xF8, 0xA5, 0x30, 0x07, 0x91, 0xCD, 0xF8, 0x24, 0xB0, +0xF3, 0xF7, 0x8C, 0xF8, 0x95, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x85, 0xF8, 0x08, 0x9B, +0x09, 0x9A, 0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xB0, 0x00, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xC0, 0xF2, 0xE5, 0x81, 0x8B, 0x4B, 0xB4, 0xF8, 0x06, 0x01, 0xB3, 0xF8, 0x50, 0x10, 0xF3, 0xF7, 0x9A, 0xF9, +0xF2, 0x19, 0x05, 0xEB, 0x82, 0x12, 0x03, 0x46, 0xB4, 0xF8, 0x06, 0x01, 0xA2, 0xF8, 0xA6, 0x30, 0x09, 0x92, 0xF3, 0xF7, +0x59, 0xF8, 0x82, 0x4A, 0x03, 0x46, 0xB2, 0xF8, 0x50, 0x00, 0x08, 0x93, 0xF3, 0xF7, 0x52, 0xF8, 0x08, 0x9B, 0x09, 0x9A, +0x98, 0x42, 0x28, 0xBF, 0x18, 0x46, 0xDA, 0xF8, 0x00, 0x30, 0x82, 0xF8, 0xAC, 0x00, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xC0, 0xF2, 0xB4, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, 0xAA, 0x00, 0x20, 0xF4, 0x7F, 0x60, +0x80, 0xB2, 0xA3, 0xF8, 0xAA, 0x00, 0xF3, 0xF7, 0x65, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAD, 0x00, +0xB2, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0x90, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x08, 0x93, 0xB3, 0xF8, +0xAA, 0x00, 0xF3, 0xF7, 0x61, 0xF8, 0x08, 0x9B, 0xDA, 0xF8, 0x00, 0x20, 0x83, 0xF8, 0xAE, 0x00, 0xB2, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0xC0, 0xF2, 0x71, 0x81, 0xB4, 0xF8, 0x54, 0x21, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0xC2, 0xF3, 0x80, 0x22, +0x83, 0xF8, 0xB2, 0x20, 0xCC, 0xF7, 0xA0, 0xFE, 0x28, 0xB1, 0x5D, 0x4B, 0x93, 0xF8, 0x43, 0x30, 0x99, 0x06, 0x00, 0xF1, +0x99, 0x81, 0x63, 0x68, 0x5B, 0x07, 0x40, 0xF1, 0xEB, 0x80, 0xD4, 0xF8, 0xE8, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x01, 0x2B, +0x00, 0xF0, 0xBD, 0x81, 0x02, 0x2B, 0x00, 0xF0, 0xB2, 0x81, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x40, 0xF6, 0xED, 0x62, +0xA3, 0xF8, 0xB6, 0x20, 0x50, 0x4B, 0x07, 0x99, 0x4F, 0xF4, 0xA4, 0x62, 0x02, 0xFB, 0x01, 0x33, 0x93, 0xF8, 0x62, 0x20, +0x00, 0x2A, 0x40, 0xF0, 0xDF, 0x80, 0xD3, 0xF8, 0xC8, 0x31, 0xD4, 0xF8, 0x48, 0x01, 0x13, 0xF4, 0x80, 0x3F, 0xC1, 0x6B, +0x40, 0xF0, 0x69, 0x81, 0x41, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0x06, 0xDB, 0xC3, 0xF3, 0x05, 0x63, 0x49, 0xEA, +0x03, 0x59, 0x02, 0x2A, 0x00, 0xF0, 0x58, 0x81, 0x49, 0xF0, 0x80, 0x59, 0x49, 0xF4, 0xC0, 0x29, 0x3D, 0x4B, 0x93, 0xF8, +0x45, 0x10, 0x94, 0xF8, 0xFD, 0x30, 0x01, 0xF0, 0x03, 0x00, 0xC3, 0xF3, 0xC1, 0x03, 0x83, 0x42, 0x06, 0xEB, 0x07, 0x02, +0x28, 0xBF, 0x03, 0x46, 0x05, 0xEB, 0x82, 0x12, 0x01, 0x20, 0x83, 0x42, 0x82, 0xF8, 0xBC, 0x00, 0x00, 0xF0, 0x6A, 0x81, +0x02, 0x2B, 0x00, 0xF0, 0x64, 0x81, 0x00, 0x2B, 0x00, 0xF0, 0x68, 0x81, 0x04, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x2E, 0x4B, +0x94, 0xF8, 0xFD, 0xC0, 0x93, 0xF8, 0x4B, 0x00, 0x93, 0xF8, 0x4A, 0x20, 0x8B, 0x08, 0xF1, 0x19, 0x03, 0xEA, 0x5C, 0x13, +0x05, 0xEB, 0x81, 0x11, 0x03, 0xF0, 0x01, 0x03, 0x81, 0xF8, 0xBE, 0x30, 0x94, 0xF8, 0x03, 0xC1, 0x94, 0xF8, 0x02, 0x31, +0x0C, 0xF0, 0x01, 0x0C, 0x9B, 0x11, 0x00, 0xF0, 0x01, 0x00, 0x92, 0x11, 0x43, 0xEA, 0x8C, 0x03, 0x42, 0xEA, 0x80, 0x02, +0x93, 0x42, 0x28, 0xBF, 0x13, 0x46, 0x81, 0xF8, 0xBF, 0x30, 0xE8, 0xE6, 0xD4, 0xF8, 0xE8, 0x30, 0x59, 0x06, 0x7F, 0xF5, +0x9E, 0xAD, 0x19, 0x4B, 0x9B, 0x89, 0x5B, 0x06, 0x7F, 0xF5, 0x99, 0xAD, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x01, 0x21, +0x83, 0xF8, 0xB1, 0x10, 0x91, 0xE5, 0xD4, 0xF8, 0xE8, 0x30, 0x9B, 0x06, 0x7F, 0xF5, 0x8D, 0xAD, 0x10, 0x4B, 0x9B, 0x89, +0x98, 0x06, 0x7F, 0xF5, 0x88, 0xAD, 0xED, 0xE7, 0xB4, 0xF8, 0xC8, 0x30, 0x59, 0x06, 0x7F, 0xF5, 0x82, 0xAD, 0xE2, 0xE7, +0xB4, 0xF8, 0xC8, 0x30, 0x98, 0x06, 0x7F, 0xF5, 0x7C, 0xAD, 0xED, 0xE7, 0x03, 0x2B, 0x7F, 0xF6, 0xCC, 0xAE, 0x40, 0xF6, +0xF9, 0x32, 0x07, 0x49, 0x07, 0x48, 0xF0, 0xF7, 0x31, 0xFA, 0x94, 0xF8, 0x2D, 0x31, 0xDA, 0xF8, 0x00, 0x20, 0xC0, 0xE6, +0xF3, 0xB8, 0x17, 0x00, 0xE4, 0xB8, 0x17, 0x00, 0x18, 0x88, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x34, 0xCA, 0x15, 0x00, +0x40, 0xF6, 0x27, 0x42, 0x88, 0x49, 0x89, 0x48, 0x07, 0x93, 0xF0, 0xF7, 0x1B, 0xFA, 0xDA, 0xF8, 0x00, 0x20, 0xB2, 0xF9, +0x00, 0x20, 0x00, 0x2A, 0xBF, 0xF6, 0x64, 0xAD, 0x07, 0x9B, 0xB3, 0xF8, 0xB4, 0x00, 0xEF, 0xE5, 0x07, 0x9B, 0x1B, 0x6B, +0x13, 0xF0, 0x10, 0x0F, 0xD4, 0xF8, 0xE8, 0x30, 0x3F, 0xF4, 0xF6, 0xAC, 0xD9, 0x06, 0x7F, 0xF5, 0xF3, 0xAC, 0x05, 0x9A, +0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0xED, 0xE4, 0x7A, 0x4B, 0x9B, 0x89, 0x13, 0xF0, 0x01, 0x0F, 0xB4, 0xF8, 0xC8, 0x30, +0x3F, 0xF4, 0x72, 0xAE, 0xDA, 0x07, 0x7F, 0xF5, 0x6F, 0xAE, 0x05, 0x9A, 0x42, 0xF0, 0x40, 0x02, 0x05, 0x92, 0x69, 0xE6, +0xB4, 0xF8, 0xC8, 0x30, 0x13, 0xF4, 0x00, 0x6F, 0x06, 0xEB, 0x07, 0x03, 0x05, 0xEB, 0x83, 0x13, 0x14, 0xBF, 0x41, 0xF6, +0xFF, 0x62, 0x40, 0xF6, 0xFF, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x15, 0xE7, 0xD4, 0xF8, 0x48, 0x01, 0xD3, 0xF8, 0xC8, 0x31, +0xC1, 0x6B, 0x00, 0x2B, 0x21, 0xF0, 0x20, 0x01, 0xC1, 0x63, 0xBF, 0xF6, 0x24, 0xAF, 0x26, 0xE7, 0x03, 0x28, 0x7F, 0xF6, +0xAF, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0xAC, 0xAC, 0x5F, 0x49, 0x62, 0x48, 0x40, 0xF6, 0xA2, 0x32, 0xF0, 0xF7, 0xC8, 0xF9, +0xA4, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x90, 0xAC, 0x0C, 0x28, 0x3F, 0xF4, 0x8D, 0xAC, 0x59, 0x49, 0x5C, 0x48, 0x4F, 0xF4, +0x3A, 0x62, 0xF0, 0xF7, 0xBB, 0xF9, 0x85, 0xE4, 0x09, 0x28, 0x7F, 0xF6, 0x6C, 0xAC, 0x54, 0x49, 0x58, 0x48, 0x40, 0xF6, +0x94, 0x32, 0xF0, 0xF7, 0xB1, 0xF9, 0x64, 0xE4, 0x07, 0x28, 0x7F, 0xF6, 0x3D, 0xAC, 0x4F, 0x49, 0x54, 0x48, 0x40, 0xF6, +0x8E, 0x32, 0xF0, 0xF7, 0xA7, 0xF9, 0x35, 0xE4, 0x03, 0x28, 0x7F, 0xF6, 0x0D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x0A, 0xAE, +0x48, 0x49, 0x4B, 0x48, 0x40, 0xF6, 0xD9, 0x32, 0xF0, 0xF7, 0x9A, 0xF9, 0x02, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0xEE, 0xAD, +0x0C, 0x28, 0x3F, 0xF4, 0xEB, 0xAD, 0x42, 0x49, 0x45, 0x48, 0x40, 0xF6, 0xD7, 0x32, 0xF0, 0xF7, 0x8D, 0xF9, 0xE3, 0xE5, +0x03, 0x28, 0x7F, 0xF6, 0xBC, 0xAD, 0x3D, 0x49, 0x43, 0x48, 0x07, 0x93, 0x40, 0xF6, 0xCC, 0x32, 0xF0, 0xF7, 0x82, 0xF9, +0x07, 0x9B, 0xB2, 0xE5, 0x03, 0x28, 0x7F, 0xF6, 0x8C, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, 0x89, 0xAE, 0x35, 0x49, 0x38, 0x48, +0x40, 0xF6, 0x22, 0x32, 0xF0, 0xF7, 0x74, 0xF9, 0x81, 0xE6, 0x03, 0x28, 0x7F, 0xF6, 0x6D, 0xAE, 0x0C, 0x28, 0x3F, 0xF4, +0x6A, 0xAE, 0x2F, 0x49, 0x32, 0x48, 0x4F, 0xF4, 0x32, 0x62, 0xF0, 0xF7, 0x67, 0xF9, 0x62, 0xE6, 0x0B, 0x28, 0x7F, 0xF6, +0x49, 0xAE, 0x2A, 0x49, 0x31, 0x48, 0x40, 0xF6, 0x1C, 0x32, 0xF0, 0xF7, 0x5D, 0xF9, 0x41, 0xE6, 0x07, 0x28, 0x7F, 0xF6, +0x18, 0xAE, 0x25, 0x49, 0x2A, 0x48, 0x40, 0xF6, 0x16, 0x32, 0xF0, 0xF7, 0x53, 0xF9, 0x10, 0xE6, 0x49, 0xF0, 0x80, 0x59, +0x49, 0xF4, 0x00, 0x39, 0xA6, 0xE6, 0x21, 0xF0, 0x20, 0x01, 0x00, 0x2B, 0xC1, 0x63, 0xBF, 0xF6, 0x96, 0xAE, 0x9B, 0xE6, +0x94, 0xF8, 0x2D, 0x31, 0x23, 0xB9, 0x94, 0xF8, 0xFB, 0x30, 0x9A, 0x06, 0x7F, 0xF5, 0x5F, 0xAE, 0x05, 0x9B, 0x43, 0xF0, +0x40, 0x03, 0x05, 0x93, 0x59, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, +0xB7, 0xE5, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0xAF, 0xE5, 0x82, 0xF8, +0xBD, 0x00, 0x9E, 0xE6, 0x00, 0x23, 0x82, 0xF8, 0xBD, 0x30, 0x9A, 0xE6, 0x82, 0xF8, 0xBC, 0x30, 0xA5, 0xE5, 0xF3, 0x19, +0x05, 0xEB, 0x83, 0x13, 0x42, 0xF6, 0x74, 0x42, 0xA3, 0xF8, 0xB6, 0x20, 0x4C, 0xE6, 0xF3, 0x19, 0x05, 0xEB, 0x83, 0x13, +0x41, 0xF6, 0xED, 0x62, 0xA3, 0xF8, 0xB6, 0x20, 0x44, 0xE6, 0x00, 0xBF, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xC9, 0x15, 0x00, +0xE4, 0xB8, 0x17, 0x00, 0xE8, 0xCA, 0x15, 0x00, 0x98, 0xCA, 0x15, 0x00, 0x38, 0xCB, 0x15, 0x00, 0x50, 0xCA, 0x15, 0x00, +0x4C, 0xCB, 0x15, 0x00, 0x84, 0xCA, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x43, 0x46, 0x7F, 0x09, 0x2E, 0x83, 0xB0, 0x04, 0x46, +0x00, 0xF2, 0x8D, 0x80, 0x4B, 0x4B, 0x4C, 0x4F, 0x1A, 0x68, 0x4F, 0xF4, 0x1E, 0x73, 0xB2, 0xF9, 0x00, 0x20, 0x03, 0xFB, +0x06, 0x73, 0x00, 0x2A, 0xD3, 0xF8, 0x4C, 0x51, 0x40, 0xDB, 0x95, 0xF8, 0xA2, 0x30, 0x59, 0x07, 0x34, 0xD4, 0x03, 0xF0, +0xFD, 0x03, 0x4F, 0xF0, 0x00, 0x08, 0xDF, 0xF8, 0x18, 0x91, 0x85, 0xF8, 0xA2, 0x30, 0xD9, 0xF8, 0x10, 0x30, 0x2A, 0x68, +0x3F, 0x49, 0x9B, 0x1A, 0x8B, 0x42, 0x36, 0xD8, 0x95, 0xF8, 0xA3, 0x20, 0x95, 0xF8, 0xA4, 0x30, 0x43, 0xEA, 0x82, 0x03, +0x84, 0xF8, 0x36, 0x30, 0x28, 0x46, 0xFE, 0xF7, 0x65, 0xFF, 0xB0, 0xB1, 0xE2, 0x8B, 0x94, 0xF8, 0x36, 0x30, 0x42, 0xF4, +0x00, 0x52, 0x23, 0xF0, 0x03, 0x03, 0xE2, 0x83, 0x84, 0xF8, 0x36, 0x30, 0xB8, 0xF1, 0x00, 0x0F, 0x59, 0xD1, 0x4F, 0xF4, +0x1E, 0x73, 0x03, 0xFB, 0x06, 0x76, 0x96, 0xF8, 0x56, 0x31, 0x43, 0xF0, 0x20, 0x03, 0x86, 0xF8, 0x56, 0x31, 0x03, 0xB0, +0xBD, 0xE8, 0xF0, 0x83, 0x62, 0x6A, 0x92, 0x02, 0xC7, 0xD5, 0x43, 0xF0, 0x02, 0x03, 0x4F, 0xF0, 0x01, 0x08, 0xC6, 0xE7, +0x00, 0x2D, 0xBC, 0xD1, 0x26, 0x49, 0x27, 0x48, 0x40, 0xF6, 0x9A, 0x22, 0xF0, 0xF7, 0x9E, 0xF8, 0xB5, 0xE7, 0x00, 0x21, +0x28, 0x46, 0xFF, 0xF7, 0xBB, 0xF9, 0x95, 0xF8, 0xA3, 0x30, 0x01, 0x33, 0x00, 0x22, 0x03, 0xF0, 0x07, 0x03, 0x85, 0xF8, +0xA3, 0x30, 0x85, 0xF8, 0x9B, 0x20, 0x85, 0xF8, 0xA4, 0x20, 0xD9, 0xF8, 0x10, 0x20, 0x2A, 0x60, 0x9B, 0x00, 0x84, 0xF8, +0x36, 0x30, 0x00, 0x28, 0xB8, 0xD0, 0x0D, 0xF1, 0x07, 0x01, 0x28, 0x46, 0xFE, 0xF7, 0xCE, 0xFC, 0x9D, 0xF8, 0x07, 0x30, +0x53, 0xB9, 0x62, 0x6A, 0x22, 0xF4, 0x00, 0x12, 0x62, 0x62, 0x95, 0xF8, 0xA2, 0x20, 0x22, 0xF0, 0x02, 0x02, 0x98, 0x46, +0x85, 0xF8, 0xA2, 0x20, 0x4F, 0xF4, 0x1E, 0x73, 0x03, 0xFB, 0x06, 0x73, 0x93, 0xF8, 0x56, 0x21, 0x42, 0xF0, 0x11, 0x02, +0x83, 0xF8, 0x56, 0x21, 0x9A, 0xE7, 0x00, 0x23, 0x80, 0xF8, 0x36, 0x30, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x83, 0x63, 0x6A, +0x43, 0xF4, 0x20, 0x13, 0x63, 0x62, 0xA0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x68, 0x65, 0x17, 0x00, 0xA0, 0x86, 0x01, 0x00, +0x70, 0x79, 0x15, 0x00, 0x68, 0x8E, 0x15, 0x00, 0x00, 0x10, 0x50, 0x40, 0x30, 0xB4, 0xCA, 0x0A, 0x12, 0xF0, 0x06, 0x0F, +0x9D, 0xF8, 0x08, 0x50, 0x9D, 0xF8, 0x14, 0x40, 0x20, 0xD0, 0x02, 0xF0, 0x07, 0x02, 0x01, 0xF0, 0x7F, 0x01, 0x04, 0x2A, +0x0C, 0xBF, 0x09, 0x09, 0xC1, 0xF3, 0xC1, 0x01, 0x4B, 0xB9, 0xC3, 0x6B, 0x23, 0xF0, 0x04, 0x03, 0xC3, 0x63, 0x64, 0xB1, +0x43, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xA9, 0x42, 0xF3, 0xD1, 0xC3, 0x6B, 0x43, 0xF0, 0x04, 0x03, +0xC3, 0x63, 0x00, 0x2C, 0xF2, 0xD1, 0x23, 0xF0, 0x10, 0x03, 0x30, 0xBC, 0xC3, 0x63, 0x70, 0x47, 0xC3, 0x6B, 0x23, 0xF0, +0x10, 0x03, 0xF8, 0xE7, 0x0B, 0x7B, 0x05, 0x2B, 0x0E, 0xD1, 0x2D, 0xE9, 0xF0, 0x41, 0x4B, 0x7B, 0x84, 0xB0, 0x0C, 0x46, +0x01, 0xF1, 0x0C, 0x07, 0x13, 0xB9, 0x0D, 0x88, 0x09, 0x2D, 0x05, 0xDC, 0x00, 0x20, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, +0x00, 0x20, 0x70, 0x47, 0x0B, 0x20, 0x97, 0xF8, 0x02, 0x80, 0x7E, 0x7A, 0xEE, 0xF7, 0xC8, 0xF9, 0x08, 0xBB, 0xFB, 0x78, +0x3B, 0xBB, 0x69, 0x1F, 0x04, 0xF1, 0x11, 0x00, 0x1D, 0x46, 0x01, 0x22, 0x07, 0x78, 0x43, 0x78, 0x26, 0x2F, 0x03, 0xF1, +0x02, 0x03, 0x14, 0xD1, 0x8B, 0x42, 0xA1, 0xEB, 0x03, 0x01, 0x10, 0xDC, 0x05, 0xB9, 0x03, 0x90, 0x02, 0x29, 0x18, 0x44, +0x4F, 0xF0, 0x01, 0x05, 0xEE, 0xDC, 0x00, 0x92, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x03, 0xAB, 0x00, 0xF0, 0x1A, 0xFD, +0x01, 0xF0, 0x52, 0xF8, 0xD0, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x04, 0x23, 0x00, 0xF0, 0xF4, 0xFC, +0xC8, 0xE7, 0x00, 0x96, 0xE1, 0x79, 0x20, 0x7A, 0x42, 0x46, 0x02, 0x23, 0x00, 0xF0, 0xEC, 0xFC, 0xC0, 0xE7, 0x00, 0xBF, +0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x90, 0xF9, 0x01, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, +0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0xEA, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x04, 0x49, 0x05, 0x48, +0x9D, 0x22, 0xEF, 0xF7, 0xD5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0x08, 0xB5, 0x0B, 0x20, 0xEE, 0xF7, 0x70, 0xF9, 0x04, 0x28, 0x07, 0xD0, 0x09, 0x4B, 0x1B, 0x68, +0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x05, 0xDB, 0x00, 0x20, 0x08, 0xBD, 0x01, 0xF0, 0x3E, 0xF8, 0x00, 0x20, 0x08, 0xBD, +0x04, 0x49, 0x05, 0x48, 0x81, 0x22, 0xEF, 0xF7, 0xB5, 0xFF, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x3A, 0xB3, 0x93, 0x68, 0x10, 0xB4, 0x93, 0xB9, 0x54, 0x69, 0x64, 0xB1, +0xFF, 0x28, 0x22, 0xD1, 0x00, 0x2C, 0x1A, 0xDD, 0x18, 0x32, 0x10, 0x19, 0x01, 0xE0, 0x82, 0x42, 0x15, 0xD0, 0x12, 0xF8, +0x01, 0x3B, 0x99, 0x42, 0xF9, 0xD1, 0x01, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0xFF, 0x28, 0x13, 0xD0, 0x00, 0x2B, +0x09, 0xDD, 0x0C, 0x32, 0x13, 0x44, 0x01, 0xE0, 0x9A, 0x42, 0x04, 0xD0, 0x12, 0xF8, 0x01, 0x1B, 0x81, 0x42, 0xF9, 0xD1, +0xED, 0xE7, 0x00, 0x20, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x18, 0x46, 0xE6, 0xE7, 0x54, 0x69, +0xD8, 0xE7, 0x00, 0xBF, 0x38, 0xB5, 0x0A, 0x4D, 0x41, 0xF2, 0x98, 0x74, 0x2B, 0x59, 0x63, 0xB1, 0x0B, 0x20, 0xEE, 0xF7, +0x1B, 0xF9, 0x03, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x38, 0xBD, 0x2B, 0x59, 0x18, 0x68, 0xB0, 0xFA, 0x80, 0xF0, 0x40, 0x09, +0x38, 0xBD, 0x01, 0x20, 0x38, 0xBD, 0x00, 0xBF, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x83, 0x46, 0x80, 0x6C, +0x89, 0xB0, 0x14, 0x46, 0x99, 0x46, 0x00, 0xF1, 0x68, 0x05, 0x00, 0x29, 0x3B, 0xD1, 0xB0, 0xF8, 0x68, 0x10, 0xBE, 0x4A, +0xB2, 0xF8, 0xFC, 0x31, 0x01, 0x33, 0x9B, 0xB2, 0x1E, 0x01, 0xA2, 0xF8, 0xFC, 0x31, 0xA0, 0xF8, 0x7E, 0x60, 0x05, 0x22, +0x58, 0x46, 0xFC, 0xF7, 0x53, 0xFA, 0x01, 0x28, 0x00, 0xF0, 0xC8, 0x80, 0x1B, 0x23, 0x03, 0x93, 0x18, 0x23, 0xE9, 0x18, +0x05, 0x22, 0xEA, 0x54, 0x01, 0x22, 0x4A, 0x70, 0x99, 0xF8, 0x00, 0x20, 0x8A, 0x70, 0x01, 0xF1, 0x03, 0x0A, 0x00, 0x2C, +0x7B, 0xD0, 0x03, 0x22, 0x27, 0x20, 0xC8, 0x70, 0x0A, 0x71, 0x99, 0xF8, 0x01, 0x20, 0x4A, 0x71, 0x8C, 0x71, 0x99, 0xF8, +0x02, 0x20, 0xCA, 0x71, 0x08, 0x33, 0xDB, 0xF8, 0x4C, 0x00, 0x9B, 0xF8, 0x35, 0x20, 0x41, 0x6A, 0x13, 0x44, 0x01, 0x39, +0x19, 0x44, 0x04, 0x33, 0xC0, 0xE9, 0x0A, 0x13, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xA2, 0x4B, 0xA2, 0x4E, 0x00, 0x22, +0x41, 0xF2, 0xA8, 0x7C, 0x6F, 0xF0, 0x2F, 0x01, 0x80, 0xF8, 0x69, 0x20, 0x80, 0xF8, 0x6A, 0x20, 0x80, 0xF8, 0x6B, 0x20, +0x80, 0xF8, 0x68, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x9B, 0x4A, 0x4F, 0xF4, 0x1E, 0x77, 0x07, 0xFB, 0x01, 0xF1, 0x41, 0xF2, +0xA9, 0x78, 0x89, 0x5B, 0xA0, 0xF8, 0x6C, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x4F, 0xF4, 0xA4, 0x6E, +0x49, 0x88, 0xA0, 0xF8, 0x6E, 0x10, 0x13, 0xF8, 0x0C, 0x10, 0x07, 0xFB, 0x01, 0x61, 0x89, 0x88, 0xA0, 0xF8, 0x70, 0x10, +0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x89, 0x5A, 0xA0, 0xF8, 0x72, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, +0x01, 0x21, 0x49, 0x88, 0xA0, 0xF8, 0x74, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0x21, 0x89, 0x88, 0xA0, 0xF8, +0x76, 0x10, 0x13, 0xF8, 0x08, 0x10, 0x0E, 0xFB, 0x01, 0xF1, 0x02, 0xEB, 0x01, 0x0A, 0x9A, 0xF8, 0x06, 0xA0, 0xBA, 0xF1, +0x02, 0x0F, 0x5F, 0xD0, 0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0xF2, 0xD0, 0x21, 0x92, 0x5B, 0xA0, 0xF8, 0x78, 0x20, +0x13, 0xF8, 0x0C, 0x20, 0x07, 0xFB, 0x02, 0x62, 0x52, 0x88, 0xA0, 0xF8, 0x7A, 0x20, 0x13, 0xF8, 0x0C, 0x30, 0x07, 0xFB, +0x03, 0x66, 0xB3, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x63, 0xE7, 0x03, 0x9B, 0x01, 0x94, 0xC3, 0xF5, 0xC0, 0x73, 0x9B, 0xB2, +0x02, 0x93, 0xCD, 0xF8, 0x14, 0xB0, 0x99, 0xF8, 0x02, 0x30, 0x02, 0x9A, 0x05, 0x2B, 0xA2, 0xF1, 0x05, 0x04, 0xA4, 0xB2, +0x00, 0xF0, 0xE2, 0x80, 0x27, 0x23, 0x8A, 0xF8, 0x00, 0x30, 0x99, 0xF8, 0x01, 0x30, 0x8A, 0xF8, 0x02, 0x30, 0x00, 0x23, +0x8A, 0xF8, 0x03, 0x30, 0x99, 0xF8, 0x02, 0x30, 0x8A, 0xF8, 0x04, 0x30, 0x05, 0x2B, 0x3A, 0xD0, 0x03, 0x23, 0x8A, 0xF8, +0x01, 0x30, 0x02, 0x94, 0x0A, 0xF1, 0x05, 0x0A, 0x05, 0x25, 0xFF, 0xF7, 0x15, 0xFF, 0x01, 0x9B, 0x2B, 0x44, 0x01, 0x93, +0x08, 0xB9, 0x04, 0x2C, 0xD7, 0xD8, 0x5C, 0x4B, 0xDD, 0xF8, 0x14, 0xB0, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xC0, 0xF2, 0x9D, 0x80, 0x01, 0x9B, 0x03, 0x9A, 0x13, 0x44, 0x52, 0xE7, 0x18, 0x22, 0x29, 0x46, 0x58, 0x46, 0xFA, 0xF7, +0xE7, 0xFF, 0x9B, 0xF8, 0x33, 0x20, 0x02, 0xF1, 0x18, 0x03, 0x1B, 0x32, 0x03, 0x92, 0x2E, 0xE7, 0x89, 0x5A, 0xA0, 0xF8, +0x78, 0x10, 0x13, 0xF8, 0x08, 0x60, 0x0E, 0xFB, 0x06, 0x26, 0xD0, 0x21, 0x76, 0x88, 0xA0, 0xF8, 0x7A, 0x60, 0x13, 0xF8, +0x08, 0x30, 0x0E, 0xFB, 0x03, 0x22, 0x93, 0x88, 0xA0, 0xF8, 0x7C, 0x30, 0x07, 0xE7, 0xD9, 0xF8, 0x5C, 0x20, 0x46, 0x49, +0x01, 0x32, 0x0D, 0x68, 0xC9, 0xF8, 0x5C, 0x20, 0x0A, 0xF1, 0x05, 0x02, 0x04, 0x92, 0x00, 0x2D, 0x00, 0xF0, 0x45, 0x81, +0xEB, 0x7C, 0x8A, 0xF8, 0x05, 0x30, 0x2B, 0x7C, 0x8A, 0xF8, 0x06, 0x30, 0xD9, 0xE9, 0x0A, 0x12, 0xB9, 0xF8, 0x30, 0x30, +0xAA, 0xF8, 0x0F, 0x30, 0xCA, 0xF8, 0x07, 0x10, 0xCA, 0xF8, 0x0B, 0x20, 0xAB, 0x7C, 0x8A, 0xF8, 0x11, 0x30, 0x95, 0xF9, +0x14, 0x00, 0xEE, 0xF7, 0x21, 0xFF, 0xFF, 0x23, 0x8A, 0xF8, 0x12, 0x00, 0x8A, 0xF8, 0x13, 0x30, 0x05, 0xF1, 0x0C, 0x00, +0xAB, 0x1D, 0x13, 0xF8, 0x01, 0x1B, 0x03, 0xF1, 0x0D, 0x02, 0x52, 0x1B, 0x83, 0x42, 0x02, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, +0x6B, 0x7C, 0x8A, 0xF8, 0x1A, 0x30, 0x02, 0x9A, 0xEB, 0x68, 0xCA, 0xF8, 0x1B, 0x30, 0x40, 0xF2, 0x01, 0x14, 0x94, 0x42, +0x99, 0xF8, 0x20, 0x30, 0x28, 0xBF, 0x14, 0x46, 0x0A, 0xF1, 0x1F, 0x02, 0xA4, 0xB2, 0x04, 0x92, 0x00, 0x2B, 0x40, 0xF0, +0x05, 0x81, 0x1F, 0x3C, 0xA4, 0xB2, 0x99, 0xF8, 0x04, 0x30, 0x00, 0x2B, 0x6D, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, 0x03, 0x23, +0x1D, 0x48, 0xAB, 0x80, 0x29, 0x46, 0xEE, 0xF7, 0xEB, 0xF9, 0x99, 0xF8, 0x20, 0x30, 0x00, 0x2B, 0x40, 0xF0, 0x12, 0x81, +0x04, 0x9B, 0x02, 0x9A, 0xA3, 0xEB, 0x0A, 0x05, 0xAB, 0x1E, 0x8A, 0xF8, 0x01, 0x30, 0x14, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, +0x00, 0x30, 0x54, 0x1B, 0x00, 0x2B, 0xA4, 0xB2, 0x80, 0xF2, 0xF9, 0x80, 0xAA, 0x42, 0x80, 0xF0, 0xF6, 0x80, 0x10, 0x49, +0x10, 0x48, 0xDD, 0xF8, 0x10, 0xA0, 0x40, 0xF2, 0x07, 0x52, 0xEF, 0xF7, 0xCF, 0xFD, 0x02, 0x94, 0x51, 0xE7, 0x01, 0x9B, +0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0x09, 0x49, 0x0A, 0x48, 0x40, 0xF2, 0x12, 0x52, 0xEF, 0xF7, 0xDB, 0xFD, 0x57, 0xE7, +0x20, 0x62, 0x17, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x8E, 0x65, 0x17, 0x00, 0x74, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0xF4, 0xD0, 0x15, 0x00, 0x0C, 0xD1, 0x15, 0x00, 0x94, 0x4B, 0x1A, 0x68, +0x00, 0x2A, 0x3F, 0xF4, 0x19, 0xAF, 0x19, 0x2C, 0x7F, 0xF6, 0x35, 0xAF, 0x02, 0x98, 0x99, 0xF8, 0x20, 0x10, 0xA0, 0xF1, +0x1F, 0x03, 0x9B, 0xB2, 0x29, 0xB1, 0x02, 0x2B, 0x7F, 0xF6, 0x2B, 0xAF, 0xA0, 0xF1, 0x22, 0x03, 0x9B, 0xB2, 0x99, 0xF8, +0x04, 0x10, 0x00, 0x29, 0x3F, 0xF4, 0x04, 0xAF, 0x03, 0x2B, 0x7F, 0xF6, 0x20, 0xAF, 0x10, 0x8B, 0x04, 0x3B, 0x9D, 0xB2, +0x00, 0x28, 0x40, 0xF0, 0xCF, 0x80, 0x0D, 0x2D, 0x3F, 0xF6, 0xF8, 0xAE, 0x15, 0xE7, 0x04, 0x9A, 0x01, 0x23, 0x13, 0x70, +0x2B, 0x8B, 0xA2, 0x1F, 0x92, 0xB2, 0x0A, 0xF1, 0x21, 0x01, 0x0B, 0x2B, 0x06, 0x92, 0x8C, 0x46, 0x1B, 0xD8, 0x7C, 0x4B, +0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xC0, 0xF2, 0xAE, 0x80, 0x05, 0xF1, 0x1C, 0x02, 0x05, 0xF1, 0x28, 0x00, +0x13, 0x46, 0x05, 0x33, 0x12, 0xF8, 0x01, 0x1B, 0x5B, 0x1B, 0x82, 0x42, 0x03, 0xF8, 0x0A, 0x10, 0xF6, 0xD1, 0x0C, 0x23, +0x12, 0x3C, 0xA2, 0xB2, 0x2B, 0x83, 0x0A, 0xF1, 0x2D, 0x03, 0x06, 0x92, 0x9C, 0x46, 0x99, 0xF8, 0x04, 0x30, 0x01, 0x2B, +0x3A, 0xD0, 0x2B, 0x8B, 0x6E, 0x8B, 0xF6, 0x1A, 0x05, 0xF1, 0x1C, 0x07, 0xB6, 0xB2, 0x1F, 0x44, 0x00, 0x2E, 0x3B, 0xD0, +0xCD, 0xF8, 0x1C, 0xA0, 0xE3, 0x46, 0xAA, 0x46, 0x09, 0xE0, 0xBA, 0xF8, 0x18, 0x10, 0x36, 0x1B, 0xB6, 0xB2, 0x0C, 0x44, +0x2F, 0x44, 0xAA, 0xF8, 0x18, 0x40, 0x00, 0x2E, 0x5D, 0xD0, 0x97, 0xF8, 0x00, 0x80, 0xB9, 0x78, 0x7C, 0x78, 0x40, 0x46, +0x4A, 0x46, 0xFF, 0xF7, 0xA9, 0xFD, 0xA5, 0x1C, 0x02, 0x34, 0xED, 0xB2, 0xE4, 0xB2, 0x00, 0x28, 0xE7, 0xD0, 0xD9, 0x2D, +0xE5, 0xD8, 0x06, 0x9B, 0x9C, 0x42, 0x4A, 0xD8, 0x4D, 0xB1, 0x59, 0x46, 0x78, 0x1A, 0xAB, 0x44, 0x01, 0xE0, 0x10, 0xF8, +0x01, 0x80, 0x01, 0xF8, 0x01, 0x8B, 0x8B, 0x45, 0xF9, 0xD1, 0x06, 0x9B, 0x1B, 0x1B, 0x9B, 0xB2, 0x06, 0x93, 0xD2, 0xE7, +0xD9, 0xF8, 0x08, 0x30, 0x00, 0x2B, 0xC0, 0xD1, 0xD9, 0xF8, 0x14, 0x30, 0x00, 0x2B, 0xBC, 0xD1, 0x6B, 0x8B, 0x2B, 0x83, +0x04, 0x9B, 0xC3, 0xF1, 0xFE, 0x0B, 0xE3, 0x44, 0x02, 0x23, 0x8A, 0xF8, 0x20, 0xB0, 0x8C, 0xF8, 0x00, 0x30, 0x8C, 0xF8, +0x01, 0x30, 0xEA, 0x7D, 0x28, 0x8B, 0x69, 0x8B, 0x99, 0xF8, 0x01, 0x30, 0x54, 0x1C, 0x88, 0x42, 0x66, 0x46, 0xEC, 0x75, +0x43, 0xEA, 0x02, 0x23, 0x23, 0xD2, 0x6F, 0xEA, 0x43, 0x43, 0x6F, 0xEA, 0x53, 0x43, 0xAC, 0xF8, 0x02, 0x30, 0x33, 0x1D, +0x04, 0x93, 0x08, 0xE7, 0x22, 0x3C, 0xA4, 0xB2, 0xF9, 0xE6, 0x03, 0x22, 0x8A, 0xF8, 0x01, 0x20, 0x36, 0x4A, 0x12, 0x68, +0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x09, 0xDB, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x1D, 0x46, 0x6B, 0xE6, 0x55, 0x46, +0xDC, 0x46, 0xDD, 0xF8, 0x1C, 0xA0, 0xC9, 0xE7, 0x1D, 0x46, 0xDD, 0xF8, 0x10, 0xA0, 0x02, 0x94, 0x61, 0xE6, 0xAC, 0xF8, +0x02, 0x30, 0x33, 0x1D, 0x04, 0x93, 0xE2, 0xE6, 0x04, 0x9D, 0xA4, 0x23, 0x01, 0x24, 0x2B, 0x70, 0x6C, 0x70, 0xFF, 0xF7, +0x6D, 0xFD, 0x20, 0xB1, 0xAC, 0x70, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0xE0, 0xE6, 0x04, 0x9B, 0x98, 0x70, 0xF8, 0xE7, +0x0B, 0x2A, 0x3F, 0xF6, 0x4F, 0xAF, 0x21, 0x49, 0x21, 0x48, 0x40, 0xF2, 0x7D, 0x42, 0xEF, 0xF7, 0xBF, 0xFC, 0x47, 0xE7, +0xB2, 0xF8, 0x1A, 0x80, 0x01, 0x29, 0x02, 0xF1, 0x1C, 0x02, 0xA8, 0xEB, 0x00, 0x08, 0x02, 0xEB, 0x00, 0x07, 0x08, 0xD0, +0xB8, 0xF1, 0x00, 0x0F, 0x1B, 0xD0, 0x7B, 0x78, 0x03, 0x33, 0xAB, 0x42, 0xFF, 0xF6, 0x1A, 0xAE, 0x37, 0xE6, 0x7E, 0x78, +0x10, 0x5C, 0x97, 0xF8, 0x02, 0xB0, 0x02, 0x36, 0xF6, 0xB2, 0x03, 0xE0, 0x7E, 0x78, 0x38, 0x78, 0x02, 0x36, 0xF6, 0xB2, +0x4A, 0x46, 0x59, 0x46, 0xFF, 0xF7, 0x08, 0xFD, 0x08, 0xB1, 0xD9, 0x2E, 0xE4, 0xD9, 0xB8, 0xEB, 0x06, 0x08, 0x37, 0x44, +0xF0, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xBF, 0xF6, 0xFC, 0xAD, 0x05, 0x49, 0x07, 0x48, +0x40, 0xF2, 0x13, 0x42, 0xEF, 0xF7, 0xA0, 0xFC, 0xF4, 0xE5, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x38, 0x36, 0x17, 0x00, +0x70, 0x79, 0x15, 0x00, 0xD0, 0xD0, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0xF8, 0xB5, 0x2D, 0x4E, 0x41, 0xF2, 0xA9, 0x73, +0xF2, 0x5C, 0x03, 0x2A, 0x42, 0xD8, 0x41, 0xF2, 0xA8, 0x73, 0xF3, 0x5C, 0x09, 0x2B, 0x3D, 0xD8, 0x0D, 0x46, 0x28, 0x49, +0x4F, 0xF4, 0xA4, 0x63, 0x03, 0xFB, 0x02, 0x13, 0x07, 0x46, 0x1B, 0x6C, 0x00, 0x2B, 0x3E, 0xD0, 0x24, 0x48, 0x1B, 0x79, +0x00, 0x68, 0xB0, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x2D, 0xDB, 0x4F, 0xF4, 0xA4, 0x60, 0x00, 0xFB, 0x02, 0x12, 0x92, 0xF8, +0xC0, 0x24, 0x13, 0x43, 0x14, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0xC0, 0x71, 0xDA, 0xF7, 0x3D, 0xFE, 0x04, 0x46, +0xE0, 0xB1, 0x41, 0xF2, 0xA9, 0x72, 0x41, 0xF2, 0xA8, 0x73, 0xB2, 0x5C, 0x02, 0x77, 0xF3, 0x5C, 0x43, 0x77, 0x00, 0x23, +0x80, 0xF8, 0x33, 0x30, 0x80, 0xF8, 0x35, 0x30, 0x15, 0xB9, 0x13, 0x4B, 0xC0, 0xE9, 0x15, 0x30, 0x20, 0x46, 0x3B, 0x46, +0x2A, 0x46, 0x01, 0x21, 0xFF, 0xF7, 0xEC, 0xFC, 0x20, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0xF8, 0x40, 0xDA, 0xF7, 0x2E, 0xBE, +0xF8, 0xBD, 0x02, 0x2B, 0xCF, 0xD1, 0x0B, 0x49, 0x0B, 0x48, 0x4F, 0xF4, 0x09, 0x72, 0xEF, 0xF7, 0x29, 0xFC, 0x01, 0x20, +0xD1, 0xE7, 0x05, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF7, 0xDA, 0xF0, 0xE7, 0x78, 0xEF, 0x17, 0x00, +0x18, 0x88, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0xA1, 0x5E, 0x15, 0x00, 0x70, 0x79, 0x15, 0x00, 0xFC, 0x90, 0x15, 0x00, +0x00, 0x2A, 0x35, 0xD0, 0x70, 0xB5, 0x04, 0x46, 0x92, 0xF8, 0x32, 0x00, 0x8A, 0xB0, 0x13, 0x46, 0x58, 0xB9, 0x95, 0x8E, +0x22, 0x88, 0x95, 0x42, 0x28, 0xD1, 0xDD, 0x8E, 0x62, 0x88, 0x95, 0x42, 0x24, 0xD1, 0xA2, 0x88, 0x1C, 0x8F, 0x94, 0x42, +0x20, 0xD1, 0x93, 0xF8, 0x3A, 0x20, 0xE2, 0xB1, 0xD9, 0xB1, 0x4D, 0x78, 0x8D, 0xF8, 0x04, 0x50, 0x6D, 0xB1, 0x01, 0xA8, +0x05, 0x44, 0xC0, 0xF1, 0x02, 0x06, 0x44, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0xA8, 0x42, 0xF9, 0xD1, 0x9D, 0xF8, +0x04, 0x10, 0x91, 0x42, 0x01, 0xD0, 0x00, 0x20, 0x08, 0xE0, 0x03, 0xF1, 0x3B, 0x00, 0x0D, 0xF1, 0x05, 0x01, 0x01, 0xF0, +0x57, 0xFE, 0x00, 0x28, 0xF5, 0xD1, 0x01, 0x20, 0x0A, 0xB0, 0x70, 0xBD, 0x01, 0x20, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, +0x04, 0x46, 0xB1, 0xB1, 0x64, 0x48, 0x65, 0x4D, 0xA0, 0xF1, 0x82, 0x07, 0xED, 0xF7, 0x78, 0xFF, 0x00, 0x26, 0x25, 0xF8, +0x02, 0x6C, 0x28, 0x46, 0x06, 0x22, 0x00, 0x21, 0x05, 0xF5, 0xF6, 0x75, 0xCA, 0xF7, 0xDE, 0xFE, 0xBD, 0x42, 0xF4, 0xD1, +0xEC, 0xF7, 0x56, 0xFC, 0xC4, 0xE9, 0x0A, 0x01, 0x26, 0x66, 0x5B, 0x4E, 0xDF, 0xF8, 0x6C, 0x81, 0x06, 0xF1, 0x88, 0x07, +0x0B, 0x20, 0xED, 0xF7, 0x77, 0xFD, 0x01, 0x28, 0x39, 0xD1, 0x57, 0x4D, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x02, 0x0A, +0x03, 0xE0, 0x05, 0xF5, 0xF6, 0x75, 0xB5, 0x42, 0x1A, 0xD0, 0xAB, 0x88, 0x01, 0x2B, 0xF8, 0xD1, 0x6B, 0x7D, 0x05, 0xF1, +0x1C, 0x01, 0x19, 0x44, 0x22, 0x46, 0xA8, 0x1D, 0xFF, 0xF7, 0x8C, 0xFF, 0x00, 0x28, 0xEE, 0xD0, 0x29, 0x46, 0xA5, 0xF8, +0x18, 0x90, 0x85, 0xF8, 0x17, 0x90, 0xA5, 0xF8, 0x04, 0xA0, 0x38, 0x46, 0x05, 0xF5, 0xF6, 0x75, 0xED, 0xF7, 0x3E, 0xFF, +0xB5, 0x42, 0xE4, 0xD1, 0x23, 0x6E, 0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0x5D, 0xDA, 0x03, 0x21, +0x0B, 0x20, 0xED, 0xF7, 0x9D, 0xFC, 0xFF, 0xF7, 0x1F, 0xFC, 0x00, 0x28, 0xC6, 0xD1, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, +0xF0, 0x47, 0xFF, 0xF7, 0xFF, 0xBE, 0x01, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x8F, 0xFC, 0x23, 0x6E, 0x06, 0xE0, 0x23, 0x6E, +0x94, 0xF8, 0x65, 0x20, 0x01, 0x33, 0x93, 0x42, 0x23, 0x66, 0xB3, 0xDA, 0x23, 0x44, 0x94, 0xF8, 0x64, 0x00, 0x93, 0xF8, +0x66, 0x10, 0xF1, 0xF7, 0xBB, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xEE, 0xD0, 0xC3, 0x78, 0x9B, 0x07, 0xEB, 0xD4, 0x4F, 0xF4, +0xBA, 0x73, 0x0B, 0x22, 0x04, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xED, 0xF7, 0x77, 0xFA, 0x06, 0x46, 0x28, 0x68, 0x30, 0x60, +0xAB, 0x88, 0xB3, 0x80, 0xE3, 0x78, 0x1B, 0xB9, 0xF3, 0x78, 0x43, 0xF0, 0x01, 0x03, 0xF3, 0x70, 0x01, 0x25, 0x86, 0xF8, +0x6F, 0x51, 0x94, 0xF8, 0x3A, 0x20, 0x86, 0xF8, 0xFC, 0x20, 0x04, 0xF1, 0x3B, 0x01, 0x06, 0xF1, 0xFD, 0x00, 0x01, 0xF0, +0xE7, 0xFD, 0x86, 0xF8, 0x70, 0x51, 0xA3, 0x8E, 0xA6, 0xF8, 0x60, 0x31, 0xE3, 0x8E, 0xA6, 0xF8, 0x62, 0x31, 0x23, 0x8F, +0xA6, 0xF8, 0x64, 0x31, 0x41, 0xF2, 0xA9, 0x73, 0x30, 0x46, 0x18, 0xF8, 0x03, 0x30, 0x86, 0xF8, 0x6E, 0x31, 0xBD, 0xE8, +0xF0, 0x47, 0xED, 0xF7, 0x79, 0xBA, 0x13, 0x4B, 0x1B, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x09, 0xDB, 0x02, 0x21, +0x0B, 0x20, 0xED, 0xF7, 0x39, 0xFC, 0x20, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x47, 0xFF, 0xF7, 0x9F, 0xBE, 0xFF, 0xF7, +0xB5, 0xFB, 0x00, 0x28, 0xF1, 0xD0, 0xE3, 0x6D, 0x00, 0x2B, 0xEE, 0xD0, 0x08, 0x49, 0x09, 0x48, 0x40, 0xF2, 0x22, 0x62, +0xEF, 0xF7, 0x0E, 0xFB, 0xE7, 0xE7, 0x00, 0xBF, 0x10, 0x07, 0x18, 0x00, 0x7E, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, +0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x1C, 0xD1, 0x15, 0x00, 0x10, 0xB5, 0x08, 0x4C, +0x00, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x10, 0xFC, 0x20, 0x46, 0x41, 0xF2, 0xB0, 0x72, 0x00, 0x21, 0x04, 0xF5, 0xBD, 0x54, +0xCA, 0xF7, 0x08, 0xFE, 0x4F, 0xF0, 0xFF, 0x33, 0x23, 0x60, 0x10, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0xF0, 0xB5, 0xA3, 0xB0, +0x0B, 0x4C, 0x9D, 0xF8, 0xA0, 0x50, 0x8D, 0xF8, 0x02, 0x50, 0x41, 0xF2, 0xA8, 0x75, 0x84, 0x46, 0x41, 0xF2, 0xA9, 0x77, +0x08, 0x46, 0x66, 0x5B, 0x60, 0x55, 0x19, 0x46, 0x68, 0x46, 0x04, 0xF8, 0x07, 0xC0, 0x8D, 0xF8, 0x00, 0x20, 0xFF, 0xF7, +0x57, 0xFE, 0x66, 0x53, 0x23, 0xB0, 0xF0, 0xBD, 0x78, 0xEF, 0x17, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAB, 0xB0, 0x41, 0xF2, +0xA8, 0x76, 0x00, 0x92, 0xC4, 0x4A, 0x41, 0xF2, 0xA9, 0x75, 0x91, 0x55, 0xCD, 0xE9, 0x01, 0x01, 0x02, 0xF5, 0xBD, 0x51, +0x50, 0x55, 0x4F, 0xF0, 0xFF, 0x30, 0x08, 0x60, 0x34, 0x99, 0x16, 0x46, 0x41, 0xF2, 0xA4, 0x74, 0x00, 0x22, 0x91, 0x42, +0x32, 0x51, 0x34, 0xDD, 0xDF, 0xF8, 0xF0, 0x82, 0x1F, 0x46, 0x91, 0x46, 0xBA, 0x46, 0x57, 0xF8, 0x04, 0x4B, 0x65, 0x78, +0xAB, 0x1C, 0x04, 0x2B, 0x37, 0xD9, 0x88, 0x22, 0x00, 0x21, 0x40, 0x46, 0xCA, 0xF7, 0xBC, 0xFD, 0xA3, 0x78, 0x88, 0xF8, +0x01, 0x30, 0xE3, 0x78, 0x22, 0x79, 0x88, 0xF8, 0x02, 0x20, 0xD9, 0x07, 0x03, 0xD4, 0x9B, 0x07, 0x1C, 0xD4, 0x05, 0x2A, +0x73, 0xD0, 0xDA, 0xF8, 0x00, 0x40, 0x02, 0x21, 0x00, 0x9A, 0x23, 0x79, 0x8D, 0xF8, 0x20, 0x20, 0xA8, 0x4A, 0x02, 0x98, +0x8D, 0xF8, 0x22, 0x30, 0x41, 0xF2, 0xA8, 0x75, 0x41, 0xF2, 0xA9, 0x73, 0x16, 0x46, 0x54, 0x5B, 0x01, 0x9F, 0x50, 0x55, +0x08, 0xA8, 0xD7, 0x54, 0xFF, 0xF7, 0x04, 0xFE, 0x74, 0x53, 0x2B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x98, 0xF8, 0x00, 0x30, +0x00, 0x9A, 0x93, 0x42, 0x4C, 0xD0, 0x34, 0x9B, 0x09, 0xF1, 0x01, 0x09, 0x4B, 0x45, 0xC1, 0xD1, 0xF1, 0xE7, 0x04, 0x21, +0xDA, 0xE7, 0xA3, 0x2C, 0x00, 0xF0, 0x25, 0x81, 0xA4, 0x2C, 0x40, 0xF0, 0x18, 0x81, 0x98, 0x78, 0x88, 0xF8, 0x20, 0x00, +0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x00, 0xF2, 0x82, 0x80, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3E, 0x46, +0x03, 0x9F, 0x2C, 0xD8, 0x04, 0x9C, 0x72, 0x2C, 0x23, 0x46, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, +0x00, 0x2E, 0x00, 0xF0, 0x2B, 0x81, 0xB6, 0xF8, 0x03, 0x20, 0xB1, 0x78, 0xB0, 0x88, 0x88, 0xF8, 0x66, 0x40, 0x41, 0xF2, +0x88, 0x33, 0x9A, 0x42, 0x94, 0xBF, 0x00, 0x22, 0x01, 0x22, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x20, 0x88, 0xF8, 0x65, 0x30, +0x00, 0x29, 0x40, 0xF0, 0x03, 0x81, 0x05, 0x9A, 0x88, 0xF8, 0x64, 0x10, 0x94, 0x42, 0x06, 0xD0, 0x80, 0xF0, 0x59, 0x81, +0x04, 0x9B, 0x04, 0x33, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x00, 0x9B, 0x88, 0xF8, 0x00, 0x30, +0x76, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x08, 0xF1, 0x88, 0x08, 0x13, 0x60, 0xAB, 0xE7, 0xEB, 0x1E, 0x0C, 0x2B, 0x40, 0xF2, +0xDD, 0x80, 0xE3, 0x7A, 0x88, 0xF8, 0x03, 0x30, 0x02, 0x2B, 0x82, 0xD8, 0x62, 0x79, 0x63, 0x7A, 0x04, 0x92, 0xA2, 0x79, +0x05, 0x92, 0xA8, 0xF8, 0x30, 0x30, 0x08, 0xF1, 0x3A, 0x0E, 0x08, 0xF1, 0x34, 0x03, 0xA4, 0xEB, 0x08, 0x01, 0x5A, 0x18, +0x12, 0xF8, 0x28, 0x2C, 0x03, 0xF8, 0x01, 0x2B, 0x73, 0x45, 0xF8, 0xD1, 0xB8, 0xF8, 0x34, 0x20, 0x4F, 0xF6, 0xFF, 0x73, +0x9A, 0x42, 0xA5, 0xF1, 0x10, 0x02, 0x08, 0xBF, 0x01, 0x23, 0x4F, 0xF0, 0x02, 0x01, 0x92, 0xB2, 0x08, 0xBF, 0x88, 0xF8, +0x32, 0x30, 0x8A, 0x42, 0x04, 0xF1, 0x12, 0x03, 0x88, 0xF8, 0x04, 0x10, 0x40, 0xF2, 0x47, 0x81, 0x00, 0x21, 0x6F, 0xF0, +0x13, 0x00, 0x0C, 0x46, 0x6F, 0xF0, 0x08, 0x06, 0x6F, 0xF0, 0x37, 0x0C, 0x0D, 0x46, 0xA0, 0xEB, 0x08, 0x01, 0x03, 0x97, +0x06, 0x91, 0xA6, 0xEB, 0x08, 0x06, 0xAC, 0xEB, 0x08, 0x0C, 0x27, 0x46, 0x58, 0x78, 0x1C, 0x78, 0x81, 0x1C, 0x91, 0x42, +0x00, 0xF2, 0x96, 0x80, 0x0B, 0x2C, 0x3F, 0xF6, 0x66, 0xAF, 0x0B, 0x2C, 0x3F, 0xF6, 0x6C, 0xAF, 0x0F, 0xF2, 0x04, 0x0B, +0x5B, 0xF8, 0x24, 0xF0, 0xA9, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0x97, 0x58, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, +0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, 0xB1, 0x56, 0x15, 0x00, +0xB1, 0x56, 0x15, 0x00, 0x65, 0x58, 0x15, 0x00, 0x11, 0x58, 0x15, 0x00, 0x02, 0x29, 0x71, 0xD0, 0x9C, 0x78, 0xFF, 0x2C, +0x7F, 0xF4, 0x4A, 0xAF, 0x00, 0xF1, 0xFF, 0x3B, 0x5F, 0xFA, 0x8B, 0xFB, 0xBB, 0xF1, 0x08, 0x0F, 0x28, 0xBF, 0x4F, 0xF0, +0x08, 0x0B, 0x01, 0x28, 0xC8, 0xF8, 0x14, 0xB0, 0x3F, 0xF4, 0x3C, 0xAF, 0x08, 0xF1, 0x17, 0x00, 0xCD, 0xF8, 0x1C, 0xA0, +0xDD, 0xF8, 0x18, 0xA0, 0x83, 0x44, 0x1C, 0x18, 0x14, 0xF8, 0x0A, 0x40, 0x00, 0xF8, 0x01, 0x4F, 0x58, 0x45, 0xF8, 0xD1, +0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0xDD, 0xF8, 0x1C, 0xA0, 0x0B, 0x44, 0xAE, 0xD8, 0x2B, 0xE7, 0x8C, 0x1E, 0x08, 0x2C, +0xA8, 0xBF, 0x08, 0x24, 0x02, 0x29, 0xC8, 0xF8, 0x08, 0x40, 0x3F, 0xF4, 0x1D, 0xAF, 0x08, 0xF1, 0x0B, 0x00, 0x00, 0xEB, +0x04, 0x0B, 0x1C, 0x18, 0xA4, 0x5D, 0x00, 0xF8, 0x01, 0x4F, 0x83, 0x45, 0xF9, 0xD1, 0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, +0x0B, 0x44, 0x95, 0xD8, 0x12, 0xE7, 0x52, 0x1A, 0x92, 0xB2, 0x98, 0x78, 0x88, 0xF8, 0x04, 0x00, 0x02, 0x2A, 0x0B, 0x44, +0x8C, 0xD8, 0x09, 0xE7, 0x22, 0x29, 0x25, 0xD8, 0x88, 0xF8, 0x3A, 0x00, 0x00, 0x28, 0x3F, 0xF4, 0xFD, 0xAE, 0x00, 0xEB, +0x0E, 0x04, 0x70, 0x46, 0x00, 0xEB, 0x03, 0x0B, 0x1B, 0xF8, 0x0C, 0xB0, 0x00, 0xF8, 0x01, 0xBF, 0xA0, 0x42, 0xF7, 0xD1, +0x52, 0x1A, 0x92, 0xB2, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x74, 0xAF, 0xF0, 0xE6, 0x52, 0x1A, 0x92, 0xB2, 0x33, 0x2C, +0x08, 0xBF, 0x1D, 0x46, 0x02, 0x2A, 0x0B, 0x44, 0x3F, 0xF6, 0x6A, 0xAF, 0xE6, 0xE6, 0x1F, 0x46, 0xDE, 0xE6, 0x00, 0x23, +0x88, 0xF8, 0x65, 0x30, 0xDA, 0xF8, 0x00, 0x40, 0x04, 0x21, 0xA9, 0xE6, 0x78, 0xEF, 0x17, 0x00, 0x1C, 0x07, 0x18, 0x00, +0x88, 0x06, 0x18, 0x00, 0x01, 0x29, 0x08, 0xF1, 0x66, 0x03, 0x00, 0xF0, 0x47, 0x81, 0x04, 0x9A, 0x41, 0x2A, 0x35, 0xBF, +0x40, 0x20, 0x80, 0x20, 0x24, 0x22, 0x64, 0x22, 0x11, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xCA, 0xB2, 0x90, 0x42, 0xF9, 0xD2, +0x08, 0x23, 0xF4, 0xE6, 0x05, 0x9B, 0xFF, 0x2B, 0x4E, 0xD0, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xF0, 0x85, 0x80, 0x05, 0x9A, +0x88, 0xF8, 0x66, 0x20, 0x01, 0x23, 0x88, 0xF8, 0x65, 0x30, 0x04, 0x9B, 0xA3, 0xF1, 0x53, 0x02, 0x08, 0xF1, 0x66, 0x03, +0x2E, 0x2A, 0x30, 0xD8, 0xDF, 0xE8, 0x12, 0xF0, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, +0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, +0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, +0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, +0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x2F, 0x00, 0x2F, 0x00, 0x39, 0x00, 0x31, 0x00, 0x71, 0x01, +0x6E, 0x01, 0x01, 0x23, 0xAD, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x04, 0x9B, 0x04, 0x3B, 0x88, 0xF8, 0x67, 0x30, 0x02, 0x23, +0xA5, 0xE6, 0x05, 0x9B, 0x04, 0x93, 0x9D, 0xE6, 0x00, 0x2D, 0x8D, 0xD0, 0xAB, 0x78, 0x04, 0x9A, 0x93, 0x42, 0x89, 0xD1, +0x68, 0x78, 0x43, 0x1E, 0xDB, 0xB2, 0x1C, 0x2B, 0x28, 0xBF, 0x1C, 0x23, 0x59, 0x1E, 0x01, 0x28, 0x05, 0xF1, 0x03, 0x05, +0xC9, 0xB2, 0x3F, 0xF4, 0x7D, 0xAF, 0x32, 0x46, 0x08, 0xEB, 0x02, 0x04, 0xAE, 0x5C, 0x84, 0xF8, 0x66, 0x60, 0x91, 0x42, +0x02, 0xF1, 0x01, 0x02, 0xF6, 0xD1, 0x01, 0x28, 0x3F, 0xF4, 0x70, 0xAF, 0x88, 0xF8, 0x65, 0x30, 0x01, 0x2B, 0x7F, 0xF4, +0x80, 0xAE, 0x98, 0xF8, 0x66, 0x30, 0x05, 0x93, 0x91, 0xE7, 0x98, 0xF8, 0x03, 0x30, 0x01, 0x2B, 0x3F, 0xF6, 0x77, 0xAE, +0x04, 0x9B, 0x72, 0x2B, 0x94, 0xBF, 0x00, 0x23, 0x01, 0x23, 0x88, 0xF8, 0x64, 0x30, 0x05, 0x9B, 0xFF, 0x2B, 0x7F, 0xF4, +0x78, 0xAF, 0x55, 0xE7, 0x04, 0x9A, 0x08, 0xF1, 0x66, 0x03, 0x51, 0x3A, 0x1E, 0x46, 0x30, 0x2A, 0x3F, 0xF6, 0x4B, 0xAF, +0x01, 0xA1, 0x51, 0xF8, 0x22, 0xF0, 0x00, 0xBF, 0x9B, 0x5B, 0x15, 0x00, 0x27, 0x5C, 0x15, 0x00, 0x9B, 0x5B, 0x15, 0x00, +0x9B, 0x5B, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, +0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, +0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, +0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, +0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, +0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, 0xF3, 0x58, 0x15, 0x00, +0xF3, 0x58, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x91, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, +0x87, 0x5B, 0x15, 0x00, 0x87, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, 0x7D, 0x5B, 0x15, 0x00, +0x29, 0x5B, 0x15, 0x00, 0x03, 0x5C, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0x29, 0x5B, 0x15, 0x00, 0xE9, 0x5B, 0x15, 0x00, +0x0D, 0x5C, 0x15, 0x00, 0x00, 0x25, 0x04, 0x20, 0xA2, 0x24, 0x95, 0x22, 0x71, 0x1E, 0x0B, 0x46, 0x02, 0x33, 0x01, 0xF8, +0x01, 0x2F, 0x02, 0x44, 0x2B, 0x44, 0x94, 0x42, 0xA3, 0xEB, 0x06, 0x03, 0xF5, 0xDC, 0x40, 0x4A, 0xDB, 0xB2, 0x12, 0x68, +0x88, 0xF8, 0x65, 0x30, 0xB2, 0xF9, 0x00, 0x20, 0x00, 0x2A, 0x03, 0xDB, 0x00, 0x2B, 0x7F, 0xF4, 0x5F, 0xAF, 0xCB, 0xE6, +0x1C, 0x2B, 0xF9, 0xD9, 0x39, 0x49, 0x3A, 0x48, 0x40, 0xF2, 0x01, 0x32, 0xEF, 0xF7, 0x06, 0xF8, 0x98, 0xF8, 0x65, 0x30, +0x00, 0x2B, 0x7F, 0xF4, 0x51, 0xAF, 0xBD, 0xE6, 0x00, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, 0xD4, 0xE7, 0x00, 0x25, +0x04, 0x20, 0x41, 0x24, 0x34, 0x22, 0xCF, 0xE7, 0x00, 0x25, 0x04, 0x20, 0x31, 0x24, 0x24, 0x22, 0xCA, 0xE7, 0x01, 0x20, +0x02, 0x46, 0x00, 0x25, 0x0E, 0x24, 0xC5, 0xE7, 0x00, 0x28, 0x7F, 0xF4, 0xB6, 0xAE, 0x04, 0x9A, 0x23, 0x2A, 0x7F, 0xF6, +0x06, 0xAF, 0x30, 0x2A, 0x15, 0xD9, 0x40, 0x2A, 0x10, 0xD9, 0x70, 0x2A, 0x3B, 0xD9, 0x80, 0x2A, 0x36, 0xD9, 0x90, 0x2A, +0x3F, 0xF6, 0xFB, 0xAE, 0x90, 0x21, 0x84, 0x22, 0x10, 0x1D, 0x03, 0xF8, 0x01, 0x2B, 0xC2, 0xB2, 0x91, 0x42, 0xF9, 0xD2, +0x04, 0x23, 0xA0, 0xE5, 0x40, 0x21, 0x34, 0x22, 0xF4, 0xE7, 0x30, 0x21, 0x24, 0x22, 0xF1, 0xE7, 0x24, 0x22, 0x03, 0xF8, +0x01, 0x2B, 0x04, 0x32, 0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x91, 0x24, 0x64, 0x22, +0x96, 0xE7, 0x00, 0x25, 0x04, 0x20, 0xAA, 0x24, 0x95, 0x22, 0x91, 0xE7, 0x24, 0x22, 0x03, 0xF8, 0x01, 0x2B, 0x04, 0x32, +0x44, 0x2A, 0xFA, 0xD1, 0x08, 0xF1, 0x6E, 0x06, 0x08, 0x25, 0x04, 0x20, 0x81, 0x24, 0x64, 0x22, 0x84, 0xE7, 0x0F, 0x24, +0x01, 0x20, 0x00, 0x25, 0x0E, 0x22, 0x7F, 0xE7, 0x80, 0x21, 0x74, 0x22, 0xCA, 0xE7, 0x70, 0x21, 0x64, 0x22, 0xC7, 0xE7, +0x05, 0x9A, 0x04, 0x92, 0x69, 0xE6, 0x05, 0x9A, 0x04, 0x92, 0xB0, 0xE7, 0x38, 0x36, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, +0x5C, 0xD1, 0x15, 0x00, 0x70, 0xB5, 0x15, 0x4D, 0x2C, 0x68, 0xA5, 0xF5, 0xBD, 0x56, 0x01, 0x34, 0xA5, 0xF1, 0x90, 0x01, +0x2C, 0x60, 0x33, 0x46, 0x01, 0x20, 0x9A, 0x88, 0x01, 0x2A, 0x88, 0xBF, 0x98, 0x80, 0x03, 0xF5, 0xF6, 0x73, 0x8B, 0x42, +0xF7, 0xD1, 0x41, 0xF2, 0xA4, 0x73, 0xF3, 0x58, 0x9C, 0x42, 0x0B, 0xDA, 0x04, 0x21, 0x0B, 0x20, 0xED, 0xF7, 0x90, 0xF8, +0x0B, 0x22, 0xBD, 0xE8, 0x70, 0x40, 0x11, 0x46, 0x4F, 0xF4, 0x30, 0x50, 0xEC, 0xF7, 0xF6, 0xBE, 0x00, 0x21, 0x0B, 0x20, +0xED, 0xF7, 0x84, 0xF8, 0x4F, 0xF0, 0xFF, 0x33, 0x2B, 0x60, 0x70, 0xBD, 0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF8, 0x43, +0x3E, 0x4C, 0x3F, 0x4E, 0x04, 0xF5, 0xBD, 0x53, 0x31, 0x68, 0x1B, 0x68, 0xB1, 0xF9, 0x00, 0x10, 0x03, 0xEB, 0x03, 0x13, +0x04, 0xEB, 0xC3, 0x05, 0x05, 0xF5, 0xB8, 0x55, 0x00, 0x29, 0x05, 0xF1, 0x10, 0x05, 0x4F, 0xEA, 0xC3, 0x03, 0x3A, 0xDB, +0x23, 0x44, 0x41, 0xF2, 0x13, 0x72, 0x9B, 0x5C, 0x01, 0x2B, 0x45, 0xD9, 0x02, 0x2B, 0x50, 0xD1, 0x02, 0x21, 0x0B, 0x20, +0xED, 0xF7, 0x5C, 0xF8, 0x30, 0x48, 0x2E, 0x4C, 0xA0, 0xF1, 0x88, 0x06, 0x06, 0xF1, 0x88, 0x09, 0xED, 0xF7, 0xE4, 0xFA, +0x00, 0x27, 0x4F, 0xF0, 0x02, 0x08, 0x03, 0xE0, 0x04, 0xF5, 0xF6, 0x74, 0xB4, 0x42, 0x18, 0xD0, 0xA3, 0x88, 0x01, 0x2B, +0xF8, 0xD1, 0x63, 0x7D, 0x04, 0xF1, 0x1C, 0x01, 0x19, 0x44, 0x2A, 0x46, 0xA0, 0x1D, 0xFF, 0xF7, 0x15, 0xFB, 0x00, 0x28, +0xEE, 0xD0, 0x21, 0x46, 0x27, 0x83, 0xE7, 0x75, 0xA4, 0xF8, 0x04, 0x80, 0x48, 0x46, 0x04, 0xF5, 0xF6, 0x74, 0xED, 0xF7, +0xC9, 0xFA, 0xB4, 0x42, 0xE6, 0xD1, 0x28, 0x46, 0x00, 0x21, 0xBD, 0xE8, 0xF8, 0x43, 0xFF, 0xF7, 0x99, 0xBA, 0x1C, 0x44, +0x41, 0xF2, 0x12, 0x73, 0xE3, 0x5C, 0x05, 0x2B, 0x19, 0xD0, 0x17, 0x49, 0x17, 0x48, 0x40, 0xF2, 0xA3, 0x62, 0xEE, 0xF7, +0x09, 0xFF, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0x05, 0xD8, 0x28, 0x46, 0x01, 0x21, 0xBD, 0xE8, 0xF8, 0x43, +0xFF, 0xF7, 0x24, 0xBB, 0x02, 0x2B, 0xB3, 0xD0, 0x33, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x08, 0xDB, 0xBD, 0xE8, +0xF8, 0x83, 0x41, 0xF2, 0x13, 0x73, 0xE3, 0x5C, 0x01, 0x2B, 0xEB, 0xD9, 0x02, 0x2B, 0xA5, 0xD0, 0xBD, 0xE8, 0xF8, 0x43, +0x05, 0x49, 0x07, 0x48, 0x40, 0xF2, 0xAF, 0x62, 0xEE, 0xF7, 0xE6, 0xBE, 0x78, 0xEF, 0x17, 0x00, 0x38, 0x36, 0x17, 0x00, +0x10, 0x07, 0x18, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, 0x64, 0x7D, 0x15, 0x00, 0x2D, 0xE9, 0xF0, 0x41, +0xDF, 0xF8, 0xCC, 0x80, 0x2C, 0x4A, 0xD8, 0xF8, 0x00, 0x30, 0x14, 0x68, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0x0C, 0xDB, +0x29, 0x4F, 0x04, 0xEB, 0x04, 0x13, 0x07, 0xEB, 0xC3, 0x03, 0x41, 0xF2, 0x13, 0x72, 0x25, 0x01, 0x9B, 0x5C, 0x01, 0x2B, +0x19, 0xD9, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x2C, 0x35, 0xDB, 0x22, 0x4F, 0x04, 0xEB, 0x04, 0x16, 0x07, 0xEB, 0xC6, 0x06, +0x41, 0xF2, 0x12, 0x73, 0x25, 0x01, 0xF3, 0x5C, 0x05, 0x2B, 0x15, 0xD0, 0x1D, 0x49, 0x1E, 0x48, 0x4F, 0xF4, 0xD7, 0x62, +0xEE, 0xF7, 0xAE, 0xFE, 0x41, 0xF2, 0x13, 0x73, 0xF3, 0x5C, 0x01, 0x2B, 0x17, 0xD8, 0x2C, 0x44, 0x07, 0xEB, 0xC4, 0x00, +0x00, 0xF5, 0xB8, 0x50, 0xBD, 0xE8, 0xF0, 0x41, 0x10, 0x30, 0x00, 0x21, 0xFF, 0xF7, 0xC4, 0xBA, 0x41, 0xF2, 0x13, 0x73, +0xF3, 0x5C, 0x01, 0x2B, 0xEF, 0xD9, 0xBD, 0xE8, 0xF0, 0x41, 0x0F, 0x49, 0x10, 0x48, 0x40, 0xF2, 0xC1, 0x62, 0xEE, 0xF7, +0x91, 0xBE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, 0xF1, 0xDB, 0xBD, 0xE8, 0xF0, 0x81, 0x08, 0x49, +0x0A, 0x48, 0x40, 0xF2, 0xB7, 0x62, 0xEE, 0xF7, 0x83, 0xFE, 0xD8, 0xF8, 0x00, 0x30, 0xB3, 0xF9, 0x00, 0x30, 0x00, 0x2B, +0xBD, 0xDB, 0xAD, 0xE7, 0x18, 0x07, 0x18, 0x00, 0x78, 0xEF, 0x17, 0x00, 0x70, 0x79, 0x15, 0x00, 0x94, 0xD1, 0x15, 0x00, +0x64, 0x7D, 0x15, 0x00, 0xC0, 0xD1, 0x15, 0x00, 0x38, 0x36, 0x17, 0x00, 0x70, 0xB5, 0x29, 0xB3, 0x18, 0x4C, 0x04, 0xF5, +0xBD, 0x53, 0x05, 0x46, 0x1E, 0x68, 0xFE, 0xF7, 0x01, 0xFF, 0x02, 0x46, 0x40, 0xB1, 0x0B, 0x20, 0xED, 0xF7, 0x20, 0xF8, +0x03, 0x28, 0x1F, 0xD0, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xC6, 0xBE, 0x06, 0xEB, 0x06, 0x16, 0x04, 0xEB, 0xC6, 0x03, +0x01, 0x21, 0x03, 0xF5, 0xB8, 0x53, 0x85, 0xF8, 0x5E, 0x10, 0x10, 0x33, 0x01, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0x00, 0xFF, +0x28, 0x46, 0x03, 0x21, 0xBD, 0xE8, 0x70, 0x40, 0xDA, 0xF7, 0x42, 0xB8, 0x0B, 0x20, 0xEC, 0xF7, 0x5B, 0xFF, 0x05, 0x4B, +0x4F, 0xF0, 0xFF, 0x32, 0x1A, 0x60, 0x70, 0xBD, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0x60, 0xBF, 0x78, 0xEF, 0x17, 0x00, +0x18, 0x07, 0x18, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x8B, 0xB0, 0xB6, 0x4F, 0x9D, 0xF8, 0x50, 0x40, 0x03, 0x94, 0x9D, 0xF9, +0x54, 0x40, 0x04, 0x94, 0x07, 0xF5, 0xBD, 0x55, 0x04, 0x46, 0x28, 0x68, 0x25, 0x7C, 0x8D, 0xF8, 0x20, 0x50, 0x65, 0x7C, +0x8D, 0xF8, 0x21, 0x50, 0xA5, 0x7C, 0x8D, 0xF8, 0x22, 0x50, 0xE5, 0x7C, 0x8D, 0xF8, 0x23, 0x50, 0x25, 0x7D, 0x8D, 0xF8, +0x24, 0x50, 0x00, 0x28, 0x65, 0x7D, 0x9D, 0xF8, 0x58, 0x90, 0x8D, 0xF8, 0x25, 0x50, 0x0E, 0x46, 0x90, 0x46, 0x05, 0x93, +0xC0, 0xF2, 0x1A, 0x81, 0x00, 0xEB, 0x00, 0x10, 0x07, 0xEB, 0xC0, 0x00, 0x00, 0xF5, 0xB8, 0x57, 0x10, 0x37, 0x3A, 0x46, +0x00, 0x21, 0x08, 0xA8, 0xFF, 0xF7, 0xEE, 0xF9, 0x10, 0xB9, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xBD, 0xF8, 0x20, 0x00, +0xBD, 0xF8, 0x24, 0x30, 0x01, 0x93, 0x00, 0x21, 0xBD, 0xF8, 0x22, 0xE0, 0x97, 0x4B, 0x98, 0x4A, 0x02, 0x94, 0x8C, 0x46, +0x0D, 0x46, 0x83, 0x46, 0x0B, 0xE0, 0x98, 0x88, 0x01, 0x28, 0x00, 0xF0, 0xC1, 0x80, 0x03, 0x28, 0x00, 0xF0, 0xB4, 0x80, +0x88, 0xB1, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0x14, 0xD0, 0xB3, 0xF8, 0x06, 0xA0, 0xDA, 0x45, 0xEF, 0xD1, 0x18, 0x89, +0x70, 0x45, 0xEC, 0xD1, 0x58, 0x89, 0x01, 0x9C, 0xA0, 0x42, 0xE8, 0xD1, 0x02, 0x9C, 0x1D, 0x46, 0x10, 0xE0, 0x00, 0x2D, +0x08, 0xBF, 0x1D, 0x46, 0x03, 0xF5, 0xF6, 0x73, 0x93, 0x42, 0xEA, 0xD1, 0x02, 0x9C, 0x00, 0x2D, 0x00, 0xF0, 0x42, 0x81, +0x4F, 0xF4, 0xF6, 0x72, 0x00, 0x21, 0x28, 0x46, 0xCA, 0xF7, 0xDC, 0xF8, 0xAB, 0x88, 0x03, 0x2B, 0xBF, 0xD0, 0x03, 0x9B, +0xBD, 0xF8, 0x20, 0x10, 0xBD, 0xF8, 0x22, 0x20, 0xC5, 0xF8, 0x0C, 0x80, 0x00, 0x2B, 0xBD, 0xF8, 0x24, 0x30, 0x6B, 0x81, +0x08, 0xBF, 0x05, 0x20, 0x05, 0xF1, 0x1C, 0x03, 0x18, 0xBF, 0x04, 0x20, 0x02, 0x93, 0x04, 0xF1, 0x24, 0x08, 0x85, 0xF8, +0x11, 0x90, 0xA8, 0x74, 0xE9, 0x80, 0x2A, 0x81, 0x18, 0x34, 0x05, 0xF1, 0x1B, 0x03, 0x14, 0xF8, 0x01, 0x2B, 0x03, 0xF8, +0x01, 0x2F, 0x44, 0x45, 0xF9, 0xD1, 0x02, 0x9B, 0xA6, 0xF1, 0x24, 0x09, 0x03, 0xF1, 0x0C, 0x0B, 0xB9, 0xF1, 0x02, 0x0F, +0x4F, 0xF0, 0x00, 0x03, 0xCD, 0xE9, 0x06, 0x33, 0x40, 0xF3, 0x56, 0x81, 0x4F, 0xF4, 0xE2, 0x7A, 0x3A, 0x46, 0x98, 0xF8, +0x01, 0x40, 0x98, 0xF8, 0x00, 0x60, 0x98, 0xF8, 0x02, 0x70, 0x02, 0x34, 0x08, 0xF1, 0x02, 0x00, 0x00, 0x2E, 0x71, 0xD0, +0x03, 0x2E, 0x7D, 0xD0, 0xA9, 0x7C, 0x05, 0x29, 0x00, 0xF2, 0x81, 0x80, 0x2A, 0x2E, 0x00, 0xF0, 0x8D, 0x80, 0x3D, 0x2E, +0x00, 0xF0, 0x8D, 0x80, 0xC0, 0x2E, 0x00, 0xF0, 0x9A, 0x80, 0xFF, 0x2E, 0x02, 0xD1, 0x08, 0x2C, 0x00, 0xF2, 0xCD, 0x80, +0x54, 0x45, 0x07, 0xDC, 0x39, 0x46, 0x30, 0x46, 0x01, 0x92, 0xFE, 0xF7, 0xD5, 0xFD, 0x01, 0x9A, 0x00, 0x28, 0x46, 0xD1, +0xA0, 0x44, 0xA9, 0xEB, 0x04, 0x09, 0xB9, 0xF1, 0x02, 0x0F, 0xD0, 0xDC, 0xCA, 0xF5, 0xE8, 0x7A, 0x1F, 0xFA, 0x8A, 0xFA, +0xAB, 0x7D, 0xA5, 0xF8, 0x1A, 0xA0, 0x00, 0x2B, 0x00, 0xF0, 0x94, 0x80, 0x04, 0x9B, 0x2B, 0x75, 0x2B, 0x7C, 0x06, 0x9A, +0x04, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x03, 0x2A, 0x00, 0xF0, 0x05, 0x81, 0x02, 0x2A, 0x00, 0xF0, 0x04, 0x81, 0x03, 0x99, +0x00, 0x29, 0x40, 0xF0, 0xC0, 0x80, 0x0E, 0x2B, 0x00, 0xF0, 0x14, 0x81, 0x00, 0x2A, 0x00, 0xF0, 0x06, 0x81, 0x07, 0x9B, +0x01, 0x2B, 0x0C, 0xBF, 0x54, 0x23, 0x53, 0x23, 0x01, 0x22, 0xEB, 0x74, 0xAA, 0x80, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, +0x00, 0x29, 0x41, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x91, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x19, 0x46, 0x42, 0xE7, +0xBC, 0xF1, 0x00, 0x0F, 0x34, 0xD0, 0x93, 0xF9, 0x14, 0xA0, 0x9C, 0xF9, 0x14, 0x00, 0x82, 0x45, 0xB8, 0xBF, 0x9C, 0x46, +0x37, 0xE7, 0x43, 0x46, 0xAB, 0xEB, 0x03, 0x00, 0xA0, 0x44, 0x19, 0x78, 0xC1, 0x54, 0x01, 0x33, 0x98, 0x45, 0xFA, 0xD1, +0xA3, 0x44, 0xAA, 0xEB, 0x04, 0x0A, 0xAC, 0xE7, 0x02, 0x9B, 0x01, 0x92, 0xAB, 0xEB, 0x03, 0x01, 0x69, 0x75, 0xA8, 0x1D, +0x41, 0x46, 0xFF, 0xF7, 0xF5, 0xF8, 0x01, 0x9A, 0x00, 0x28, 0x95, 0xD1, 0xA8, 0x80, 0x02, 0xE7, 0x02, 0x9B, 0xAB, 0xEB, +0x03, 0x01, 0xA9, 0x75, 0x01, 0x78, 0x29, 0x74, 0x8C, 0xE7, 0x06, 0x29, 0x3F, 0xF4, 0x7F, 0xAF, 0x08, 0x29, 0x7F, 0xF6, +0x7F, 0xAF, 0x0D, 0x29, 0x84, 0xD8, 0x7E, 0xE7, 0x00, 0x27, 0xEA, 0xE6, 0x9C, 0x46, 0x08, 0xE7, 0x19, 0x46, 0x06, 0xE7, +0x06, 0x21, 0xA9, 0x74, 0x7A, 0xE7, 0x18, 0x2C, 0x7F, 0xF4, 0x78, 0xAF, 0x4F, 0xF0, 0x07, 0x03, 0xAB, 0x74, 0x98, 0xF8, +0x03, 0x10, 0x11, 0xF0, 0x03, 0x03, 0x07, 0x93, 0x06, 0x9B, 0x18, 0xBF, 0x01, 0x23, 0x06, 0x93, 0x6A, 0xE7, 0x07, 0x2C, +0x7F, 0xF4, 0x68, 0xAF, 0x4F, 0xF0, 0x09, 0x03, 0xAB, 0x74, 0x01, 0x78, 0x00, 0x29, 0x3F, 0xF4, 0x61, 0xAF, 0x01, 0x29, +0x76, 0xD0, 0x02, 0x29, 0x00, 0xF0, 0x97, 0x80, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x55, 0xE7, +0x78, 0xEF, 0x17, 0x00, 0x88, 0x06, 0x18, 0x00, 0xAA, 0x88, 0x22, 0xB1, 0x95, 0xF9, 0x14, 0x20, 0x04, 0x99, 0x8A, 0x42, +0x60, 0xDA, 0x04, 0x9A, 0x2A, 0x75, 0x03, 0x9A, 0x00, 0x2A, 0x42, 0xD1, 0x05, 0x99, 0xA1, 0xF6, 0x6C, 0x13, 0x48, 0x2B, +0x6D, 0xD8, 0x40, 0xF6, 0xB4, 0x13, 0x99, 0x42, 0x00, 0xF0, 0x82, 0x80, 0x48, 0x4A, 0xA1, 0xF6, 0x67, 0x13, 0xA2, 0xFB, +0x03, 0x23, 0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x4F, 0xE7, 0x24, 0x2F, 0x7F, 0xF4, 0x30, 0xAF, 0x09, 0x29, 0x11, 0xD0, +0x0B, 0x2C, 0x0F, 0xD9, 0xD8, 0xF8, 0x03, 0x10, 0x4B, 0x04, 0x0B, 0xD5, 0x98, 0xF8, 0x09, 0x10, 0x41, 0xB1, 0x01, 0x29, +0x71, 0xD0, 0x02, 0x29, 0x72, 0xD0, 0x03, 0x29, 0x06, 0x9B, 0x08, 0xBF, 0x04, 0x23, 0x06, 0x93, 0x4F, 0xF0, 0x0E, 0x03, +0xAB, 0x74, 0x17, 0xE7, 0x89, 0xB3, 0x0D, 0x46, 0xBA, 0xE6, 0x30, 0x2B, 0x24, 0xD9, 0x40, 0x2B, 0x40, 0xD9, 0x90, 0x2B, +0x4C, 0xD9, 0xA4, 0x2B, 0x59, 0xD8, 0x06, 0x9B, 0x00, 0x2B, 0x54, 0xD0, 0x0A, 0x23, 0x07, 0x9A, 0x01, 0x2A, 0x0C, 0xBF, +0x74, 0x33, 0x75, 0x33, 0x38, 0xE7, 0x03, 0x9A, 0x01, 0x2A, 0xCA, 0xD1, 0x05, 0x9A, 0xA2, 0xF5, 0x9C, 0x51, 0xA1, 0xF1, +0x0D, 0x02, 0x92, 0xB2, 0xB2, 0xF5, 0x4D, 0x7F, 0xC1, 0xD8, 0x26, 0x4A, 0xA1, 0xF1, 0x08, 0x03, 0xA2, 0xFB, 0x03, 0x23, +0xC3, 0xF3, 0x87, 0x03, 0x2B, 0x74, 0x0A, 0xE7, 0x06, 0x9B, 0x23, 0xB3, 0x00, 0x23, 0xE0, 0xE7, 0x2B, 0x7C, 0x04, 0xE7, +0x02, 0x23, 0x06, 0x93, 0xE4, 0xE6, 0xBC, 0xF1, 0x00, 0x0F, 0x3F, 0xF4, 0x50, 0xAE, 0x9C, 0xF9, 0x14, 0x30, 0x04, 0x9A, +0x93, 0x42, 0xBF, 0xF6, 0x4A, 0xAE, 0x65, 0x46, 0x7E, 0xE6, 0x82, 0x23, 0x0C, 0xE7, 0x81, 0x23, 0x0A, 0xE7, 0x80, 0x23, +0x08, 0xE7, 0x03, 0x9B, 0x2B, 0x74, 0xEC, 0xE6, 0x06, 0x9B, 0x8B, 0xB1, 0x03, 0x23, 0xC2, 0xE7, 0x4F, 0xF0, 0x0C, 0x0A, +0xDC, 0xE6, 0x51, 0x23, 0xFC, 0xE6, 0x73, 0x23, 0xFA, 0xE6, 0x03, 0x23, 0x06, 0x93, 0xC1, 0xE6, 0x06, 0x9B, 0x43, 0xB1, +0x06, 0x23, 0xB4, 0xE7, 0x52, 0x23, 0xF1, 0xE6, 0x76, 0x23, 0xEF, 0xE6, 0x0E, 0x23, 0x2B, 0x74, 0xD3, 0xE6, 0x79, 0x23, +0xEA, 0xE6, 0x7C, 0x23, 0xE8, 0xE6, 0x7D, 0x23, 0xE6, 0xE6, 0x02, 0x23, 0x06, 0x93, 0x91, 0xE7, 0x03, 0x23, 0x06, 0x93, +0x8E, 0xE7, 0x00, 0xBF, 0xCD, 0xCC, 0xCC, 0xCC, 0x2D, 0xE9, 0xF0, 0x48, 0xC1, 0xF3, 0x0A, 0x57, 0xA7, 0xF2, 0xFF, 0x34, +0x13, 0x2C, 0x0B, 0x46, 0x0D, 0x46, 0x02, 0x46, 0x0F, 0xDC, 0x00, 0x2C, 0x2A, 0xDB, 0x1D, 0x49, 0x21, 0x41, 0x03, 0xEA, +0x01, 0x00, 0x10, 0x43, 0x2F, 0xD0, 0x4F, 0xF4, 0x00, 0x23, 0x23, 0x41, 0x1D, 0x44, 0x25, 0xEA, 0x01, 0x05, 0x00, 0x23, +0x25, 0xE0, 0x33, 0x2C, 0x07, 0xDD, 0xB4, 0xF5, 0x80, 0x6F, 0x22, 0xD1, 0x00, 0xF0, 0x2E, 0xF8, 0x02, 0x46, 0x0B, 0x46, +0x1D, 0xE0, 0xA7, 0xF2, 0x13, 0x47, 0x4F, 0xF0, 0xFF, 0x31, 0x21, 0xFA, 0x07, 0xF7, 0x38, 0x42, 0x15, 0xD0, 0x01, 0x22, +0xC4, 0xF1, 0x33, 0x03, 0x02, 0xFA, 0x03, 0xF3, 0xC3, 0x18, 0x28, 0xBF, 0xAD, 0x18, 0x23, 0xEA, 0x07, 0x03, 0x08, 0xE0, +0x01, 0xF0, 0x00, 0x45, 0x01, 0x34, 0x04, 0xBF, 0x45, 0xF0, 0x7F, 0x55, 0x45, 0xF4, 0x40, 0x15, 0x00, 0x23, 0x1A, 0x46, +0x2B, 0x46, 0x10, 0x46, 0x19, 0x46, 0xBD, 0xE8, 0xF0, 0x88, 0x00, 0xBF, 0xFF, 0xFF, 0x0F, 0x00, 0x81, 0xF0, 0x00, 0x41, +0x02, 0xE0, 0x00, 0xBF, 0x83, 0xF0, 0x00, 0x43, 0x30, 0xB5, 0x4F, 0xEA, 0x41, 0x04, 0x4F, 0xEA, 0x43, 0x05, 0x94, 0xEA, +0x05, 0x0F, 0x08, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x1F, 0xBF, 0x54, 0xEA, 0x00, 0x0C, 0x55, 0xEA, 0x02, 0x0C, 0x7F, 0xEA, +0x64, 0x5C, 0x7F, 0xEA, 0x65, 0x5C, 0x00, 0xF0, 0xE2, 0x80, 0x4F, 0xEA, 0x54, 0x54, 0xD4, 0xEB, 0x55, 0x55, 0xB8, 0xBF, +0x6D, 0x42, 0x0C, 0xDD, 0x2C, 0x44, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x82, 0xEA, 0x00, 0x00, 0x83, 0xEA, +0x01, 0x01, 0x80, 0xEA, 0x02, 0x02, 0x81, 0xEA, 0x03, 0x03, 0x36, 0x2D, 0x88, 0xBF, 0x30, 0xBD, 0x11, 0xF0, 0x00, 0x4F, +0x4F, 0xEA, 0x01, 0x31, 0x4F, 0xF4, 0x80, 0x1C, 0x4C, 0xEA, 0x11, 0x31, 0x02, 0xD0, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, +0x13, 0xF0, 0x00, 0x4F, 0x4F, 0xEA, 0x03, 0x33, 0x4C, 0xEA, 0x13, 0x33, 0x02, 0xD0, 0x52, 0x42, 0x63, 0xEB, 0x43, 0x03, +0x94, 0xEA, 0x05, 0x0F, 0x00, 0xF0, 0xA7, 0x80, 0xA4, 0xF1, 0x01, 0x04, 0xD5, 0xF1, 0x20, 0x0E, 0x0D, 0xDB, 0x02, 0xFA, +0x0E, 0xFC, 0x22, 0xFA, 0x05, 0xF2, 0x80, 0x18, 0x41, 0xF1, 0x00, 0x01, 0x03, 0xFA, 0x0E, 0xF2, 0x80, 0x18, 0x43, 0xFA, +0x05, 0xF3, 0x59, 0x41, 0x0E, 0xE0, 0xA5, 0xF1, 0x20, 0x05, 0x0E, 0xF1, 0x20, 0x0E, 0x01, 0x2A, 0x03, 0xFA, 0x0E, 0xFC, +0x28, 0xBF, 0x4C, 0xF0, 0x02, 0x0C, 0x43, 0xFA, 0x05, 0xF3, 0xC0, 0x18, 0x51, 0xEB, 0xE3, 0x71, 0x01, 0xF0, 0x00, 0x45, +0x07, 0xD5, 0x4F, 0xF0, 0x00, 0x0E, 0xDC, 0xF1, 0x00, 0x0C, 0x7E, 0xEB, 0x00, 0x00, 0x6E, 0xEB, 0x01, 0x01, 0xB1, 0xF5, +0x80, 0x1F, 0x1B, 0xD3, 0xB1, 0xF5, 0x00, 0x1F, 0x0C, 0xD3, 0x49, 0x08, 0x5F, 0xEA, 0x30, 0x00, 0x4F, 0xEA, 0x3C, 0x0C, +0x04, 0xF1, 0x01, 0x04, 0x4F, 0xEA, 0x44, 0x52, 0x12, 0xF5, 0x80, 0x0F, 0x80, 0xF0, 0x9A, 0x80, 0xBC, 0xF1, 0x00, 0x4F, +0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, 0x04, 0x51, 0x41, 0xEA, 0x05, 0x01, 0x30, 0xBD, +0x5F, 0xEA, 0x4C, 0x0C, 0x40, 0x41, 0x41, 0xEB, 0x01, 0x01, 0x01, 0x3C, 0x28, 0xBF, 0xB1, 0xF5, 0x80, 0x1F, 0xE9, 0xD2, +0x91, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x01, 0x46, 0x00, 0x20, 0xB1, 0xFA, 0x81, 0xF3, 0x08, 0xBF, 0x20, 0x33, 0xA3, 0xF1, +0x0B, 0x03, 0xB3, 0xF1, 0x20, 0x02, 0x0C, 0xDA, 0x0C, 0x32, 0x08, 0xDD, 0x02, 0xF1, 0x14, 0x0C, 0xC2, 0xF1, 0x0C, 0x02, +0x01, 0xFA, 0x0C, 0xF0, 0x21, 0xFA, 0x02, 0xF1, 0x0C, 0xE0, 0x02, 0xF1, 0x14, 0x02, 0xD8, 0xBF, 0xC2, 0xF1, 0x20, 0x0C, +0x01, 0xFA, 0x02, 0xF1, 0x20, 0xFA, 0x0C, 0xFC, 0xDC, 0xBF, 0x41, 0xEA, 0x0C, 0x01, 0x90, 0x40, 0xE4, 0x1A, 0xA2, 0xBF, +0x01, 0xEB, 0x04, 0x51, 0x29, 0x43, 0x30, 0xBD, 0x6F, 0xEA, 0x04, 0x04, 0x1F, 0x3C, 0x1C, 0xDA, 0x0C, 0x34, 0x0E, 0xDC, +0x04, 0xF1, 0x14, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x02, 0xF3, 0x40, 0xEA, 0x03, 0x00, +0x21, 0xFA, 0x04, 0xF3, 0x45, 0xEA, 0x03, 0x01, 0x30, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x02, 0x20, 0xFA, +0x02, 0xF0, 0x01, 0xFA, 0x04, 0xF3, 0x40, 0xEA, 0x03, 0x00, 0x29, 0x46, 0x30, 0xBD, 0x21, 0xFA, 0x04, 0xF0, 0x29, 0x46, +0x30, 0xBD, 0x94, 0xF0, 0x00, 0x0F, 0x83, 0xF4, 0x80, 0x13, 0x06, 0xBF, 0x81, 0xF4, 0x80, 0x11, 0x01, 0x34, 0x01, 0x3D, +0x4E, 0xE7, 0x7F, 0xEA, 0x64, 0x5C, 0x18, 0xBF, 0x7F, 0xEA, 0x65, 0x5C, 0x29, 0xD0, 0x94, 0xEA, 0x05, 0x0F, 0x08, 0xBF, +0x90, 0xEA, 0x02, 0x0F, 0x05, 0xD0, 0x54, 0xEA, 0x00, 0x0C, 0x04, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x30, 0xBD, 0x91, 0xEA, +0x03, 0x0F, 0x1E, 0xBF, 0x00, 0x21, 0x00, 0x20, 0x30, 0xBD, 0x5F, 0xEA, 0x54, 0x5C, 0x05, 0xD1, 0x40, 0x00, 0x49, 0x41, +0x28, 0xBF, 0x41, 0xF0, 0x00, 0x41, 0x30, 0xBD, 0x14, 0xF5, 0x80, 0x04, 0x3C, 0xBF, 0x01, 0xF5, 0x80, 0x11, 0x30, 0xBD, +0x01, 0xF0, 0x00, 0x45, 0x45, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x30, 0xBD, 0x7F, 0xEA, +0x64, 0x5C, 0x1A, 0xBF, 0x19, 0x46, 0x10, 0x46, 0x7F, 0xEA, 0x65, 0x5C, 0x1C, 0xBF, 0x0B, 0x46, 0x02, 0x46, 0x50, 0xEA, +0x01, 0x34, 0x06, 0xBF, 0x52, 0xEA, 0x03, 0x35, 0x91, 0xEA, 0x03, 0x0F, 0x41, 0xF4, 0x00, 0x21, 0x30, 0xBD, 0x00, 0xBF, +0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, +0x4F, 0xF0, 0x00, 0x05, 0x4F, 0xF0, 0x00, 0x01, 0x50, 0xE7, 0x00, 0xBF, 0x90, 0xF0, 0x00, 0x0F, 0x04, 0xBF, 0x00, 0x21, +0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, 0x32, 0x04, 0x10, 0xF0, 0x00, 0x45, 0x48, 0xBF, 0x40, 0x42, +0x4F, 0xF0, 0x00, 0x01, 0x3E, 0xE7, 0x00, 0xBF, 0x42, 0x00, 0x4F, 0xEA, 0xE2, 0x01, 0x4F, 0xEA, 0x31, 0x01, 0x4F, 0xEA, +0x02, 0x70, 0x1F, 0xBF, 0x12, 0xF0, 0x7F, 0x43, 0x93, 0xF0, 0x7F, 0x4F, 0x81, 0xF0, 0x60, 0x51, 0x70, 0x47, 0x32, 0xF0, +0x7F, 0x42, 0x08, 0xBF, 0x70, 0x47, 0x93, 0xF0, 0x7F, 0x4F, 0x04, 0xBF, 0x41, 0xF4, 0x00, 0x21, 0x70, 0x47, 0x30, 0xB5, +0x4F, 0xF4, 0x60, 0x74, 0x01, 0xF0, 0x00, 0x45, 0x21, 0xF0, 0x00, 0x41, 0x1C, 0xE7, 0x00, 0xBF, 0x50, 0xEA, 0x01, 0x02, +0x08, 0xBF, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF0, 0x00, 0x05, 0x0A, 0xE0, 0x50, 0xEA, 0x01, 0x02, 0x08, 0xBF, 0x70, 0x47, +0x30, 0xB5, 0x11, 0xF0, 0x00, 0x45, 0x02, 0xD5, 0x40, 0x42, 0x61, 0xEB, 0x41, 0x01, 0x4F, 0xF4, 0x80, 0x64, 0x04, 0xF1, +0x32, 0x04, 0x5F, 0xEA, 0x91, 0x5C, 0x3F, 0xF4, 0xD8, 0xAE, 0x4F, 0xF0, 0x03, 0x02, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, +0x03, 0x32, 0x5F, 0xEA, 0xDC, 0x0C, 0x18, 0xBF, 0x03, 0x32, 0x02, 0xEB, 0xDC, 0x02, 0xC2, 0xF1, 0x20, 0x03, 0x00, 0xFA, +0x03, 0xFC, 0x20, 0xFA, 0x02, 0xF0, 0x01, 0xFA, 0x03, 0xFE, 0x40, 0xEA, 0x0E, 0x00, 0x21, 0xFA, 0x02, 0xF1, 0x14, 0x44, +0xBD, 0xE6, 0x00, 0xBF, 0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, +0x1C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xDE, 0xF8, 0x2C, 0x44, 0x81, 0xEA, +0x03, 0x06, 0x21, 0xEA, 0x4C, 0x51, 0x23, 0xEA, 0x4C, 0x53, 0x50, 0xEA, 0x01, 0x35, 0x18, 0xBF, 0x52, 0xEA, 0x03, 0x35, +0x41, 0xF4, 0x80, 0x11, 0x43, 0xF4, 0x80, 0x13, 0x38, 0xD0, 0xA0, 0xFB, 0x02, 0xCE, 0x4F, 0xF0, 0x00, 0x05, 0xE1, 0xFB, +0x02, 0xE5, 0x06, 0xF0, 0x00, 0x42, 0xE0, 0xFB, 0x03, 0xE5, 0x4F, 0xF0, 0x00, 0x06, 0xE1, 0xFB, 0x03, 0x56, 0x9C, 0xF0, +0x00, 0x0F, 0x18, 0xBF, 0x4E, 0xF0, 0x01, 0x0E, 0xA4, 0xF1, 0xFF, 0x04, 0xB6, 0xF5, 0x00, 0x7F, 0x64, 0xF5, 0x40, 0x74, +0x04, 0xD2, 0x5F, 0xEA, 0x4E, 0x0E, 0x6D, 0x41, 0x46, 0xEB, 0x06, 0x06, 0x42, 0xEA, 0xC6, 0x21, 0x41, 0xEA, 0x55, 0x51, +0x4F, 0xEA, 0xC5, 0x20, 0x40, 0xEA, 0x5E, 0x50, 0x4F, 0xEA, 0xCE, 0x2E, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, +0xE0, 0x6F, 0x1E, 0xD8, 0xBE, 0xF1, 0x00, 0x4F, 0x08, 0xBF, 0x5F, 0xEA, 0x50, 0x0E, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, +0x04, 0x51, 0x70, 0xBD, 0x06, 0xF0, 0x00, 0x46, 0x46, 0xEA, 0x01, 0x01, 0x40, 0xEA, 0x02, 0x00, 0x81, 0xEA, 0x03, 0x01, +0xB4, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, 0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, +0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x00, 0xF3, 0xAB, 0x80, 0x14, 0xF1, 0x36, 0x0F, 0xDE, 0xBF, 0x00, 0x20, 0x01, 0xF0, +0x00, 0x41, 0x70, 0xBD, 0xC4, 0xF1, 0x00, 0x04, 0x20, 0x3C, 0x35, 0xDA, 0x0C, 0x34, 0x1B, 0xDC, 0x04, 0xF1, 0x14, 0x04, +0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF3, 0x20, 0xFA, 0x04, 0xF0, 0x01, 0xFA, 0x05, 0xF2, 0x40, 0xEA, 0x02, 0x00, +0x01, 0xF0, 0x00, 0x42, 0x21, 0xF0, 0x00, 0x41, 0x10, 0xEB, 0xD3, 0x70, 0x21, 0xFA, 0x04, 0xF6, 0x42, 0xEB, 0x06, 0x01, +0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0xC4, 0xF1, 0x0C, 0x04, 0xC4, 0xF1, 0x20, 0x05, +0x00, 0xFA, 0x04, 0xF3, 0x20, 0xFA, 0x05, 0xF0, 0x01, 0xFA, 0x04, 0xF2, 0x40, 0xEA, 0x02, 0x00, 0x01, 0xF0, 0x00, 0x41, +0x10, 0xEB, 0xD3, 0x70, 0x41, 0xF1, 0x00, 0x01, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, +0xC4, 0xF1, 0x20, 0x05, 0x00, 0xFA, 0x05, 0xF2, 0x4E, 0xEA, 0x02, 0x0E, 0x20, 0xFA, 0x04, 0xF3, 0x01, 0xFA, 0x05, 0xF2, +0x43, 0xEA, 0x02, 0x03, 0x21, 0xFA, 0x04, 0xF0, 0x01, 0xF0, 0x00, 0x41, 0x21, 0xFA, 0x04, 0xF2, 0x20, 0xEA, 0x02, 0x00, +0x00, 0xEB, 0xD3, 0x70, 0x5E, 0xEA, 0x43, 0x0E, 0x08, 0xBF, 0x20, 0xEA, 0xD3, 0x70, 0x70, 0xBD, 0x94, 0xF0, 0x00, 0x0F, +0x0F, 0xD1, 0x01, 0xF0, 0x00, 0x46, 0x40, 0x00, 0x41, 0xEB, 0x01, 0x01, 0x11, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3C, +0xF7, 0xD0, 0x41, 0xEA, 0x06, 0x01, 0x95, 0xF0, 0x00, 0x0F, 0x18, 0xBF, 0x70, 0x47, 0x03, 0xF0, 0x00, 0x46, 0x52, 0x00, +0x43, 0xEB, 0x03, 0x03, 0x13, 0xF4, 0x80, 0x1F, 0x08, 0xBF, 0x01, 0x3D, 0xF7, 0xD0, 0x43, 0xEA, 0x06, 0x03, 0x70, 0x47, +0x94, 0xEA, 0x0C, 0x0F, 0x0C, 0xEA, 0x13, 0x55, 0x18, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, 0x0C, 0xD0, 0x50, 0xEA, 0x41, 0x06, +0x18, 0xBF, 0x52, 0xEA, 0x43, 0x06, 0xD1, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, +0x70, 0xBD, 0x50, 0xEA, 0x41, 0x06, 0x06, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x52, 0xEA, 0x43, 0x06, 0x19, 0xD0, 0x94, 0xEA, +0x0C, 0x0F, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x36, 0x13, 0xD1, 0x95, 0xEA, 0x0C, 0x0F, 0x05, 0xD1, 0x52, 0xEA, 0x03, 0x36, +0x1C, 0xBF, 0x10, 0x46, 0x19, 0x46, 0x0A, 0xD1, 0x81, 0xEA, 0x03, 0x01, 0x01, 0xF0, 0x00, 0x41, 0x41, 0xF0, 0xFE, 0x41, +0x41, 0xF4, 0x70, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0xBD, 0x41, 0xF0, 0xFE, 0x41, 0x41, 0xF4, 0x78, 0x01, 0x70, 0xBD, +0x70, 0xB5, 0x4F, 0xF0, 0xFF, 0x0C, 0x4C, 0xF4, 0xE0, 0x6C, 0x1C, 0xEA, 0x11, 0x54, 0x1D, 0xBF, 0x1C, 0xEA, 0x13, 0x55, +0x94, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, 0x0F, 0x00, 0xF0, 0xA7, 0xF8, 0xA4, 0xEB, 0x05, 0x04, 0x81, 0xEA, 0x03, 0x0E, +0x52, 0xEA, 0x03, 0x35, 0x4F, 0xEA, 0x01, 0x31, 0x00, 0xF0, 0x88, 0x80, 0x4F, 0xEA, 0x03, 0x33, 0x4F, 0xF0, 0x80, 0x55, +0x45, 0xEA, 0x13, 0x13, 0x43, 0xEA, 0x12, 0x63, 0x4F, 0xEA, 0x02, 0x22, 0x45, 0xEA, 0x11, 0x15, 0x45, 0xEA, 0x10, 0x65, +0x4F, 0xEA, 0x00, 0x26, 0x0E, 0xF0, 0x00, 0x41, 0x9D, 0x42, 0x08, 0xBF, 0x96, 0x42, 0x44, 0xF1, 0xFD, 0x04, 0x04, 0xF5, +0x40, 0x74, 0x02, 0xD2, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0x1A, 0x65, 0xEB, 0x03, 0x05, 0x5B, 0x08, 0x4F, 0xEA, +0x32, 0x02, 0x4F, 0xF4, 0x80, 0x10, 0x4F, 0xF4, 0x00, 0x2C, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, +0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x0C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, +0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x5C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, 0x32, 0x02, 0xB6, 0xEB, +0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0x9C, 0x00, 0x5B, 0x08, 0x4F, 0xEA, +0x32, 0x02, 0xB6, 0xEB, 0x02, 0x0E, 0x75, 0xEB, 0x03, 0x0E, 0x22, 0xBF, 0xB6, 0x1A, 0x75, 0x46, 0x40, 0xEA, 0xDC, 0x00, +0x55, 0xEA, 0x06, 0x0E, 0x18, 0xD0, 0x4F, 0xEA, 0x05, 0x15, 0x45, 0xEA, 0x16, 0x75, 0x4F, 0xEA, 0x06, 0x16, 0x4F, 0xEA, +0xC3, 0x03, 0x43, 0xEA, 0x52, 0x73, 0x4F, 0xEA, 0xC2, 0x02, 0x5F, 0xEA, 0x1C, 0x1C, 0xC0, 0xD1, 0x11, 0xF4, 0x80, 0x1F, +0x0B, 0xD1, 0x41, 0xEA, 0x00, 0x01, 0x4F, 0xF0, 0x00, 0x00, 0x4F, 0xF0, 0x00, 0x4C, 0xB6, 0xE7, 0x11, 0xF4, 0x80, 0x1F, +0x04, 0xBF, 0x01, 0x43, 0x00, 0x20, 0xB4, 0xF1, 0xFD, 0x0C, 0x88, 0xBF, 0xBC, 0xF5, 0xE0, 0x6F, 0x3F, 0xF6, 0xAF, 0xAE, +0xB5, 0xEB, 0x03, 0x0C, 0x04, 0xBF, 0xB6, 0xEB, 0x02, 0x0C, 0x5F, 0xEA, 0x50, 0x0C, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xEB, +0x04, 0x51, 0x70, 0xBD, 0x0E, 0xF0, 0x00, 0x4E, 0x4E, 0xEA, 0x11, 0x31, 0x14, 0xEB, 0x5C, 0x04, 0xC2, 0xBF, 0xD4, 0xEB, +0x0C, 0x05, 0x41, 0xEA, 0x04, 0x51, 0x70, 0xBD, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xF0, 0x00, 0x0E, 0x01, 0x3C, 0x90, 0xE6, +0x45, 0xEA, 0x06, 0x0E, 0x8D, 0xE6, 0x0C, 0xEA, 0x13, 0x55, 0x94, 0xEA, 0x0C, 0x0F, 0x08, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, +0x3F, 0xF4, 0x3B, 0xAF, 0x94, 0xEA, 0x0C, 0x0F, 0x0A, 0xD1, 0x50, 0xEA, 0x01, 0x34, 0x7F, 0xF4, 0x34, 0xAF, 0x95, 0xEA, +0x0C, 0x0F, 0x7F, 0xF4, 0x25, 0xAF, 0x10, 0x46, 0x19, 0x46, 0x2C, 0xE7, 0x95, 0xEA, 0x0C, 0x0F, 0x06, 0xD1, 0x52, 0xEA, +0x03, 0x35, 0x3F, 0xF4, 0xFD, 0xAE, 0x10, 0x46, 0x19, 0x46, 0x22, 0xE7, 0x50, 0xEA, 0x41, 0x06, 0x18, 0xBF, 0x52, 0xEA, +0x43, 0x06, 0x7F, 0xF4, 0xC5, 0xAE, 0x50, 0xEA, 0x41, 0x04, 0x7F, 0xF4, 0x0D, 0xAF, 0x52, 0xEA, 0x43, 0x05, 0x7F, 0xF4, +0xEB, 0xAE, 0x12, 0xE7, 0x4F, 0xF0, 0xFF, 0x3C, 0x06, 0xE0, 0x00, 0xBF, 0x4F, 0xF0, 0x01, 0x0C, 0x02, 0xE0, 0x00, 0xBF, +0x4F, 0xF0, 0x01, 0x0C, 0x4D, 0xF8, 0x04, 0xCD, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x4F, 0xEA, 0x43, 0x0C, +0x18, 0xBF, 0x7F, 0xEA, 0x6C, 0x5C, 0x1B, 0xD0, 0x01, 0xB0, 0x50, 0xEA, 0x41, 0x0C, 0x0C, 0xBF, 0x52, 0xEA, 0x43, 0x0C, +0x91, 0xEA, 0x03, 0x0F, 0x02, 0xBF, 0x90, 0xEA, 0x02, 0x0F, 0x00, 0x20, 0x70, 0x47, 0x10, 0xF1, 0x00, 0x0F, 0x91, 0xEA, +0x03, 0x0F, 0x58, 0xBF, 0x99, 0x42, 0x08, 0xBF, 0x90, 0x42, 0x2C, 0xBF, 0xD8, 0x17, 0x6F, 0xEA, 0xE3, 0x70, 0x40, 0xF0, +0x01, 0x00, 0x70, 0x47, 0x4F, 0xEA, 0x41, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0x02, 0xD1, 0x50, 0xEA, 0x01, 0x3C, 0x07, 0xD1, +0x4F, 0xEA, 0x43, 0x0C, 0x7F, 0xEA, 0x6C, 0x5C, 0xD6, 0xD1, 0x52, 0xEA, 0x03, 0x3C, 0xD3, 0xD0, 0x5D, 0xF8, 0x04, 0x0B, +0x70, 0x47, 0x00, 0xBF, 0x84, 0x46, 0x10, 0x46, 0x62, 0x46, 0x8C, 0x46, 0x19, 0x46, 0x63, 0x46, 0x00, 0xE0, 0x00, 0xBF, +0x01, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x28, 0x48, 0xBF, 0x10, 0xF1, 0x00, 0x0F, 0x01, 0xBD, 0x4D, 0xF8, 0x08, 0xED, +0xFF, 0xF7, 0xF4, 0xFF, 0x0C, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, +0xFF, 0xF7, 0xEA, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, +0xFF, 0xF7, 0xE0, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, +0xFF, 0xF7, 0xCE, 0xFF, 0x94, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4D, 0xF8, 0x08, 0xED, +0xFF, 0xF7, 0xC4, 0xFF, 0x34, 0xBF, 0x01, 0x20, 0x00, 0x20, 0x5D, 0xF8, 0x08, 0xFB, 0x00, 0xBF, 0x4A, 0x00, 0x11, 0xD2, +0x12, 0xF5, 0x00, 0x12, 0x11, 0xD2, 0x0D, 0xD5, 0x6F, 0xF4, 0x78, 0x73, 0xB3, 0xEB, 0x62, 0x52, 0x0E, 0xD4, 0x4F, 0xEA, +0xC1, 0x23, 0x43, 0xF0, 0x00, 0x43, 0x43, 0xEA, 0x50, 0x53, 0x23, 0xFA, 0x02, 0xF0, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, +0x70, 0x47, 0x50, 0xEA, 0x01, 0x30, 0x02, 0xD1, 0x4F, 0xF0, 0xFF, 0x30, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, +0x4F, 0xEA, 0x41, 0x02, 0xB2, 0xF1, 0xE0, 0x43, 0x24, 0xBF, 0xB3, 0xF5, 0x00, 0x1C, 0xDC, 0xF1, 0xFE, 0x5C, 0x0D, 0xD9, +0x01, 0xF0, 0x00, 0x4C, 0x4F, 0xEA, 0xC0, 0x02, 0x4C, 0xEA, 0x50, 0x70, 0xB2, 0xF1, 0x00, 0x4F, 0x40, 0xEB, 0x83, 0x00, +0x08, 0xBF, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x11, 0xF0, 0x80, 0x4F, 0x21, 0xD1, 0x13, 0xF1, 0x38, 0x72, 0xBC, 0xBF, +0x01, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x41, 0xF4, 0x80, 0x11, 0x4F, 0xEA, 0x52, 0x52, 0xC2, 0xF1, 0x18, 0x02, 0xC2, 0xF1, +0x20, 0x0C, 0x10, 0xFA, 0x0C, 0xF3, 0x20, 0xFA, 0x02, 0xF0, 0x18, 0xBF, 0x40, 0xF0, 0x01, 0x00, 0x4F, 0xEA, 0xC1, 0x23, +0x4F, 0xEA, 0xD3, 0x23, 0x03, 0xFA, 0x0C, 0xFC, 0x40, 0xEA, 0x0C, 0x00, 0x23, 0xFA, 0x02, 0xF3, 0x4F, 0xEA, 0x43, 0x03, +0xCC, 0xE7, 0x7F, 0xEA, 0x62, 0x53, 0x07, 0xD1, 0x50, 0xEA, 0x01, 0x33, 0x1E, 0xBF, 0x4F, 0xF0, 0xFE, 0x40, 0x40, 0xF4, +0x40, 0x00, 0x70, 0x47, 0x01, 0xF0, 0x00, 0x40, 0x40, 0xF0, 0xFE, 0x40, 0x40, 0xF4, 0x00, 0x00, 0x70, 0x47, 0x00, 0xBF, +0x53, 0xB9, 0x4A, 0xB9, 0x00, 0x29, 0x08, 0xBF, 0x00, 0x28, 0x1C, 0xBF, 0x4F, 0xF0, 0xFF, 0x31, 0x4F, 0xF0, 0xFF, 0x30, +0x00, 0xF0, 0x6C, 0xB9, 0xAD, 0xF1, 0x08, 0x0C, 0x6D, 0xE9, 0x04, 0xCE, 0x00, 0xF0, 0x06, 0xF8, 0xDD, 0xF8, 0x04, 0xE0, +0xDD, 0xE9, 0x02, 0x23, 0x04, 0xB0, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x08, 0x9E, 0x0D, 0x46, 0x04, 0x46, 0x8E, 0x46, +0x00, 0x2B, 0x40, 0xF0, 0x82, 0x80, 0x8A, 0x42, 0x17, 0x46, 0x46, 0xD9, 0xB2, 0xFA, 0x82, 0xF2, 0x4A, 0xB1, 0xC2, 0xF1, +0x20, 0x01, 0x05, 0xFA, 0x02, 0xF3, 0x20, 0xFA, 0x01, 0xF1, 0x97, 0x40, 0x41, 0xEA, 0x03, 0x0E, 0x94, 0x40, 0x4F, 0xEA, +0x17, 0x48, 0x23, 0x0C, 0xBE, 0xFB, 0xF8, 0xFC, 0xB9, 0xB2, 0x08, 0xFB, 0x1C, 0xEE, 0x43, 0xEA, 0x0E, 0x43, 0x0C, 0xFB, +0x01, 0xF0, 0x98, 0x42, 0x0A, 0xD9, 0xFB, 0x18, 0x0C, 0xF1, 0xFF, 0x35, 0x80, 0xF0, 0x16, 0x81, 0x98, 0x42, 0x40, 0xF2, +0x13, 0x81, 0xAC, 0xF1, 0x02, 0x0C, 0x3B, 0x44, 0x1B, 0x1A, 0xA4, 0xB2, 0xB3, 0xFB, 0xF8, 0xF0, 0x08, 0xFB, 0x10, 0x33, +0x44, 0xEA, 0x03, 0x44, 0x00, 0xFB, 0x01, 0xF1, 0xA1, 0x42, 0x09, 0xD9, 0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x80, 0xF0, +0x01, 0x81, 0xA1, 0x42, 0x40, 0xF2, 0xFE, 0x80, 0x02, 0x38, 0x3C, 0x44, 0x64, 0x1A, 0x40, 0xEA, 0x0C, 0x40, 0x00, 0x21, +0x1E, 0xB1, 0xD4, 0x40, 0x00, 0x23, 0xC6, 0xE9, 0x00, 0x43, 0xBD, 0xE8, 0xF0, 0x87, 0x02, 0xB9, 0xFF, 0xDE, 0xB2, 0xFA, +0x82, 0xF2, 0x00, 0x2A, 0x4F, 0xD1, 0xCB, 0x1B, 0x4F, 0xEA, 0x17, 0x4E, 0x1F, 0xFA, 0x87, 0xF8, 0x01, 0x21, 0xB3, 0xFB, +0xFE, 0xFC, 0x25, 0x0C, 0x0E, 0xFB, 0x1C, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x08, 0xFB, 0x0C, 0xF3, 0xAB, 0x42, 0x07, 0xD9, +0x7D, 0x19, 0x0C, 0xF1, 0xFF, 0x30, 0x02, 0xD2, 0xAB, 0x42, 0x00, 0xF2, 0xE7, 0x80, 0x84, 0x46, 0xED, 0x1A, 0xA3, 0xB2, +0xB5, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x55, 0x43, 0xEA, 0x05, 0x44, 0x08, 0xFB, 0x00, 0xF8, 0xA0, 0x45, 0x07, 0xD9, +0x3C, 0x19, 0x00, 0xF1, 0xFF, 0x33, 0x02, 0xD2, 0xA0, 0x45, 0x00, 0xF2, 0xD7, 0x80, 0x18, 0x46, 0xA4, 0xEB, 0x08, 0x04, +0x40, 0xEA, 0x0C, 0x40, 0xC0, 0xE7, 0x8B, 0x42, 0x08, 0xD9, 0x00, 0x2E, 0x00, 0xF0, 0xAF, 0x80, 0x00, 0x21, 0xC6, 0xE9, +0x00, 0x05, 0x08, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xB3, 0xFA, 0x83, 0xF1, 0x00, 0x29, 0x4B, 0xD1, 0xAB, 0x42, 0x02, 0xD3, +0x82, 0x42, 0x00, 0xF2, 0xB7, 0x80, 0x84, 0x1A, 0x65, 0xEB, 0x03, 0x03, 0x01, 0x20, 0x9E, 0x46, 0x00, 0x2E, 0xAA, 0xD0, +0xC6, 0xE9, 0x00, 0x4E, 0xA7, 0xE7, 0xC2, 0xF1, 0x20, 0x0C, 0x01, 0xFA, 0x02, 0xF3, 0x97, 0x40, 0x20, 0xFA, 0x0C, 0xF0, +0x4F, 0xEA, 0x17, 0x4E, 0x21, 0xFA, 0x0C, 0xFC, 0x18, 0x43, 0xBC, 0xFB, 0xFE, 0xF1, 0x05, 0x0C, 0x0E, 0xFB, 0x11, 0xCC, +0x1F, 0xFA, 0x87, 0xF8, 0x45, 0xEA, 0x0C, 0x45, 0x01, 0xFB, 0x08, 0xF3, 0xAB, 0x42, 0x04, 0xFA, 0x02, 0xF4, 0x09, 0xD9, +0x7D, 0x19, 0x01, 0xF1, 0xFF, 0x3C, 0x80, 0xF0, 0x8B, 0x80, 0xAB, 0x42, 0x40, 0xF2, 0x88, 0x80, 0x02, 0x39, 0x3D, 0x44, +0xEB, 0x1A, 0x85, 0xB2, 0xB3, 0xFB, 0xFE, 0xF0, 0x0E, 0xFB, 0x10, 0x33, 0x45, 0xEA, 0x03, 0x45, 0x00, 0xFB, 0x08, 0xF3, +0xAB, 0x42, 0x07, 0xD9, 0x7D, 0x19, 0x00, 0xF1, 0xFF, 0x3C, 0x71, 0xD2, 0xAB, 0x42, 0x6F, 0xD9, 0x02, 0x38, 0x3D, 0x44, +0xEB, 0x1A, 0x40, 0xEA, 0x01, 0x41, 0x78, 0xE7, 0xC1, 0xF1, 0x20, 0x0C, 0x8B, 0x40, 0x22, 0xFA, 0x0C, 0xF7, 0x1F, 0x43, +0x20, 0xFA, 0x0C, 0xF4, 0x05, 0xFA, 0x01, 0xF3, 0x4F, 0xEA, 0x17, 0x4E, 0x25, 0xFA, 0x0C, 0xF5, 0x1C, 0x43, 0x23, 0x0C, +0xB5, 0xFB, 0xFE, 0xF9, 0x1F, 0xFA, 0x87, 0xF8, 0x0E, 0xFB, 0x19, 0x55, 0x43, 0xEA, 0x05, 0x45, 0x09, 0xFB, 0x08, 0xFA, +0xAA, 0x45, 0x02, 0xFA, 0x01, 0xF2, 0x00, 0xFA, 0x01, 0xF3, 0x08, 0xD9, 0x7D, 0x19, 0x09, 0xF1, 0xFF, 0x30, 0x47, 0xD2, +0xAA, 0x45, 0x45, 0xD9, 0xA9, 0xF1, 0x02, 0x09, 0x3D, 0x44, 0xA5, 0xEB, 0x0A, 0x05, 0xA4, 0xB2, 0xB5, 0xFB, 0xFE, 0xF0, +0x0E, 0xFB, 0x10, 0x55, 0x44, 0xEA, 0x05, 0x44, 0x00, 0xFB, 0x08, 0xF8, 0xA0, 0x45, 0x07, 0xD9, 0x3C, 0x19, 0x00, 0xF1, +0xFF, 0x35, 0x2D, 0xD2, 0xA0, 0x45, 0x2B, 0xD9, 0x02, 0x38, 0x3C, 0x44, 0x40, 0xEA, 0x09, 0x40, 0xA4, 0xEB, 0x08, 0x04, +0xA0, 0xFB, 0x02, 0x89, 0x4C, 0x45, 0xC6, 0x46, 0x4D, 0x46, 0x19, 0xD3, 0x16, 0xD0, 0x5E, 0xB1, 0xB3, 0xEB, 0x0E, 0x02, +0x64, 0xEB, 0x05, 0x04, 0x04, 0xFA, 0x0C, 0xFC, 0xCA, 0x40, 0x4C, 0xEA, 0x02, 0x02, 0xCC, 0x40, 0xC6, 0xE9, 0x00, 0x24, +0x00, 0x21, 0xBD, 0xE8, 0xF0, 0x87, 0x31, 0x46, 0x30, 0x46, 0x0E, 0xE7, 0xAC, 0x46, 0xED, 0xE6, 0x18, 0x46, 0x01, 0xE7, +0x43, 0x45, 0xE6, 0xD2, 0xB8, 0xEB, 0x02, 0x0E, 0x69, 0xEB, 0x07, 0x05, 0x01, 0x38, 0xE0, 0xE7, 0x28, 0x46, 0xD3, 0xE7, +0x60, 0x46, 0x8F, 0xE7, 0x81, 0x46, 0xBA, 0xE7, 0x61, 0x46, 0x77, 0xE7, 0x08, 0x46, 0x4B, 0xE7, 0xAC, 0xF1, 0x02, 0x0C, +0x3D, 0x44, 0x15, 0xE7, 0x02, 0x38, 0x3C, 0x44, 0x26, 0xE7, 0x00, 0xBF, 0x70, 0x47, 0x00, 0xBF, 0x00, 0x28, 0xB8, 0xBF, +0x40, 0x42, 0x70, 0x47, 0x03, 0x2A, 0x70, 0xB4, 0x12, 0xD9, 0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x0B, 0x46, +0x1E, 0xD1, 0x19, 0x46, 0x20, 0x46, 0x53, 0xF8, 0x04, 0x5B, 0x54, 0xF8, 0x04, 0x6B, 0xAE, 0x42, 0x16, 0xD1, 0x04, 0x3A, +0x03, 0x2A, 0x20, 0x46, 0x19, 0x46, 0xF2, 0xD8, 0x56, 0x1E, 0xA2, 0xB1, 0x01, 0x39, 0x44, 0x1E, 0x01, 0xE0, 0xC3, 0x18, +0x0C, 0xD0, 0x14, 0xF8, 0x01, 0x5F, 0x11, 0xF8, 0x01, 0x2F, 0x95, 0x42, 0xA6, 0xEB, 0x04, 0x03, 0xF5, 0xD0, 0xA8, 0x1A, +0x70, 0xBC, 0x70, 0x47, 0x56, 0x1E, 0xED, 0xE7, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x10, 0x46, 0xF6, 0xE7, 0x00, 0xBF, +0x84, 0x46, 0x41, 0xEA, 0x00, 0x03, 0x13, 0xF0, 0x03, 0x03, 0x6D, 0xD1, 0x40, 0x3A, 0x41, 0xD3, 0x51, 0xF8, 0x04, 0x3B, +0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, +0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, +0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, +0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, +0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, +0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, +0x40, 0xF8, 0x04, 0x3B, 0x40, 0x3A, 0xBD, 0xD2, 0x30, 0x32, 0x11, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, +0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, 0x51, 0xF8, 0x04, 0x3B, +0x40, 0xF8, 0x04, 0x3B, 0x10, 0x3A, 0xED, 0xD2, 0x0C, 0x32, 0x05, 0xD3, 0x51, 0xF8, 0x04, 0x3B, 0x40, 0xF8, 0x04, 0x3B, +0x04, 0x3A, 0xF9, 0xD2, 0x04, 0x32, 0x08, 0xD0, 0xD2, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, +0x01, 0xD3, 0x0B, 0x88, 0x03, 0x80, 0x60, 0x46, 0x70, 0x47, 0x00, 0xBF, 0x08, 0x2A, 0x13, 0xD3, 0x8B, 0x07, 0x8D, 0xD0, +0x10, 0xF0, 0x03, 0x03, 0x8A, 0xD0, 0xC3, 0xF1, 0x04, 0x03, 0xD2, 0x1A, 0xDB, 0x07, 0x1C, 0xBF, 0x11, 0xF8, 0x01, 0x3B, +0x00, 0xF8, 0x01, 0x3B, 0x80, 0xD3, 0x31, 0xF8, 0x02, 0x3B, 0x20, 0xF8, 0x02, 0x3B, 0x7B, 0xE7, 0x04, 0x3A, 0xD9, 0xD3, +0x01, 0x3A, 0x11, 0xF8, 0x01, 0x3B, 0x00, 0xF8, 0x01, 0x3B, 0xF9, 0xD2, 0x0B, 0x78, 0x03, 0x70, 0x4B, 0x78, 0x43, 0x70, +0x8B, 0x78, 0x83, 0x70, 0x60, 0x46, 0x70, 0x47, 0x88, 0x42, 0xF0, 0xB4, 0x0D, 0xD9, 0x8B, 0x18, 0x83, 0x42, 0x0A, 0xD9, +0x84, 0x18, 0x32, 0xB1, 0x22, 0x46, 0x13, 0xF8, 0x01, 0x4D, 0x02, 0xF8, 0x01, 0x4D, 0x99, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, +0x70, 0x47, 0x0F, 0x2A, 0x0E, 0xD8, 0x03, 0x46, 0x54, 0x1E, 0x00, 0x2A, 0xF7, 0xD0, 0x01, 0x34, 0x0C, 0x44, 0x01, 0x3B, +0x11, 0xF8, 0x01, 0x2B, 0x03, 0xF8, 0x01, 0x2F, 0xA1, 0x42, 0xF9, 0xD1, 0xF0, 0xBC, 0x70, 0x47, 0x40, 0xEA, 0x01, 0x03, +0x9B, 0x07, 0x3F, 0xD1, 0xA2, 0xF1, 0x10, 0x03, 0x23, 0xF0, 0x0F, 0x04, 0x01, 0xF1, 0x20, 0x07, 0x27, 0x44, 0x1B, 0x09, +0x01, 0xF1, 0x10, 0x04, 0x00, 0xF1, 0x10, 0x05, 0x54, 0xF8, 0x10, 0x6C, 0x45, 0xF8, 0x10, 0x6C, 0x54, 0xF8, 0x0C, 0x6C, +0x45, 0xF8, 0x0C, 0x6C, 0x54, 0xF8, 0x08, 0x6C, 0x45, 0xF8, 0x08, 0x6C, 0x54, 0xF8, 0x04, 0x6C, 0x45, 0xF8, 0x04, 0x6C, +0x10, 0x34, 0xBC, 0x42, 0x05, 0xF1, 0x10, 0x05, 0xEA, 0xD1, 0x01, 0x33, 0x12, 0xF0, 0x0C, 0x0F, 0x01, 0xEB, 0x03, 0x11, +0x02, 0xF0, 0x0F, 0x04, 0x00, 0xEB, 0x03, 0x13, 0x17, 0xD0, 0x04, 0x3C, 0x24, 0xF0, 0x03, 0x0C, 0xA5, 0x08, 0x9C, 0x44, +0x1C, 0x1F, 0x0E, 0x46, 0x56, 0xF8, 0x04, 0x7B, 0x44, 0xF8, 0x04, 0x7F, 0x64, 0x45, 0xF9, 0xD1, 0x6C, 0x1C, 0x03, 0xEB, +0x84, 0x03, 0x01, 0xEB, 0x84, 0x01, 0x02, 0xF0, 0x03, 0x02, 0xAD, 0xE7, 0x54, 0x1E, 0x03, 0x46, 0xAD, 0xE7, 0x22, 0x46, +0xA8, 0xE7, 0x00, 0xBF, 0x0B, 0x4B, 0x0C, 0x48, 0x19, 0x68, 0xD1, 0xE9, 0x2A, 0x23, 0x10, 0xB4, 0x0A, 0x4C, 0x00, 0xFB, +0x02, 0xF0, 0x04, 0xFB, 0x03, 0x00, 0xA2, 0xFB, 0x04, 0x34, 0x04, 0x44, 0x5A, 0x1C, 0x44, 0xF1, 0x00, 0x00, 0xC1, 0xE9, +0x2A, 0x20, 0x10, 0xBC, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x00, 0xBF, 0x80, 0x01, 0x17, 0x00, 0x2D, 0xF4, 0x51, 0x58, +0x2D, 0x7F, 0x95, 0x4C, 0x11, 0xF0, 0xFF, 0x01, 0x03, 0x46, 0x44, 0xD0, 0x82, 0x07, 0x32, 0xD1, 0x70, 0xB4, 0x04, 0x68, +0x41, 0xEA, 0x01, 0x26, 0x46, 0xEA, 0x06, 0x46, 0x86, 0xEA, 0x04, 0x05, 0xA5, 0xF1, 0x01, 0x33, 0xA4, 0xF1, 0x01, 0x32, +0x23, 0xEA, 0x05, 0x03, 0x22, 0xEA, 0x04, 0x02, 0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0x0F, 0xD1, 0x50, 0xF8, 0x04, 0x4F, +0x84, 0xEA, 0x06, 0x05, 0xA5, 0xF1, 0x01, 0x32, 0xA4, 0xF1, 0x01, 0x33, 0x22, 0xEA, 0x05, 0x02, 0x23, 0xEA, 0x04, 0x03, +0x13, 0x43, 0x13, 0xF0, 0x80, 0x3F, 0xEF, 0xD0, 0x03, 0x78, 0x23, 0xB9, 0x36, 0xE0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, +0x32, 0xD0, 0x99, 0x42, 0xF9, 0xD1, 0x30, 0xE0, 0x8A, 0x42, 0x11, 0xD0, 0x9A, 0x07, 0x18, 0x46, 0xCC, 0xD0, 0x18, 0x46, +0x13, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF5, 0xD1, 0x10, 0x46, 0x70, 0x47, 0x99, 0x07, 0x18, 0x46, 0x07, 0xD0, 0x18, 0x46, +0x01, 0x33, 0x02, 0x78, 0x00, 0x2A, 0xF7, 0xD1, 0x70, 0x47, 0x82, 0x07, 0xF7, 0xD1, 0x02, 0x68, 0xA2, 0xF1, 0x01, 0x33, +0x23, 0xEA, 0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0x08, 0xD1, 0x50, 0xF8, 0x04, 0x2F, 0xA2, 0xF1, 0x01, 0x33, 0x23, 0xEA, +0x02, 0x03, 0x13, 0xF0, 0x80, 0x3F, 0xF6, 0xD0, 0x03, 0x78, 0x00, 0x2B, 0xE8, 0xD0, 0x10, 0xF8, 0x01, 0x3F, 0x00, 0x2B, +0xFB, 0xD1, 0x70, 0x47, 0x18, 0x46, 0x70, 0xBC, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEA, 0x01, 0x02, 0x84, 0x46, 0x12, 0xF0, +0x03, 0x0F, 0x4F, 0xD1, 0x11, 0xF0, 0x03, 0x0F, 0x32, 0xD1, 0x4D, 0xF8, 0x04, 0x4D, 0x11, 0xF0, 0x04, 0x0F, 0x51, 0xF8, +0x04, 0x3B, 0x0B, 0xD0, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, 0x4C, 0xF8, 0x04, 0x3B, +0x51, 0xF8, 0x04, 0x3B, 0x16, 0xD1, 0x00, 0xBF, 0x51, 0xF8, 0x04, 0x4B, 0xA3, 0xF1, 0x01, 0x32, 0x9A, 0x43, 0x12, 0xF0, +0x80, 0x3F, 0xA4, 0xF1, 0x01, 0x32, 0x0B, 0xD1, 0x4C, 0xF8, 0x04, 0x3B, 0xA2, 0x43, 0x12, 0xF0, 0x80, 0x3F, 0x04, 0xBF, +0x51, 0xF8, 0x04, 0x3B, 0x4C, 0xF8, 0x04, 0x4B, 0xEA, 0xD0, 0x23, 0x46, 0x0C, 0xF8, 0x01, 0x3B, 0x13, 0xF0, 0xFF, 0x0F, +0x4F, 0xEA, 0x33, 0x23, 0xF8, 0xD1, 0x5D, 0xF8, 0x04, 0x4B, 0x70, 0x47, 0x11, 0xF0, 0x01, 0x0F, 0x06, 0xD0, 0x11, 0xF8, +0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0x08, 0xBF, 0x70, 0x47, 0x11, 0xF0, 0x02, 0x0F, 0xBF, 0xD0, 0x31, 0xF8, +0x02, 0x2B, 0x12, 0xF0, 0xFF, 0x0F, 0x16, 0xBF, 0x2C, 0xF8, 0x02, 0x2B, 0x8C, 0xF8, 0x00, 0x20, 0x12, 0xF4, 0x7F, 0x4F, +0xB3, 0xD1, 0x70, 0x47, 0x11, 0xF8, 0x01, 0x2B, 0x0C, 0xF8, 0x01, 0x2B, 0x00, 0x2A, 0xF9, 0xD1, 0x70, 0x47, 0x00, 0xBF, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xF8, 0x00, 0xF0, +0x6D, 0xE9, 0x02, 0x45, 0x20, 0xF0, 0x07, 0x01, 0x6F, 0xF0, 0x00, 0x0C, 0x10, 0xF0, 0x07, 0x04, 0x91, 0xF8, 0x20, 0xF0, +0x40, 0xF0, 0x49, 0x80, 0x4F, 0xF0, 0x00, 0x04, 0x6F, 0xF0, 0x07, 0x00, 0xD1, 0xE9, 0x00, 0x23, 0x91, 0xF8, 0x40, 0xF0, +0x00, 0xF1, 0x08, 0x00, 0x82, 0xFA, 0x4C, 0xF2, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, +0x4B, 0xBB, 0xD1, 0xE9, 0x02, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, +0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0xE3, 0xB9, 0xD1, 0xE9, 0x04, 0x23, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, +0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, 0x8C, 0xF3, 0x7B, 0xB9, 0xD1, 0xE9, 0x06, 0x23, 0x01, 0xF1, +0x20, 0x01, 0x82, 0xFA, 0x4C, 0xF2, 0x00, 0xF1, 0x08, 0x00, 0xA4, 0xFA, 0x8C, 0xF2, 0x83, 0xFA, 0x4C, 0xF3, 0xA2, 0xFA, +0x8C, 0xF3, 0x00, 0x2B, 0xC6, 0xD0, 0x00, 0x2A, 0x04, 0xBF, 0x04, 0x30, 0x1A, 0x46, 0x12, 0xBA, 0xB2, 0xFA, 0x82, 0xF2, +0xFD, 0xE8, 0x02, 0x45, 0x00, 0xEB, 0xD2, 0x00, 0x70, 0x47, 0xD1, 0xE9, 0x00, 0x23, 0x04, 0xF0, 0x03, 0x05, 0xC4, 0xF1, +0x00, 0x00, 0x4F, 0xEA, 0xC5, 0x05, 0x14, 0xF0, 0x04, 0x0F, 0x91, 0xF8, 0x40, 0xF0, 0x0C, 0xFA, 0x05, 0xF5, 0x62, 0xEA, +0x05, 0x02, 0x1C, 0xBF, 0x63, 0xEA, 0x05, 0x03, 0x62, 0x46, 0x4F, 0xF0, 0x00, 0x04, 0xA9, 0xE7, 0x9A, 0xB3, 0xF0, 0xB4, +0x40, 0xEA, 0x01, 0x05, 0xAD, 0x07, 0x04, 0x46, 0x03, 0x46, 0x08, 0x46, 0x28, 0xD0, 0x20, 0x78, 0x0E, 0x78, 0x86, 0x42, +0x29, 0xD1, 0x01, 0x2A, 0x2A, 0xD0, 0x25, 0x46, 0x50, 0xB1, 0x15, 0xF8, 0x01, 0x0F, 0x11, 0xF8, 0x01, 0x6F, 0xEB, 0x43, +0xB0, 0x42, 0x13, 0x44, 0x1D, 0xD1, 0xE3, 0x18, 0xF4, 0xD1, 0x18, 0x46, 0xF0, 0xBC, 0x70, 0x47, 0x07, 0x68, 0x1C, 0x46, +0x53, 0xF8, 0x04, 0x5B, 0xA5, 0xF1, 0x01, 0x36, 0xBD, 0x42, 0x01, 0x46, 0x26, 0xEA, 0x05, 0x06, 0x00, 0xF1, 0x04, 0x00, +0xDD, 0xD1, 0x04, 0x3A, 0x1C, 0x46, 0x01, 0x46, 0x0A, 0xD0, 0x16, 0xF0, 0x80, 0x3F, 0x07, 0xD1, 0x03, 0x2A, 0xE9, 0xD8, +0xD3, 0xE7, 0x10, 0x46, 0x70, 0x47, 0x80, 0x1B, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0x20, 0xF0, 0xBC, 0x70, 0x47, 0x00, 0xBF, +0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x6B, 0x5F, 0x73, 0x74, +0x61, 0x72, 0x74, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x6D, 0x65, 0x6D, 0x20, 0x6F, 0x76, 0x65, 0x72, 0x6C, 0x61, 0x70, 0x73, 0x3A, 0x20, 0x73, 0x74, +0x6B, 0x5F, 0x65, 0x6E, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x61, 0x73, 0x65, 0x3D, +0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x64, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, +0x6D, 0x61, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, +0x08, 0x12, 0xC7, 0x11, 0x10, 0x14, 0x08, 0x12, 0x3C, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x45, 0x11, +0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, 0x08, 0x12, 0x04, 0x11, +0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, +0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, +0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x86, 0x11, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, +0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0xC3, 0x10, 0x04, 0x11, 0xC2, 0x10, 0x08, 0x12, 0x04, 0x11, +0x78, 0x00, 0x8A, 0x12, 0x07, 0x12, 0x0C, 0x13, 0x08, 0x12, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, +0x07, 0x12, 0x86, 0x11, 0x04, 0x11, 0xC2, 0x10, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x0C, 0x13, +0x04, 0x11, 0x03, 0x11, 0x04, 0x11, 0x04, 0x11, 0x78, 0x00, 0x8A, 0x12, 0x8A, 0x12, 0x86, 0x11, 0x04, 0x11, 0x03, 0x11, +0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x3D, 0x25, 0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x3D, 0x25, +0x64, 0x20, 0x66, 0x72, 0x65, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x74, 0x79, 0x70, 0x65, 0x3D, +0x25, 0x64, 0x20, 0x73, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x63, 0x68, 0x61, 0x6E, 0x3A, +0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x62, 0x61, 0x6E, 0x64, 0x20, +0x25, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x3C, 0x20, 0x50, +0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x28, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x61, 0x6A, +0x6F, 0x72, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x2B, 0x20, +0x32, 0x29, 0x20, 0x2A, 0x20, 0x31, 0x30, 0x20, 0x2B, 0x20, 0x6D, 0x64, 0x6D, 0x5F, 0x6D, 0x69, 0x6E, 0x6F, 0x72, 0x5F, +0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x58, +0x5F, 0x4D, 0x44, 0x4D, 0x5F, 0x56, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x72, 0x61, +0x64, 0x69, 0x6F, 0x20, 0x25, 0x64, 0x20, 0x64, 0x6F, 0x65, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, +0x74, 0x0A, 0x00, 0x00, 0x9D, 0x87, 0x25, 0x73, 0x3A, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x61, +0x6D, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x2C, 0x20, 0x64, 0x6F, 0x20, 0x6E, 0x6F, 0x74, 0x68, 0x69, +0x6E, 0x67, 0x0A, 0x00, 0x9B, 0x25, 0x73, 0x20, 0x4D, 0x41, 0x43, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x21, 0x3D, +0x20, 0x49, 0x44, 0x4C, 0x45, 0x0A, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x68, 0x77, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, +0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x73, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, +0x6E, 0x65, 0x6C, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x67, 0x65, 0x74, 0x5F, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x00, +0x70, 0x68, 0x79, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, +0x0E, 0xFF, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, 0x12, 0xFD, 0x0C, 0x03, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, +0x14, 0xFD, 0x0A, 0x03, 0x0B, 0xFC, 0x11, 0xFF, 0x0D, 0x01, 0x0E, 0xFF, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFE, +0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x12, 0xFE, 0x0C, 0x02, 0x0D, 0xFE, 0x13, 0xFE, 0x0B, 0x02, +0x0C, 0xFD, 0x1F, 0x00, 0x0C, 0x02, 0x0D, 0xFE, 0x11, 0x00, 0x0D, 0x00, 0x0E, 0xFF, 0x13, 0x03, 0x0B, 0x03, 0x0C, 0xFD, +0x14, 0xFC, 0x0A, 0x04, 0x0B, 0xFC, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x11, 0xFE, 0x0D, 0x02, 0x0E, 0xFF, 0x13, 0xFE, +0x0B, 0x02, 0x0C, 0xFD, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x12, 0xFD, 0x0C, 0x03, +0x0D, 0xFE, 0x12, 0xFF, 0x0C, 0x01, 0x0D, 0xFE, 0x13, 0xFD, 0x0B, 0x03, 0x0C, 0xFD, 0x13, 0xFE, 0x0B, 0x02, 0x0C, 0xFD, +0x1F, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x74, 0x63, 0x5F, 0x73, 0x70, 0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x00, 0x00, 0x00, +0x18, 0x10, 0x0C, 0x08, 0x07, 0x06, 0x8B, 0x05, 0x89, 0x04, 0x87, 0x03, 0x85, 0x02, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, +0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x32, 0x2E, 0x34, +0x67, 0x28, 0x70, 0x61, 0x5F, 0x64, 0x72, 0x76, 0x5F, 0x69, 0x62, 0x69, 0x74, 0x29, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, +0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, +0x4F, 0x4E, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, 0x66, 0x65, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, +0x66, 0x69, 0x6E, 0x74, 0x66, 0x20, 0x52, 0x58, 0x4F, 0x46, 0x46, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x65, 0x74, 0x65, +0x63, 0x74, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x62, 0x79, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x20, +0x69, 0x6E, 0x20, 0x63, 0x61, 0x6C, 0x5F, 0x6C, 0x73, 0x20, 0x64, 0x65, 0x74, 0x20, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x73, 0x6C, 0x6F, 0x70, 0x65, 0x20, 0x74, 0x6F, 0x6F, 0x20, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, +0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x66, 0x69, +0x74, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x6F, 0x65, 0x66, 0x5F, 0x49, 0x51, 0x20, +0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2E, 0x00, 0x25, 0x30, 0x33, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, +0x73, 0x64, 0x6D, 0x20, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, +0x66, 0x72, 0x65, 0x71, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x20, +0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x65, 0x6E, +0x20, 0x72, 0x65, 0x67, 0x20, 0x69, 0x73, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, +0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6E, 0x21, 0x0D, 0x0A, 0x00, 0x66, 0x69, 0x74, 0x2D, +0x69, 0x6E, 0x2D, 0x49, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, +0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x66, 0x69, 0x74, 0x2D, 0x69, 0x6E, 0x2D, 0x51, 0x20, 0x25, 0x78, 0x3A, 0x20, 0x5B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, +0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x3B, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x5D, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x67, 0x61, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x3A, 0x20, 0x63, 0x61, 0x6C, 0x49, 0x20, 0x25, +0x78, 0x2C, 0x20, 0x63, 0x61, 0x6C, 0x51, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x20, 0x64, +0x63, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x20, 0x65, 0x6E, 0x64, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x61, 0x6C, 0x5F, +0x63, 0x66, 0x67, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x61, 0x6C, 0x70, 0x68, 0x61, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, +0x70, 0x6C, 0x6C, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x63, 0x6B, 0x3A, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, 0x20, 0x6F, 0x66, 0x66, +0x0D, 0x0A, 0x00, 0x00, 0x20, 0x2A, 0x20, 0x63, 0x61, 0x6C, 0x20, 0x74, 0x69, 0x61, 0x5F, 0x69, 0x71, 0x3A, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, 0x64, +0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, +0x20, 0x20, 0x49, 0x69, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x69, +0x31, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x31, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x20, 0x61, 0x64, 0x6A, +0x49, 0x69, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x64, 0x6A, 0x49, 0x71, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x2D, 0x3E, 0x20, 0x49, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x49, 0x71, 0x30, 0x3D, 0x25, +0x64, 0x2C, 0x20, 0x56, 0x69, 0x30, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x56, 0x71, 0x30, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x2A, 0x6C, 0x6E, 0x61, 0x5F, 0x76, 0x63, 0x6D, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6C, 0x6E, +0x61, 0x5F, 0x76, 0x63, 0x6D, 0x6E, 0x3D, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, +0x67, 0x61, 0x69, 0x6E, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x3B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x66, 0x72, 0x66, +0x20, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, +0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x69, +0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x73, 0x66, 0x74, 0x20, 0x64, 0x69, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x73, 0x66, 0x74, 0x72, 0x73, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x6F, 0x61, 0x64, +0x5F, 0x76, 0x61, 0x6C, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x73, +0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x68, 0x6F, 0x73, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x5F, 0x64, 0x6D, 0x61, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x20, 0x21, 0x3D, +0x20, 0x30, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, +0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, +0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x64, +0x73, 0x74, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, +0x6D, 0x73, 0x67, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x5F, 0x6D, 0x73, 0x67, +0x5F, 0x62, 0x75, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x69, 0x70, 0x63, 0x5F, 0x65, 0x6D, 0x62, 0x5F, +0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x66, 0x77, 0x64, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, +0x6D, 0x73, 0x67, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x73, 0x72, 0x63, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x2C, 0x64, 0x73, +0x74, 0x69, 0x64, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x69, +0x70, 0x63, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, +0x20, 0x75, 0x73, 0x62, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x25, 0x64, 0x2C, +0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6B, 0x6D, 0x73, 0x67, 0x5F, 0x73, 0x72, 0x63, 0x2D, 0x3E, 0x70, 0x61, +0x72, 0x61, 0x6D, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x6D, 0x73, +0x67, 0x2D, 0x3E, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x29, 0x00, 0x00, 0x00, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6D, 0x73, 0x67, +0x20, 0x63, 0x66, 0x67, 0x20, 0x74, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x68, 0x61, 0x73, 0x20, 0x6E, 0x6F, 0x20, +0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x3A, +0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x54, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x68, 0x6F, +0x73, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x70, 0x6D, 0x69, 0x63, 0x20, 0x67, 0x70, 0x69, 0x6F, 0x0A, 0x00, 0x00, +0x77, 0x6B, 0x62, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x50, 0x4D, 0x49, 0x43, 0x5F, 0x45, 0x52, 0x52, +0x49, 0x52, 0x51, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x5F, +0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x49, 0x50, 0x43, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x43, 0x48, 0x41, 0x4E, 0x4E, 0x45, +0x4C, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x23, 0x20, 0x3D, 0x25, 0x64, 0x20, +0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x6C, +0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, +0x20, 0x31, 0x00, 0x00, 0x73, 0x74, 0x61, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x63, 0x6F, 0x6E, +0x6E, 0x5F, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x6D, 0x20, +0x73, 0x74, 0x61, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x74, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, +0x72, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x31, 0x0A, 0x00, +0x63, 0x6C, 0x65, 0x61, 0x72, 0x0A, 0x00, 0x00, 0x73, 0x74, 0x61, 0x74, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x0A, 0x00, 0x00, +0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x73, 0x74, 0x61, +0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, +0x41, 0x58, 0x00, 0x00, 0x73, 0x74, 0x61, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, 0x64, 0x0A, 0x00, +0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x74, 0x6D, 0x70, 0x2D, 0x3E, 0x68, 0x6F, 0x73, 0x74, 0x2E, 0x66, 0x6C, 0x61, +0x67, 0x73, 0x20, 0x26, 0x20, 0x54, 0x58, 0x55, 0x5F, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x54, 0x52, 0x59, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xD9, 0x67, 0x12, 0x00, 0xF9, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, +0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, +0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, +0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, +0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, +0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, +0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, +0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x49, 0x6E, +0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, +0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x67, 0x72, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x53, +0x75, 0x62, 0x70, 0x6F, 0x6F, 0x6C, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x53, 0x77, 0x45, 0x72, +0x3A, 0x4E, 0x6F, 0x53, 0x69, 0x7A, 0x65, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x0D, 0x00, +0x67, 0x65, 0x74, 0x5F, 0x6E, 0x65, 0x78, 0x74, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x61, 0x64, 0x64, 0x72, +0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, +0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x70, 0x61, 0x74, 0x74, +0x65, 0x72, 0x6E, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, +0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x53, 0x77, 0x45, 0x72, 0x3A, 0x41, 0x6C, 0x6C, +0x63, 0x45, 0x72, 0x72, 0x50, 0x74, 0x72, 0x6E, 0x20, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, +0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x5F, 0x6E, 0x61, 0x74, 0x69, +0x76, 0x65, 0x5F, 0x70, 0x6F, 0x6F, 0x6C, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, +0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, +0x64, 0x65, 0x63, 0x72, 0x5F, 0x6E, 0x75, 0x6D, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, +0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, +0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, +0x61, 0x6C, 0x69, 0x64, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, +0x25, 0x78, 0x0A, 0x00, 0x6E, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x69, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x00, 0x00, +0x67, 0x65, 0x74, 0x5F, 0x75, 0x73, 0x65, 0x72, 0x5F, 0x69, 0x64, 0x3A, 0x20, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, +0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, +0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x65, 0x73, 0x63, 0x0D, 0x0A, 0x00, 0x00, +0x70, 0x61, 0x72, 0x61, 0x6D, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6E, 0x74, 0x20, +0x65, 0x72, 0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x69, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6E, 0x75, 0x6D, 0x3D, 0x25, 0x64, +0x2C, 0x20, 0x72, 0x78, 0x64, 0x65, 0x73, 0x63, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x61, 0x63, 0x3E, 0x3D, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x61, 0x63, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x20, +0x2B, 0x20, 0x31, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, +0x4C, 0x4C, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x63, 0x72, 0x63, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x69, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x73, 0x6F, 0x66, 0x74, +0x77, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x20, 0x69, 0x6E, 0x74, 0x20, 0x25, 0x78, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x20, 0x73, 0x74, +0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x68, 0x6F, 0x73, +0x74, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x68, 0x62, 0x32, 0x73, 0x64, 0x69, 0x6F, +0x20, 0x74, 0x78, 0x20, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x53, 0x44, 0x49, 0x4F, 0x32, 0x41, 0x48, 0x42, +0x5F, 0x4C, 0x4C, 0x53, 0x54, 0x5F, 0x48, 0x44, 0x52, 0x5F, 0x45, 0x52, 0x52, 0x0D, 0x0A, 0x00, 0x73, 0x64, 0x69, 0x6F, +0x20, 0x65, 0x72, 0x72, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3D, 0x25, 0x78, 0x2C, 0x30, 0x78, 0x34, 0x35, 0x3D, +0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x67, 0x72, 0x78, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, +0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x63, 0x75, 0x73, 0x65, 0x64, 0x3D, +0x25, 0x64, 0x2C, 0x20, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x78, 0x63, 0x6D, +0x73, 0x67, 0x75, 0x73, 0x65, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x6D, 0x73, 0x67, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x3D, +0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, +0x6C, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6F, 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x0D, 0x0A, 0x00, +0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x70, 0x6B, 0x74, 0x21, 0x0D, 0x0A, 0x00, 0x00, +0x65, 0x72, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x64, 0x73, 0x63, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x6F, 0x70, 0x65, 0x6E, +0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x55, 0x4C, 0x50, 0x49, 0x20, 0x63, 0x6C, 0x6B, 0x20, 0x64, 0x65, 0x74, +0x65, 0x63, 0x74, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x75, 0x73, 0x62, +0x20, 0x75, 0x6C, 0x70, 0x69, 0x20, 0x63, 0x6C, 0x6B, 0x0D, 0x0A, 0x00, 0x77, 0x61, 0x69, 0x74, 0x20, 0x63, 0x66, 0x67, +0x0A, 0x00, 0x00, 0x00, 0x46, 0x49, 0x46, 0x4F, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x3A, 0x20, 0x6F, 0x76, 0x65, 0x72, +0x66, 0x6C, 0x6F, 0x77, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x69, +0x7A, 0x65, 0x20, 0x69, 0x73, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x54, 0x6F, 0x74, 0x61, 0x6C, 0x20, 0x52, 0x41, 0x4D, 0x20, +0x69, 0x73, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E, +0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, +0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x64, 0x69, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x00, +0x45, 0x50, 0x30, 0x20, 0x53, 0x45, 0x54, 0x55, 0x50, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x2C, 0x20, 0x77, 0x4C, 0x65, +0x6E, 0x67, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, +0x6F, 0x77, 0x6E, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6F, 0x72, 0x3A, 0x20, 0x25, 0x64, 0x00, 0x00, +0x45, 0x70, 0x30, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x65, 0x72, 0x72, 0x20, +0x25, 0x75, 0x2D, 0x25, 0x75, 0x00, 0x00, 0x00, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, +0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x0D, 0x0A, 0x00, 0x65, 0x78, 0x69, 0x74, +0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, +0x75, 0x70, 0x20, 0x75, 0x73, 0x62, 0x0A, 0x00, 0x69, 0x72, 0x71, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x77, 0x6C, 0x61, 0x6E, 0x5F, 0x75, 0x73, 0x62, 0x5F, 0x73, 0x75, 0x73, 0x70, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, +0x52, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x64, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, +0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x77, 0x6D, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, +0x64, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, +0x20, 0x6D, 0x73, 0x67, 0x20, 0x65, 0x6C, 0x65, 0x6D, 0x0D, 0x0A, 0x00, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, +0x20, 0x25, 0x58, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x65, 0x6E, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x58, 0x20, 0x25, +0x64, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x65, 0x72, +0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x65, +0x72, 0x72, 0x23, 0x23, 0x23, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x62, 0x20, 0x77, 0x6C, 0x61, 0x6E, +0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x65, 0x72, 0x72, 0x21, 0x21, 0x21, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x65, 0x6E, 0x20, 0x72, 0x65, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x65, 0x72, 0x72, 0x21, 0x21, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x20, 0x25, 0x64, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02, 0x20, 0x00, +0x01, 0x01, 0x00, 0xA0, 0xFA, 0x09, 0x04, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, +0x00, 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00, 0x05, 0x0F, 0x0C, 0x00, 0x01, 0x07, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, +0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x9C, 0xA6, 0x00, 0x88, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, +0x0A, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, +0x0A, 0x03, 0x77, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x10, 0x03, 0x61, 0x00, 0x69, 0x00, 0x63, 0x00, +0x73, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x69, 0x00, 0x12, 0x03, 0x41, 0x00, 0x49, 0x00, 0x43, 0x00, 0x20, 0x00, 0x57, 0x00, +0x6C, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x12, 0x03, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x30, 0x00, +0x32, 0x00, 0x32, 0x00, 0x37, 0x00, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x75, 0x73, 0x62, 0x5F, 0x77, 0x6C, 0x61, 0x6E, +0x5F, 0x72, 0x78, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x6E, +0x69, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, +0x77, 0x66, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x75, 0x73, 0x62, 0x20, 0x73, 0x74, 0x61, +0x72, 0x74, 0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x68, 0x6F, 0x73, +0x74, 0x5F, 0x69, 0x66, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x73, 0x69, 0x7A, +0x65, 0x00, 0x00, 0x00, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x64, 0x73, 0x63, 0x72, 0x20, 0x75, +0x73, 0x65, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x23, 0x77, 0x66, 0x3A, 0x25, 0x58, 0x0A, 0x00, +0x23, 0x77, 0x65, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, +0x65, 0x72, 0x72, 0x21, 0x20, 0x77, 0x64, 0x20, 0x6E, 0x6F, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, +0x77, 0x64, 0x20, 0x72, 0x78, 0x20, 0x6D, 0x61, 0x78, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, +0x68, 0x6F, 0x73, 0x74, 0x5F, 0x72, 0x65, 0x61, 0x64, 0x79, 0x0A, 0x00, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, +0x61, 0x20, 0x72, 0x65, 0x63, 0x76, 0x20, 0x72, 0x65, 0x74, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, +0x20, 0x6E, 0x6F, 0x20, 0x77, 0x6C, 0x61, 0x6E, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x69, 0x70, 0x63, +0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x69, 0x70, 0x63, 0x20, 0x68, 0x6F, 0x73, +0x74, 0x20, 0x72, 0x78, 0x3A, 0x20, 0x6E, 0x6F, 0x62, 0x75, 0x66, 0x66, 0x2C, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x3D, +0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x54, 0x4F, 0x5F, 0x4B, 0x45, +0x59, 0x28, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, 0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x20, +0x2D, 0x20, 0x31, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x6B, 0x65, +0x79, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, +0x6C, 0x70, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x61, 0x63, 0x74, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, +0x6D, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, +0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, +0x73, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x6B, 0x65, 0x75, 0x70, 0x20, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, +0x67, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, +0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x6C, 0x61, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x6D, 0x73, 0x2C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, +0x6F, 0x77, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x0D, 0x0A, 0x00, +0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x6C, 0x6C, 0x6F, 0x77, 0x65, 0x64, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x4F, 0x4E, 0x54, 0x52, 0x4F, 0x4C, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x78, +0x50, 0x53, 0x52, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, +0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x20, 0x20, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x50, +0x52, 0x49, 0x4D, 0x41, 0x53, 0x4B, 0x3D, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, +0x3D, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x0A, 0x57, 0x72, 0x6F, 0x6E, 0x67, 0x20, 0x50, 0x53, 0x50, 0x21, 0x00, +0x0A, 0x44, 0x75, 0x6D, 0x70, 0x4D, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x0A, 0x5B, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x3A, +0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x25, 0x2D, 0x34, 0x64, 0x3A, 0x20, +0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x50, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, +0x0A, 0x4C, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x43, 0x20, 0x20, 0x20, 0x3A, 0x20, +0x25, 0x30, 0x38, 0x58, 0x0A, 0x78, 0x50, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x53, 0x50, +0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x4D, 0x53, 0x50, 0x20, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, +0x00, 0x00, 0x00, 0x00, 0x0A, 0x43, 0x50, 0x55, 0x49, 0x44, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x49, 0x43, 0x53, +0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x56, 0x54, 0x4F, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, +0x0A, 0x41, 0x49, 0x52, 0x43, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x53, 0x48, 0x43, +0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x43, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, +0x0A, 0x48, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x44, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, +0x25, 0x30, 0x38, 0x58, 0x0A, 0x41, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, +0x0A, 0x4D, 0x4D, 0x46, 0x53, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x41, 0x43, 0x43, 0x56, +0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, 0x41, 0x43, 0x43, 0x56, 0x49, 0x4F, 0x4C, 0x20, 0x3A, 0x25, 0x64, +0x0A, 0x20, 0x20, 0x4D, 0x55, 0x4E, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x4D, 0x53, 0x54, 0x4B, +0x45, 0x52, 0x52, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x4D, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, +0x3A, 0x25, 0x64, 0x09, 0x4D, 0x4D, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, +0x0A, 0x4D, 0x4D, 0x46, 0x41, 0x52, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x42, 0x46, 0x53, +0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x20, 0x20, 0x49, 0x42, 0x55, 0x53, 0x45, 0x52, 0x52, 0x20, 0x20, +0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x0A, 0x20, +0x20, 0x49, 0x4D, 0x50, 0x52, 0x45, 0x43, 0x49, 0x53, 0x45, 0x52, 0x52, 0x3A, 0x25, 0x64, 0x09, 0x55, 0x4E, 0x53, 0x54, +0x4B, 0x45, 0x52, 0x52, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x53, 0x54, 0x4B, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, +0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4C, 0x53, 0x50, 0x45, 0x52, 0x52, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, +0x20, 0x42, 0x46, 0x41, 0x52, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x42, 0x46, 0x41, +0x52, 0x20, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x55, 0x46, 0x53, 0x52, 0x20, 0x3A, 0x20, +0x25, 0x30, 0x34, 0x58, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x44, 0x45, 0x46, 0x49, 0x4E, 0x53, 0x54, 0x52, 0x3A, 0x25, 0x64, +0x09, 0x49, 0x4E, 0x56, 0x53, 0x54, 0x41, 0x54, 0x45, 0x20, 0x3A, 0x25, 0x64, 0x0A, 0x20, 0x20, 0x49, 0x4E, 0x56, 0x50, +0x43, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x4E, 0x4F, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3A, +0x25, 0x64, 0x0A, 0x20, 0x20, 0x55, 0x4E, 0x41, 0x4C, 0x49, 0x47, 0x4E, 0x45, 0x44, 0x20, 0x3A, 0x25, 0x64, 0x09, 0x44, +0x49, 0x56, 0x42, 0x59, 0x5A, 0x45, 0x52, 0x4F, 0x3A, 0x25, 0x64, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, +0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x55, 0x73, 0x65, 0x72, +0x00, 0x00, 0x00, 0x00, 0x0A, 0x50, 0x72, 0x69, 0x76, 0x20, 0x3A, 0x20, 0x50, 0x72, 0x69, 0x76, 0x69, 0x6C, 0x65, 0x67, +0x65, 0x64, 0x00, 0x00, 0x0A, 0x4D, 0x6F, 0x64, 0x65, 0x20, 0x3A, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, +0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, 0x50, 0x53, 0x50, 0x00, 0x0A, 0x53, 0x74, 0x61, 0x63, 0x6B, 0x3A, 0x20, +0x4D, 0x53, 0x50, 0x00, 0x0A, 0x43, 0x4E, 0x54, 0x52, 0x4C, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x50, 0x4D, 0x41, +0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x0A, 0x46, 0x4D, 0x41, 0x53, 0x4B, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, +0x0A, 0x42, 0x41, 0x53, 0x45, 0x50, 0x3A, 0x20, 0x25, 0x30, 0x38, 0x58, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x44, 0x75, 0x6D, +0x70, 0x50, 0x53, 0x50, 0x3A, 0x00, 0x00, 0x00, 0x50, 0x61, 0x6E, 0x69, 0x63, 0x2E, 0x2E, 0x2E, 0x0A, 0x00, 0x00, 0x00, +0x0A, 0x2B, 0x2B, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, +0x72, 0x20, 0x2B, 0x2B, 0x0A, 0x0A, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x54, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x00, 0x00, 0x00, +0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, +0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, +0x48, 0x61, 0x72, 0x64, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x78, +0x74, 0x3A, 0x00, 0x00, 0x0A, 0x0A, 0x2D, 0x2D, 0x20, 0x43, 0x4D, 0x34, 0x20, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x48, +0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x2D, 0x2D, 0x0A, 0x0A, 0x00, 0x9A, 0x25, 0x73, 0x20, 0x2D, 0x20, 0x62, 0x75, +0x69, 0x6C, 0x64, 0x3A, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x25, +0x64, 0x2C, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x65, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x64, 0x2C, 0x00, 0x00, 0x74, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x74, 0x20, +0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x61, 0x73, 0x73, +0x3A, 0x20, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, +0x68, 0x77, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, +0x74, 0x69, 0x6D, 0x65, 0x20, 0x2D, 0x20, 0x67, 0x5F, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6E, +0x67, 0x73, 0x2E, 0x70, 0x77, 0x72, 0x5F, 0x6F, 0x70, 0x65, 0x6E, 0x5F, 0x73, 0x79, 0x73, 0x64, 0x65, 0x6C, 0x61, 0x79, +0x29, 0x00, 0x00, 0x00, 0x73, 0x6C, 0x70, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x62, 0x74, 0x0A, 0x00, +0x6C, 0x70, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x67, 0x6E, 0x6F, 0x72, 0x65, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, +0x77, 0x2C, 0x20, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x68, 0x77, +0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, +0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x00, 0x00, 0x00, 0x00, +0x77, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x77, 0x6E, 0x78, 0x6C, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5F, +0x65, 0x76, 0x74, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, 0x30, 0x5D, 0x20, +0x26, 0x26, 0x20, 0x74, 0x78, 0x5F, 0x68, 0x77, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5B, +0x30, 0x5D, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, +0x74, 0x78, 0x6C, 0x20, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x6C, 0x65, 0x6E, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x74, 0x78, 0x6C, 0x5F, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, +0x63, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, +0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, 0x6E, 0x65, 0x78, 0x74, 0x64, 0x65, 0x73, 0x63, +0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, +0x2D, 0x3E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x41, 0x47, 0x47, 0x5F, 0x42, 0x41, 0x5F, 0x52, 0x45, +0x43, 0x45, 0x49, 0x56, 0x45, 0x44, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x62, 0x63, 0x6E, +0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, +0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x33, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, +0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, +0x5F, 0x61, 0x63, 0x5F, 0x32, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, +0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x31, 0x5F, 0x73, 0x74, +0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, +0x63, 0x5F, 0x74, 0x78, 0x5F, 0x61, 0x63, 0x5F, 0x30, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, +0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x78, 0x5F, 0x68, 0x69, 0x5F, +0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x00, 0x00, 0x00, +0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5F, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6F, 0x72, 0x79, 0x20, 0x3C, 0x20, 0x28, 0x4E, +0x58, 0x5F, 0x54, 0x58, 0x51, 0x5F, 0x43, 0x4E, 0x54, 0x2B, 0x32, 0x29, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x21, +0x21, 0x21, 0x20, 0x74, 0x78, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, +0x20, 0x66, 0x6F, 0x72, 0x20, 0x75, 0x73, 0x62, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x20, 0x66, 0x6C, 0x75, 0x73, +0x68, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x63, 0x66, 0x6D, 0x73, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x73, 0x6E, 0x3D, 0x25, 0x64, 0x2C, +0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, +0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x5F, +0x68, 0x77, 0x20, 0x3E, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, +0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x67, +0x65, 0x74, 0x28, 0x29, 0x20, 0x26, 0x20, 0x65, 0x76, 0x74, 0x5F, 0x62, 0x69, 0x74, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, +0x73, 0x63, 0x5F, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, +0x62, 0x75, 0x67, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x64, 0x69, 0x6F, 0x20, 0x74, 0x61, 0x69, 0x6C, 0x20, 0x65, 0x72, +0x72, 0x6F, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x00, 0x00, 0x28, 0x74, 0x68, 0x64, 0x2D, 0x3E, 0x64, 0x61, +0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, 0x20, 0x26, 0x20, 0x30, 0x78, 0x30, 0x31, 0x29, 0x20, 0x3D, +0x3D, 0x20, 0x30, 0x00, 0x62, 0x61, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x48, 0x59, 0x5F, 0x42, 0x41, 0x4E, 0x44, +0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, +0x6F, 0x72, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x62, 0x75, 0x66, +0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, +0x4C, 0x4C, 0x00, 0x00, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, 0x65, 0x77, 0x20, 0x21, 0x3D, 0x20, +0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x70, 0x69, 0x63, 0x6B, +0x28, 0x26, 0x74, 0x78, 0x6C, 0x69, 0x73, 0x74, 0x2D, 0x3E, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x73, +0x29, 0x20, 0x3D, 0x3D, 0x20, 0x26, 0x61, 0x67, 0x67, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, +0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6E, +0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, +0x6F, 0x64, 0x20, 0x3E, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, 0x48, +0x54, 0x5F, 0x44, 0x55, 0x50, 0x5F, 0x4F, 0x46, 0x44, 0x4D, 0x00, 0x00, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3E, 0x20, +0x30, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x2A, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x34, 0x29, 0x00, 0x00, 0x00, +0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x39, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, +0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x31, 0x00, 0x00, 0x00, 0x69, 0x73, 0x5F, 0x6D, 0x70, 0x64, 0x75, 0x5F, +0x66, 0x69, 0x72, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, 0x21, 0x69, 0x73, 0x5F, +0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x61, 0x73, 0x74, 0x28, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x29, 0x00, 0x00, 0x00, +0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x70, 0x72, 0x65, 0x76, 0x20, 0x3D, 0x3D, 0x20, 0x61, 0x67, 0x67, 0x5F, 0x64, +0x65, 0x73, 0x63, 0x5F, 0x6F, 0x6C, 0x64, 0x2D, 0x3E, 0x74, 0x78, 0x64, 0x65, 0x73, 0x63, 0x5F, 0x6C, 0x61, 0x73, 0x74, +0x00, 0x00, 0x00, 0x00, 0x61, 0x5F, 0x74, 0x68, 0x64, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x52, +0x45, 0x54, 0x52, 0x59, 0x5F, 0x4C, 0x49, 0x4D, 0x49, 0x54, 0x5F, 0x52, 0x45, 0x41, 0x43, 0x48, 0x45, 0x44, 0x5F, 0x42, +0x49, 0x54, 0x00, 0x00, 0x1A, 0x00, 0x1C, 0x00, 0x36, 0x00, 0x3C, 0x00, 0x75, 0x00, 0x82, 0x00, 0xEA, 0x00, 0x04, 0x01, +0x34, 0x00, 0x39, 0x00, 0x6C, 0x00, 0x78, 0x00, 0xEA, 0x00, 0x04, 0x01, 0xD4, 0x01, 0x08, 0x02, 0x4E, 0x00, 0x56, 0x00, +0xA2, 0x00, 0xB4, 0x00, 0x5F, 0x01, 0x86, 0x01, 0xBE, 0x02, 0x0C, 0x03, 0x68, 0x00, 0x73, 0x00, 0xD8, 0x00, 0xF0, 0x00, +0xD4, 0x01, 0x08, 0x02, 0xA8, 0x03, 0x10, 0x04, 0x9C, 0x00, 0xAD, 0x00, 0x44, 0x01, 0x68, 0x01, 0xBE, 0x02, 0x0C, 0x03, +0x7C, 0x05, 0x18, 0x06, 0xD0, 0x00, 0xE7, 0x00, 0xB0, 0x01, 0xE0, 0x01, 0xA8, 0x03, 0x10, 0x04, 0x50, 0x07, 0x20, 0x08, +0xEA, 0x00, 0x04, 0x01, 0xE6, 0x01, 0x1C, 0x02, 0x1D, 0x04, 0x92, 0x04, 0x3A, 0x08, 0x24, 0x09, 0x04, 0x01, 0x20, 0x01, +0x1C, 0x02, 0x58, 0x02, 0x92, 0x04, 0x14, 0x05, 0x24, 0x09, 0x28, 0x0A, 0x38, 0x01, 0x5A, 0x01, 0x88, 0x02, 0xD0, 0x02, +0x7C, 0x05, 0x18, 0x06, 0xF8, 0x0A, 0x30, 0x0C, 0x5A, 0x01, 0x81, 0x01, 0xD0, 0x02, 0x20, 0x03, 0x18, 0x06, 0xC5, 0x06, +0x30, 0x0C, 0x8A, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x08, 0x09, 0x02, 0x02, 0x04, 0x04, 0x08, 0x09, 0x0F, 0x11, +0x03, 0x03, 0x06, 0x06, 0x0B, 0x0D, 0x16, 0x19, 0x04, 0x04, 0x07, 0x08, 0x0F, 0x11, 0x1E, 0x21, 0x05, 0x06, 0x0B, 0x0C, +0x16, 0x19, 0x2C, 0x31, 0x07, 0x08, 0x0E, 0x0F, 0x1E, 0x21, 0x3B, 0x41, 0x08, 0x09, 0x10, 0x11, 0x21, 0x25, 0x42, 0x4A, +0x09, 0x0A, 0x11, 0x13, 0x25, 0x29, 0x4A, 0x52, 0x0A, 0x0B, 0x15, 0x17, 0x2C, 0x31, 0x58, 0x62, 0x0B, 0x0D, 0x17, 0x19, +0x31, 0x37, 0x62, 0x6D, 0x74, 0x78, 0x6C, 0x5F, 0x68, 0x65, 0x5F, 0x65, 0x64, 0x63, 0x61, 0x5F, 0x71, 0x75, 0x65, 0x75, +0x65, 0x5F, 0x68, 0x61, 0x6C, 0x74, 0x65, 0x64, 0x28, 0x61, 0x63, 0x29, 0x00, 0x00, 0x00, 0x00, 0x68, 0x64, 0x72, 0x64, +0x65, 0x73, 0x63, 0x2D, 0x3E, 0x66, 0x72, 0x6D, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x3D, 0x20, 0x48, 0x45, 0x5F, 0x54, 0x52, +0x49, 0x47, 0x5F, 0x46, 0x52, 0x4D, 0x5F, 0x4D, 0x49, 0x4E, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, +0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x6D, 0x63, 0x73, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x31, +0x31, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, +0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, +0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 0x05, 0x00, 0x07, 0x00, +0x06, 0x00, 0x06, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, +0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, +0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, +0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, +0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, +0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, +0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, +0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, +0x22, 0x00, 0x20, 0x00, 0x1D, 0x00, 0x90, 0x00, 0x88, 0x00, 0x7A, 0x00, 0x44, 0x00, 0x41, 0x00, 0x3A, 0x00, 0x20, 0x01, +0x10, 0x01, 0xF5, 0x00, 0x67, 0x00, 0x61, 0x00, 0x57, 0x00, 0xB0, 0x01, 0x98, 0x01, 0x6F, 0x01, 0x89, 0x00, 0x82, 0x00, +0x75, 0x00, 0x40, 0x02, 0x20, 0x02, 0xEA, 0x01, 0xCE, 0x00, 0xC3, 0x00, 0xAF, 0x00, 0x60, 0x03, 0x30, 0x03, 0xDF, 0x02, +0x13, 0x01, 0x04, 0x01, 0xEA, 0x00, 0x80, 0x04, 0x40, 0x04, 0xD4, 0x03, 0x35, 0x01, 0x24, 0x01, 0x07, 0x01, 0x11, 0x05, +0xC9, 0x04, 0x4E, 0x04, 0x58, 0x01, 0x45, 0x01, 0x24, 0x01, 0xA1, 0x05, 0x51, 0x05, 0xC9, 0x04, 0x9C, 0x01, 0x86, 0x01, +0x5F, 0x01, 0xC1, 0x06, 0x61, 0x06, 0xBE, 0x05, 0xCA, 0x01, 0xB1, 0x01, 0x86, 0x01, 0x81, 0x07, 0x16, 0x07, 0x61, 0x06, +0x04, 0x02, 0xE7, 0x01, 0xB6, 0x01, 0x71, 0x08, 0xF9, 0x07, 0x2D, 0x07, 0x3D, 0x02, 0x1D, 0x02, 0xE7, 0x01, 0x61, 0x09, +0xDC, 0x08, 0xF9, 0x07, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, +0x02, 0x00, 0x0A, 0x00, 0x09, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x0C, 0x00, +0x05, 0x00, 0x05, 0x00, 0x04, 0x00, 0x13, 0x00, 0x12, 0x00, 0x10, 0x00, 0x07, 0x00, 0x07, 0x00, 0x06, 0x00, 0x1C, 0x00, +0x1A, 0x00, 0x17, 0x00, 0x09, 0x00, 0x09, 0x00, 0x08, 0x00, 0x25, 0x00, 0x23, 0x00, 0x1F, 0x00, 0x0A, 0x00, 0x0A, 0x00, +0x09, 0x00, 0x29, 0x00, 0x27, 0x00, 0x23, 0x00, 0x0B, 0x00, 0x0B, 0x00, 0x0A, 0x00, 0x2E, 0x00, 0x2B, 0x00, 0x27, 0x00, +0x0D, 0x00, 0x0D, 0x00, 0x0B, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2E, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x3D, 0x00, +0x39, 0x00, 0x34, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0E, 0x00, 0x44, 0x00, 0x40, 0x00, 0x3A, 0x00, 0x12, 0x00, 0x11, 0x00, +0x10, 0x00, 0x4C, 0x00, 0x47, 0x00, 0x40, 0x00, 0x08, 0x10, 0x20, 0x04, 0x50, 0x94, 0x15, 0x00, 0x98, 0x94, 0x15, 0x00, +0x08, 0x94, 0x15, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, +0x74, 0x72, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x6E, 0x6F, 0x20, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, +0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x31, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, +0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, +0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, +0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, +0x78, 0x0D, 0x0A, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x72, 0x65, 0x63, 0x6F, +0x76, 0x65, 0x72, 0x79, 0x0D, 0x0A, 0x00, 0x00, 0x70, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, +0x70, 0x64, 0x2D, 0x3E, 0x70, 0x62, 0x64, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x61, 0x72, 0x74, 0x70, 0x74, 0x72, +0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x61, 0x5F, 0x68, 0x64, 0x72, 0x64, 0x65, 0x73, 0x63, 0x2D, +0x3E, 0x68, 0x64, 0x2E, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5F, 0x70, 0x62, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x20, 0x3D, 0x3D, +0x20, 0x30, 0x00, 0x00, 0x70, 0x62, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x72, 0x78, 0x6C, 0x20, +0x65, 0x72, 0x72, 0x2C, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x75, 0x66, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x6E, 0x6F, 0x20, 0x74, +0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6F, 0x20, 0x74, +0x78, 0x5F, 0x64, 0x73, 0x63, 0x72, 0x5F, 0x68, 0x64, 0x72, 0x21, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, +0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x6D, 0x70, 0x64, 0x75, 0x5F, 0x6C, 0x65, 0x6E, +0x20, 0x3C, 0x3D, 0x20, 0x52, 0x57, 0x4E, 0x58, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x41, 0x4D, 0x53, 0x44, 0x55, 0x5F, 0x52, +0x58, 0x00, 0x00, 0x00, 0x72, 0x68, 0x64, 0x2D, 0x3E, 0x75, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6E, 0x72, 0x78, 0x20, +0x3D, 0x3D, 0x20, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5F, 0x50, 0x41, +0x54, 0x54, 0x45, 0x52, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x78, 0x62, 0x75, 0x66, 0x32, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, +0x25, 0x30, 0x38, 0x78, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x65, 0x6E, +0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x77, +0x72, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x72, 0x64, 0x70, 0x74, 0x72, 0x20, 0x25, 0x30, 0x38, +0x78, 0x0D, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, +0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, +0x73, 0x74, 0x61, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, +0x6D, 0x61, 0x63, 0x20, 0x69, 0x73, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x70, 0x32, 0x70, 0x3D, 0x25, +0x64, 0x0D, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x61, 0x63, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x20, 0x6D, +0x61, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x70, 0x32, 0x70, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, +0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x21, 0x3D, 0x20, 0x50, 0x32, +0x50, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, +0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x76, 0x69, 0x66, 0x20, +0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, +0x76, 0x69, 0x66, 0x20, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6D, 0x67, 0x6D, 0x74, 0x3A, +0x25, 0x64, 0x0A, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, +0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x75, 0x6E, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x00, +0x73, 0x6C, 0x65, 0x65, 0x70, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x6F, 0x6E, 0x5F, 0x61, 0x69, 0x72, 0x5F, 0x76, 0x61, +0x6C, 0x69, 0x64, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x64, 0x74, 0x69, 0x6D, +0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x2A, 0x28, 0x76, 0x6F, +0x6C, 0x61, 0x74, 0x69, 0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, +0x61, 0x6F, 0x6E, 0x5F, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x63, 0x6E, 0x74, 0x5F, +0x61, 0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x3C, 0x20, 0x2A, 0x28, 0x76, 0x6F, 0x6C, 0x61, 0x74, 0x69, +0x6C, 0x65, 0x20, 0x75, 0x69, 0x6E, 0x74, 0x38, 0x5F, 0x74, 0x20, 0x2A, 0x29, 0x26, 0x67, 0x5F, 0x61, 0x6F, 0x6E, 0x5F, +0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2E, 0x64, 0x74, 0x69, 0x6D, 0x5F, 0x70, 0x65, 0x72, 0x69, 0x6F, 0x64, 0x5F, 0x61, +0x6F, 0x6E, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, +0x6C, 0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x4C, 0x2C, 0x00, 0x00, 0x9B, 0x84, 0x4B, 0x65, 0x79, 0x69, 0x64, 0x78, +0x20, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x2C, 0x25, 0x30, 0x32, 0x58, 0x0A, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, +0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x6B, 0x65, 0x79, 0x69, 0x64, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9B, 0x84, 0x49, 0x6E, +0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x53, 0x54, 0x41, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, +0x73, 0x74, 0x61, 0x20, 0x3D, 0x3D, 0x20, 0x76, 0x69, 0x66, 0x00, 0x00, 0x54, 0x3D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x42, 0x43, 0x4E, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x63, 0x6E, 0x20, +0x64, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, +0x6F, 0x6B, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x63, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x6F, 0x6B, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x69, 0x64, 0x6C, 0x65, +0x20, 0x69, 0x6E, 0x74, 0x20, 0x65, 0x72, 0x72, 0x0D, 0x0A, 0x00, 0x00, 0x65, 0x76, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4D, +0x4D, 0x5F, 0x54, 0x42, 0x54, 0x54, 0x5F, 0x45, 0x56, 0x54, 0x5F, 0x4D, 0x41, 0x53, 0x4B, 0x00, 0x61, 0x64, 0x64, 0x20, +0x67, 0x74, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x20, +0x3C, 0x20, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x20, 0x70, 0x74, 0x6B, 0x3A, +0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, +0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, 0x54, +0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, +0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, +0x4E, 0x4F, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x72, +0x65, 0x71, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x63, 0x65, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x65, +0x78, 0x69, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, +0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x48, 0x4F, 0x53, +0x54, 0x5F, 0x42, 0x59, 0x50, 0x41, 0x53, 0x53, 0x45, 0x44, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, +0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x4D, 0x29, 0x20, 0x21, 0x3D, +0x20, 0x4D, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x6B, +0x65, 0x79, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4C, 0x54, +0x5F, 0x4D, 0x46, 0x50, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x43, 0x4F, 0x55, 0x4E, 0x54, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, +0x6D, 0x2D, 0x3E, 0x6B, 0x65, 0x79, 0x2E, 0x6C, 0x65, 0x6E, 0x67, 0x74, 0x68, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x41, 0x43, +0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4B, 0x45, 0x59, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, +0x6D, 0x2D, 0x3E, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5F, 0x73, 0x75, 0x69, 0x74, 0x65, 0x20, 0x3C, 0x3D, 0x20, 0x4D, +0x41, 0x43, 0x5F, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x50, 0x5F, 0x43, 0x4D, 0x41, 0x43, 0x5F, 0x31, +0x32, 0x38, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x68, 0x77, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x69, 0x64, +0x78, 0x20, 0x3C, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x53, 0x45, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x4D, 0x46, 0x50, 0x5F, +0x4B, 0x45, 0x59, 0x5F, 0x4E, 0x42, 0x52, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, +0x20, 0x56, 0x49, 0x46, 0x5F, 0x53, 0x54, 0x41, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, +0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, +0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x6D, 0x75, 0x20, 0x65, 0x64, 0x63, 0x61, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x44, 0x48, 0x43, 0x50, 0x65, 0x64, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x78, 0x2E, 0x0D, 0x0A, 0x00, +0x73, 0x65, 0x74, 0x20, 0x61, 0x67, 0x67, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x2C, 0x20, +0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x72, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x65, 0x74, 0x20, +0x6D, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x73, 0x65, 0x74, 0x20, 0x74, 0x78, 0x6F, 0x70, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x62, 0x6B, 0x3A, 0x25, 0x78, 0x2C, +0x20, 0x62, 0x65, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x69, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x76, 0x6F, 0x3A, 0x25, 0x78, +0x2C, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x6E, 0x61, 0x76, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x63, 0x66, 0x65, 0x3D, 0x25, 0x64, +0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x20, 0x74, 0x72, 0x78, 0x3A, 0x20, +0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, +0x25, 0x78, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, +0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x6F, 0x70, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x69, 0x73, 0x20, 0x35, 0x67, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x77, 0x5F, 0x65, 0x6E, 0x3D, +0x25, 0x64, 0x2C, 0x20, 0x76, 0x65, 0x6E, 0x64, 0x6F, 0x72, 0x5F, 0x69, 0x6E, 0x66, 0x6F, 0x3D, 0x30, 0x78, 0x25, 0x78, +0x0D, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, 0x20, 0x65, 0x66, +0x75, 0x73, 0x65, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, +0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x75, 0x73, 0x65, 0x72, 0x20, 0x63, 0x61, 0x70, 0x5F, 0x66, 0x69, 0x6E, +0x65, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, +0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20, 0x78, 0x74, 0x61, 0x6C, 0x5F, 0x63, 0x61, 0x70, +0x5F, 0x66, 0x69, 0x6E, 0x65, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x62, 0x65, 0x66, +0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, +0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x32, 0x2E, 0x34, 0x67, 0x3A, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x20, +0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x35, 0x67, 0x3A, 0x62, 0x65, 0x66, 0x6F, 0x72, 0x65, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, +0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, 0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x35, 0x67, 0x3A, 0x61, +0x66, 0x74, 0x65, 0x72, 0x20, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x64, 0x63, 0x3D, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x76, 0x63, +0x6D, 0x3D, 0x25, 0x34, 0x78, 0x0D, 0x0A, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, +0x74, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x48, 0x57, +0x5F, 0x49, 0x44, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, +0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x4D, 0x4D, 0x5F, 0x4E, 0x4F, 0x5F, 0x49, +0x44, 0x4C, 0x45, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, +0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x68, 0x65, 0x20, 0x65, +0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x20, 0x73, 0x74, 0x61, 0x74, +0x65, 0x20, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, +0xA8, 0x1F, 0x17, 0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x70, 0x61, 0x73, 0x74, 0x3A, 0x20, +0x63, 0x62, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x63, 0x75, 0x72, 0x72, +0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x6D, 0x61, 0x63, 0x68, 0x77, 0x5F, 0x74, +0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x29, 0x00, 0x74, 0x69, 0x6D, 0x65, +0x72, 0x2D, 0x3E, 0x63, 0x62, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, 0x70, 0x72, 0x6F, 0x62, +0x65, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x20, +0x70, 0x72, 0x6F, 0x62, 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x0A, 0x00, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, +0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x6C, +0x6C, 0x65, 0x20, 0x6E, 0x65, 0x76, 0x65, 0x72, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x61, 0x70, 0x6D, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x6E, 0x75, 0x6C, 0x6C, 0x20, 0x74, 0x6F, 0x20, 0x70, 0x72, 0x6F, +0x62, 0x65, 0x20, 0x73, 0x74, 0x61, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x5F, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0A, 0x00, +0x21, 0x6D, 0x6D, 0x5F, 0x62, 0x63, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x74, 0x78, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, +0x61, 0x70, 0x6D, 0x5F, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, +0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, +0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, +0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x29, 0x20, 0x7C, +0x7C, 0x20, 0x28, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, +0x74, 0x78, 0x74, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, +0x20, 0x3D, 0x3D, 0x20, 0x70, 0x32, 0x70, 0x67, 0x6F, 0x5F, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, +0x29, 0x00, 0x00, 0x00, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x62, 0x5F, 0x76, +0x69, 0x66, 0x5F, 0x6F, 0x74, 0x68, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3E, 0x20, 0x31, 0x00, 0x6E, 0x6F, 0x61, 0x5F, +0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, 0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, +0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x33, 0x32, 0x00, +0x76, 0x69, 0x66, 0x2D, 0x3E, 0x74, 0x62, 0x74, 0x74, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2E, 0x70, 0x32, 0x70, +0x5F, 0x6E, 0x6F, 0x61, 0x5F, 0x76, 0x69, 0x66, 0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, +0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, 0x00, 0x63, 0x68, 0x5F, 0x73, +0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, +0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x52, +0x4F, 0x43, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x50, 0x45, 0x4E, 0x44, 0x49, 0x4E, 0x47, 0x5F, 0x4D, 0x41, 0x53, 0x4B, +0x00, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, +0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x52, +0x4F, 0x43, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x63, 0x68, 0x61, +0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, +0x54, 0x28, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x45, 0x4E, 0x56, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, +0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x28, 0x76, 0x6F, 0x69, 0x64, 0x20, 0x2A, 0x29, 0x63, 0x68, 0x5F, 0x73, +0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, +0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x00, 0x00, 0x00, +0x4E, 0x6F, 0x20, 0x63, 0x74, 0x78, 0x74, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x64, 0x20, 0x70, 0x72, +0x65, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x69, 0x64, +0x78, 0x20, 0x3D, 0x3D, 0x20, 0x43, 0x48, 0x41, 0x4E, 0x5F, 0x43, 0x54, 0x58, 0x54, 0x5F, 0x55, 0x4E, 0x55, 0x53, 0x45, +0x44, 0x00, 0x00, 0x00, 0x72, 0x6F, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x64, 0x75, 0x72, 0x3D, 0x25, 0x64, 0x2C, +0x20, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x74, 0x78, 0x74, 0x2D, 0x3E, 0x6E, 0x62, +0x5F, 0x6C, 0x69, 0x6E, 0x6B, 0x65, 0x64, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, +0x76, 0x69, 0x66, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, +0x4C, 0x4C, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, +0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x63, 0x68, 0x5F, 0x73, 0x77, 0x69, 0x74, 0x63, +0x68, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, +0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, +0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, 0x20, 0x75, 0x6E, 0x6C, 0x69, 0x6E, 0x6B, 0x3A, 0x20, 0x25, 0x64, 0x2C, +0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x68, 0x61, 0x6E, +0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x6E, 0x62, 0x5F, 0x73, 0x63, 0x68, 0x65, 0x64, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x3C, +0x3D, 0x20, 0x31, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x70, 0x73, 0x3A, 0x6C, 0x69, 0x6E, 0x6B, 0x6C, +0x6F, 0x73, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, +0x70, 0x73, 0x5F, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x64, +0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x5F, 0x63, 0x66, 0x6D, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, +0x6E, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5F, 0x75, 0x70, 0x6D, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x00, +0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, +0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x6F, 0x61, 0x5F, 0x69, 0x6E, 0x73, 0x74, 0x20, 0x3C, 0x20, 0x50, 0x32, 0x50, 0x5F, +0x4E, 0x4F, 0x41, 0x5F, 0x4E, 0x42, 0x5F, 0x4D, 0x41, 0x58, 0x29, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x70, 0x32, 0x70, +0x5F, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x50, 0x32, 0x50, 0x5F, 0x56, 0x49, 0x46, 0x5F, +0x4D, 0x41, 0x58, 0x00, 0x74, 0x64, 0x73, 0x5F, 0x65, 0x6E, 0x76, 0x00, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, +0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, 0x74, 0x20, 0x3E, 0x20, 0x30, 0x00, +0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, +0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x57, 0x41, 0x49, 0x54, 0x5F, 0x43, 0x48, 0x41, +0x4E, 0x4E, 0x45, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, +0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, +0x57, 0x41, 0x49, 0x54, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, 0x4E, 0x5F, 0x50, 0x52, 0x4F, 0x42, 0x45, 0x5F, 0x52, 0x53, +0x50, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x5F, 0x68, +0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, +0x72, 0x65, 0x71, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x50, 0x21, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, +0x73, 0x63, 0x61, 0x6E, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x5F, 0x63, 0x66, 0x6D, +0x00, 0x00, 0x00, 0x00, 0x6E, 0x78, 0x6D, 0x61, 0x63, 0x5F, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x74, 0x5F, 0x73, 0x74, +0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x66, 0x28, 0x29, 0x20, 0x21, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x49, 0x44, 0x4C, +0x45, 0x00, 0x00, 0x00, 0x21, 0x68, 0x61, 0x6C, 0x5F, 0x61, 0x6F, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, 0x74, 0x69, +0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x20, +0x2B, 0x20, 0x35, 0x30, 0x30, 0x30, 0x29, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, +0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6B, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, +0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, +0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x20, 0x6D, +0x6D, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x67, 0x65, 0x6E, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x72, +0x20, 0x61, 0x6E, 0x79, 0x6D, 0x6F, 0x72, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x30, 0x5F, 0x54, 0x49, +0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x31, 0x5F, 0x54, 0x49, +0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x32, 0x5F, 0x54, 0x49, +0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x41, 0x43, 0x33, 0x5F, 0x54, 0x49, +0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x5F, 0x54, +0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x45, 0x5F, 0x54, 0x42, 0x5F, +0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x5F, +0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x48, 0x41, 0x4C, 0x5F, 0x48, 0x49, 0x51, 0x5F, 0x54, 0x49, +0x4D, 0x45, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x52, 0x58, 0x5F, 0x46, 0x49, 0x46, 0x4F, 0x5F, +0x4F, 0x56, 0x45, 0x52, 0x5F, 0x46, 0x4C, 0x4F, 0x57, 0x20, 0x68, 0x61, 0x70, 0x70, 0x65, 0x6E, 0x2C, 0x20, 0x68, 0x77, +0x20, 0x72, 0x65, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6C, 0x66, 0x0D, 0x0A, 0x00, 0x00, +0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, +0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x5F, 0x45, 0x52, 0x52, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, +0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, +0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x55, 0x4E, 0x44, 0x45, 0x52, +0x5F, 0x52, 0x55, 0x4E, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, +0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x4D, 0x41, 0x43, +0x5F, 0x50, 0x48, 0x59, 0x49, 0x46, 0x5F, 0x4F, 0x56, 0x45, 0x52, 0x46, 0x4C, 0x4F, 0x57, 0x5F, 0x42, 0x49, 0x54, 0x29, +0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, +0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x50, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x5F, 0x42, 0x49, +0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, +0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x30, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, +0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, +0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, +0x31, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, +0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, +0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x32, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, +0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, +0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x41, 0x43, 0x5F, 0x33, 0x5F, 0x54, 0x58, +0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, +0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, +0x5F, 0x42, 0x43, 0x4E, 0x5F, 0x54, 0x58, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, +0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, +0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x58, 0x5F, 0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x5F, 0x44, +0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, +0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, +0x5F, 0x52, 0x58, 0x5F, 0x50, 0x41, 0x59, 0x4C, 0x4F, 0x41, 0x44, 0x5F, 0x44, 0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, +0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, +0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x57, 0x5F, 0x45, 0x52, 0x52, 0x5F, +0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x67, 0x65, 0x6E, 0x69, 0x72, 0x71, 0x5F, 0x70, 0x65, 0x6E, +0x64, 0x69, 0x6E, 0x67, 0x20, 0x26, 0x20, 0x4E, 0x58, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x49, 0x5F, 0x54, 0x58, 0x5F, 0x44, +0x4D, 0x41, 0x5F, 0x44, 0x45, 0x41, 0x44, 0x5F, 0x42, 0x49, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, +0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x08, 0x06, 0x04, 0x0B, 0x09, 0x07, 0x05, 0xA5, 0xC6, 0x84, 0xF8, 0x99, 0xEE, 0x8D, 0xF6, +0x0D, 0xFF, 0xBD, 0xD6, 0xB1, 0xDE, 0x54, 0x91, 0x50, 0x60, 0x03, 0x02, 0xA9, 0xCE, 0x7D, 0x56, 0x19, 0xE7, 0x62, 0xB5, +0xE6, 0x4D, 0x9A, 0xEC, 0x45, 0x8F, 0x9D, 0x1F, 0x40, 0x89, 0x87, 0xFA, 0x15, 0xEF, 0xEB, 0xB2, 0xC9, 0x8E, 0x0B, 0xFB, +0xEC, 0x41, 0x67, 0xB3, 0xFD, 0x5F, 0xEA, 0x45, 0xBF, 0x23, 0xF7, 0x53, 0x96, 0xE4, 0x5B, 0x9B, 0xC2, 0x75, 0x1C, 0xE1, +0xAE, 0x3D, 0x6A, 0x4C, 0x5A, 0x6C, 0x41, 0x7E, 0x02, 0xF5, 0x4F, 0x83, 0x5C, 0x68, 0xF4, 0x51, 0x34, 0xD1, 0x08, 0xF9, +0x93, 0xE2, 0x73, 0xAB, 0x53, 0x62, 0x3F, 0x2A, 0x0C, 0x08, 0x52, 0x95, 0x65, 0x46, 0x5E, 0x9D, 0x28, 0x30, 0xA1, 0x37, +0x0F, 0x0A, 0xB5, 0x2F, 0x09, 0x0E, 0x36, 0x24, 0x9B, 0x1B, 0x3D, 0xDF, 0x26, 0xCD, 0x69, 0x4E, 0xCD, 0x7F, 0x9F, 0xEA, +0x1B, 0x12, 0x9E, 0x1D, 0x74, 0x58, 0x2E, 0x34, 0x2D, 0x36, 0xB2, 0xDC, 0xEE, 0xB4, 0xFB, 0x5B, 0xF6, 0xA4, 0x4D, 0x76, +0x61, 0xB7, 0xCE, 0x7D, 0x7B, 0x52, 0x3E, 0xDD, 0x71, 0x5E, 0x97, 0x13, 0xF5, 0xA6, 0x68, 0xB9, 0x00, 0x00, 0x2C, 0xC1, +0x60, 0x40, 0x1F, 0xE3, 0xC8, 0x79, 0xED, 0xB6, 0xBE, 0xD4, 0x46, 0x8D, 0xD9, 0x67, 0x4B, 0x72, 0xDE, 0x94, 0xD4, 0x98, +0xE8, 0xB0, 0x4A, 0x85, 0x6B, 0xBB, 0x2A, 0xC5, 0xE5, 0x4F, 0x16, 0xED, 0xC5, 0x86, 0xD7, 0x9A, 0x55, 0x66, 0x94, 0x11, +0xCF, 0x8A, 0x10, 0xE9, 0x06, 0x04, 0x81, 0xFE, 0xF0, 0xA0, 0x44, 0x78, 0xBA, 0x25, 0xE3, 0x4B, 0xF3, 0xA2, 0xFE, 0x5D, +0xC0, 0x80, 0x8A, 0x05, 0xAD, 0x3F, 0xBC, 0x21, 0x48, 0x70, 0x04, 0xF1, 0xDF, 0x63, 0xC1, 0x77, 0x75, 0xAF, 0x63, 0x42, +0x30, 0x20, 0x1A, 0xE5, 0x0E, 0xFD, 0x6D, 0xBF, 0x4C, 0x81, 0x14, 0x18, 0x35, 0x26, 0x2F, 0xC3, 0xE1, 0xBE, 0xA2, 0x35, +0xCC, 0x88, 0x39, 0x2E, 0x57, 0x93, 0xF2, 0x55, 0x82, 0xFC, 0x47, 0x7A, 0xAC, 0xC8, 0xE7, 0xBA, 0x2B, 0x32, 0x95, 0xE6, +0xA0, 0xC0, 0x98, 0x19, 0xD1, 0x9E, 0x7F, 0xA3, 0x66, 0x44, 0x7E, 0x54, 0xAB, 0x3B, 0x83, 0x0B, 0xCA, 0x8C, 0x29, 0xC7, +0xD3, 0x6B, 0x3C, 0x28, 0x79, 0xA7, 0xE2, 0xBC, 0x1D, 0x16, 0x76, 0xAD, 0x3B, 0xDB, 0x56, 0x64, 0x4E, 0x74, 0x1E, 0x14, +0xDB, 0x92, 0x0A, 0x0C, 0x6C, 0x48, 0xE4, 0xB8, 0x5D, 0x9F, 0x6E, 0xBD, 0xEF, 0x43, 0xA6, 0xC4, 0xA8, 0x39, 0xA4, 0x31, +0x37, 0xD3, 0x8B, 0xF2, 0x32, 0xD5, 0x43, 0x8B, 0x59, 0x6E, 0xB7, 0xDA, 0x8C, 0x01, 0x64, 0xB1, 0xD2, 0x9C, 0xE0, 0x49, +0xB4, 0xD8, 0xFA, 0xAC, 0x07, 0xF3, 0x25, 0xCF, 0xAF, 0xCA, 0x8E, 0xF4, 0xE9, 0x47, 0x18, 0x10, 0xD5, 0x6F, 0x88, 0xF0, +0x6F, 0x4A, 0x72, 0x5C, 0x24, 0x38, 0xF1, 0x57, 0xC7, 0x73, 0x51, 0x97, 0x23, 0xCB, 0x7C, 0xA1, 0x9C, 0xE8, 0x21, 0x3E, +0xDD, 0x96, 0xDC, 0x61, 0x86, 0x0D, 0x85, 0x0F, 0x90, 0xE0, 0x42, 0x7C, 0xC4, 0x71, 0xAA, 0xCC, 0xD8, 0x90, 0x05, 0x06, +0x01, 0xF7, 0x12, 0x1C, 0xA3, 0xC2, 0x5F, 0x6A, 0xF9, 0xAE, 0xD0, 0x69, 0x91, 0x17, 0x58, 0x99, 0x27, 0x3A, 0xB9, 0x27, +0x38, 0xD9, 0x13, 0xEB, 0xB3, 0x2B, 0x33, 0x22, 0xBB, 0xD2, 0x70, 0xA9, 0x89, 0x07, 0xA7, 0x33, 0xB6, 0x2D, 0x22, 0x3C, +0x92, 0x15, 0x20, 0xC9, 0x49, 0x87, 0xFF, 0xAA, 0x78, 0x50, 0x7A, 0xA5, 0x8F, 0x03, 0xF8, 0x59, 0x80, 0x09, 0x17, 0x1A, +0xDA, 0x65, 0x31, 0xD7, 0xC6, 0x84, 0xB8, 0xD0, 0xC3, 0x82, 0xB0, 0x29, 0x77, 0x5A, 0x11, 0x1E, 0xCB, 0x7B, 0xFC, 0xA8, +0xD6, 0x6D, 0x3A, 0x2C, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x3E, 0x20, 0x30, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x61, +0x79, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x54, 0x49, 0x4D, 0x45, 0x52, 0x5F, 0x44, 0x45, 0x4C, 0x41, 0x59, 0x5F, 0x4D, +0x41, 0x58, 0x00, 0x00, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0x21, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x7C, +0x7C, 0x20, 0x21, 0x6B, 0x65, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x5F, 0x70, 0x61, 0x73, 0x74, 0x28, 0x66, 0x69, 0x72, 0x73, +0x74, 0x2D, 0x3E, 0x74, 0x69, 0x6D, 0x65, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, +0x55, 0x4C, 0x4C, 0x00, 0x9D, 0x80, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x73, +0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x20, 0x74, 0x6F, 0x20, +0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x74, 0x6F, 0x74, 0x61, 0x6C, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3E, 0x3D, +0x20, 0x73, 0x69, 0x7A, 0x65, 0x6F, 0x66, 0x28, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6D, 0x62, 0x6C, 0x6F, 0x63, +0x6B, 0x5F, 0x66, 0x72, 0x65, 0x65, 0x29, 0x00, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, +0x4C, 0x00, 0x00, 0x00, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6D, 0x65, 0x6D, 0x5F, 0x70, 0x74, +0x72, 0x20, 0x3E, 0x20, 0x28, 0x75, 0x69, 0x6E, 0x74, 0x33, 0x32, 0x5F, 0x74, 0x29, 0x6E, 0x6F, 0x64, 0x65, 0x00, 0x00, +0x70, 0x72, 0x65, 0x76, 0x5F, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, +0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x2D, 0x3E, 0x6D, 0x73, 0x67, 0x5F, 0x74, +0x61, 0x62, 0x6C, 0x65, 0x5B, 0x69, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x00, 0x00, 0x00, 0x74, 0x79, 0x70, 0x65, +0x20, 0x3C, 0x20, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x6B, 0x65, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x5F, +0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x28, 0x74, 0x79, 0x70, 0x65, 0x29, 0x00, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x54, 0x41, +0x53, 0x4B, 0x5F, 0x44, 0x45, 0x53, 0x43, 0x5B, 0x74, 0x79, 0x70, 0x65, 0x5D, 0x2E, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, +0x78, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x69, 0x64, 0x5F, 0x70, 0x74, 0x72, 0x00, 0x00, +0x80, 0x9D, 0x73, 0x65, 0x74, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x9A, 0x80, 0x4E, 0x6F, 0x20, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x20, 0x66, +0x6F, 0x72, 0x20, 0x6D, 0x73, 0x67, 0x3A, 0x25, 0x78, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, +0x78, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x73, 0x6B, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x24, 0x9F, 0x15, 0x00, +0x1C, 0x9F, 0x15, 0x00, 0xCC, 0x9C, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xB5, 0x15, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xA4, 0x15, 0x00, 0xF0, 0x9F, 0x17, 0x00, +0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x20, 0xBF, 0x15, 0x00, 0x18, 0xBF, 0x15, 0x00, 0xA4, 0xBA, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x8C, 0xB8, 0x15, 0x00, 0xE0, 0xB8, 0x17, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xBB, 0x15, 0x00, +0x60, 0xBA, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xBE, 0x15, 0x00, 0x90, 0xBA, 0x17, 0x00, +0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xC2, 0x15, 0x00, 0xF4, 0xDF, 0x17, 0x00, 0x05, 0x00, 0x20, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xD0, 0x15, 0x00, +0x74, 0xEF, 0x17, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x28, 0x65, 0x76, 0x65, 0x6E, 0x74, 0x20, 0x3C, 0x20, 0x4B, 0x45, 0x5F, 0x45, 0x56, 0x54, 0x5F, +0x4D, 0x41, 0x58, 0x29, 0x20, 0x26, 0x26, 0x20, 0x6B, 0x65, 0x5F, 0x65, 0x76, 0x74, 0x5F, 0x68, 0x64, 0x6C, 0x72, 0x5B, +0x65, 0x76, 0x65, 0x6E, 0x74, 0x5D, 0x2E, 0x66, 0x75, 0x6E, 0x63, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x68, 0x64, 0x72, +0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x21, 0x3D, 0x20, +0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, +0x74, 0x20, 0x3D, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x70, 0x72, 0x65, 0x76, 0x5F, +0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x2D, 0x3E, 0x6E, 0x65, 0x78, 0x74, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6C, 0x65, +0x6D, 0x65, 0x6E, 0x74, 0x29, 0x00, 0x00, 0x00, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, +0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x30, 0x07, 0x77, 0x2C, 0x61, 0x0E, 0xEE, 0xBA, 0x51, 0x09, 0x99, +0x19, 0xC4, 0x6D, 0x07, 0x8F, 0xF4, 0x6A, 0x70, 0x35, 0xA5, 0x63, 0xE9, 0xA3, 0x95, 0x64, 0x9E, 0x32, 0x88, 0xDB, 0x0E, +0xA4, 0xB8, 0xDC, 0x79, 0x1E, 0xE9, 0xD5, 0xE0, 0x88, 0xD9, 0xD2, 0x97, 0x2B, 0x4C, 0xB6, 0x09, 0xBD, 0x7C, 0xB1, 0x7E, +0x07, 0x2D, 0xB8, 0xE7, 0x91, 0x1D, 0xBF, 0x90, 0x64, 0x10, 0xB7, 0x1D, 0xF2, 0x20, 0xB0, 0x6A, 0x48, 0x71, 0xB9, 0xF3, +0xDE, 0x41, 0xBE, 0x84, 0x7D, 0xD4, 0xDA, 0x1A, 0xEB, 0xE4, 0xDD, 0x6D, 0x51, 0xB5, 0xD4, 0xF4, 0xC7, 0x85, 0xD3, 0x83, +0x56, 0x98, 0x6C, 0x13, 0xC0, 0xA8, 0x6B, 0x64, 0x7A, 0xF9, 0x62, 0xFD, 0xEC, 0xC9, 0x65, 0x8A, 0x4F, 0x5C, 0x01, 0x14, +0xD9, 0x6C, 0x06, 0x63, 0x63, 0x3D, 0x0F, 0xFA, 0xF5, 0x0D, 0x08, 0x8D, 0xC8, 0x20, 0x6E, 0x3B, 0x5E, 0x10, 0x69, 0x4C, +0xE4, 0x41, 0x60, 0xD5, 0x72, 0x71, 0x67, 0xA2, 0xD1, 0xE4, 0x03, 0x3C, 0x47, 0xD4, 0x04, 0x4B, 0xFD, 0x85, 0x0D, 0xD2, +0x6B, 0xB5, 0x0A, 0xA5, 0xFA, 0xA8, 0xB5, 0x35, 0x6C, 0x98, 0xB2, 0x42, 0xD6, 0xC9, 0xBB, 0xDB, 0x40, 0xF9, 0xBC, 0xAC, +0xE3, 0x6C, 0xD8, 0x32, 0x75, 0x5C, 0xDF, 0x45, 0xCF, 0x0D, 0xD6, 0xDC, 0x59, 0x3D, 0xD1, 0xAB, 0xAC, 0x30, 0xD9, 0x26, +0x3A, 0x00, 0xDE, 0x51, 0x80, 0x51, 0xD7, 0xC8, 0x16, 0x61, 0xD0, 0xBF, 0xB5, 0xF4, 0xB4, 0x21, 0x23, 0xC4, 0xB3, 0x56, +0x99, 0x95, 0xBA, 0xCF, 0x0F, 0xA5, 0xBD, 0xB8, 0x9E, 0xB8, 0x02, 0x28, 0x08, 0x88, 0x05, 0x5F, 0xB2, 0xD9, 0x0C, 0xC6, +0x24, 0xE9, 0x0B, 0xB1, 0x87, 0x7C, 0x6F, 0x2F, 0x11, 0x4C, 0x68, 0x58, 0xAB, 0x1D, 0x61, 0xC1, 0x3D, 0x2D, 0x66, 0xB6, +0x90, 0x41, 0xDC, 0x76, 0x06, 0x71, 0xDB, 0x01, 0xBC, 0x20, 0xD2, 0x98, 0x2A, 0x10, 0xD5, 0xEF, 0x89, 0x85, 0xB1, 0x71, +0x1F, 0xB5, 0xB6, 0x06, 0xA5, 0xE4, 0xBF, 0x9F, 0x33, 0xD4, 0xB8, 0xE8, 0xA2, 0xC9, 0x07, 0x78, 0x34, 0xF9, 0x00, 0x0F, +0x8E, 0xA8, 0x09, 0x96, 0x18, 0x98, 0x0E, 0xE1, 0xBB, 0x0D, 0x6A, 0x7F, 0x2D, 0x3D, 0x6D, 0x08, 0x97, 0x6C, 0x64, 0x91, +0x01, 0x5C, 0x63, 0xE6, 0xF4, 0x51, 0x6B, 0x6B, 0x62, 0x61, 0x6C, 0x1C, 0xD8, 0x30, 0x65, 0x85, 0x4E, 0x00, 0x62, 0xF2, +0xED, 0x95, 0x06, 0x6C, 0x7B, 0xA5, 0x01, 0x1B, 0xC1, 0xF4, 0x08, 0x82, 0x57, 0xC4, 0x0F, 0xF5, 0xC6, 0xD9, 0xB0, 0x65, +0x50, 0xE9, 0xB7, 0x12, 0xEA, 0xB8, 0xBE, 0x8B, 0x7C, 0x88, 0xB9, 0xFC, 0xDF, 0x1D, 0xDD, 0x62, 0x49, 0x2D, 0xDA, 0x15, +0xF3, 0x7C, 0xD3, 0x8C, 0x65, 0x4C, 0xD4, 0xFB, 0x58, 0x61, 0xB2, 0x4D, 0xCE, 0x51, 0xB5, 0x3A, 0x74, 0x00, 0xBC, 0xA3, +0xE2, 0x30, 0xBB, 0xD4, 0x41, 0xA5, 0xDF, 0x4A, 0xD7, 0x95, 0xD8, 0x3D, 0x6D, 0xC4, 0xD1, 0xA4, 0xFB, 0xF4, 0xD6, 0xD3, +0x6A, 0xE9, 0x69, 0x43, 0xFC, 0xD9, 0x6E, 0x34, 0x46, 0x88, 0x67, 0xAD, 0xD0, 0xB8, 0x60, 0xDA, 0x73, 0x2D, 0x04, 0x44, +0xE5, 0x1D, 0x03, 0x33, 0x5F, 0x4C, 0x0A, 0xAA, 0xC9, 0x7C, 0x0D, 0xDD, 0x3C, 0x71, 0x05, 0x50, 0xAA, 0x41, 0x02, 0x27, +0x10, 0x10, 0x0B, 0xBE, 0x86, 0x20, 0x0C, 0xC9, 0x25, 0xB5, 0x68, 0x57, 0xB3, 0x85, 0x6F, 0x20, 0x09, 0xD4, 0x66, 0xB9, +0x9F, 0xE4, 0x61, 0xCE, 0x0E, 0xF9, 0xDE, 0x5E, 0x98, 0xC9, 0xD9, 0x29, 0x22, 0x98, 0xD0, 0xB0, 0xB4, 0xA8, 0xD7, 0xC7, +0x17, 0x3D, 0xB3, 0x59, 0x81, 0x0D, 0xB4, 0x2E, 0x3B, 0x5C, 0xBD, 0xB7, 0xAD, 0x6C, 0xBA, 0xC0, 0x20, 0x83, 0xB8, 0xED, +0xB6, 0xB3, 0xBF, 0x9A, 0x0C, 0xE2, 0xB6, 0x03, 0x9A, 0xD2, 0xB1, 0x74, 0x39, 0x47, 0xD5, 0xEA, 0xAF, 0x77, 0xD2, 0x9D, +0x15, 0x26, 0xDB, 0x04, 0x83, 0x16, 0xDC, 0x73, 0x12, 0x0B, 0x63, 0xE3, 0x84, 0x3B, 0x64, 0x94, 0x3E, 0x6A, 0x6D, 0x0D, +0xA8, 0x5A, 0x6A, 0x7A, 0x0B, 0xCF, 0x0E, 0xE4, 0x9D, 0xFF, 0x09, 0x93, 0x27, 0xAE, 0x00, 0x0A, 0xB1, 0x9E, 0x07, 0x7D, +0x44, 0x93, 0x0F, 0xF0, 0xD2, 0xA3, 0x08, 0x87, 0x68, 0xF2, 0x01, 0x1E, 0xFE, 0xC2, 0x06, 0x69, 0x5D, 0x57, 0x62, 0xF7, +0xCB, 0x67, 0x65, 0x80, 0x71, 0x36, 0x6C, 0x19, 0xE7, 0x06, 0x6B, 0x6E, 0x76, 0x1B, 0xD4, 0xFE, 0xE0, 0x2B, 0xD3, 0x89, +0x5A, 0x7A, 0xDA, 0x10, 0xCC, 0x4A, 0xDD, 0x67, 0x6F, 0xDF, 0xB9, 0xF9, 0xF9, 0xEF, 0xBE, 0x8E, 0x43, 0xBE, 0xB7, 0x17, +0xD5, 0x8E, 0xB0, 0x60, 0xE8, 0xA3, 0xD6, 0xD6, 0x7E, 0x93, 0xD1, 0xA1, 0xC4, 0xC2, 0xD8, 0x38, 0x52, 0xF2, 0xDF, 0x4F, +0xF1, 0x67, 0xBB, 0xD1, 0x67, 0x57, 0xBC, 0xA6, 0xDD, 0x06, 0xB5, 0x3F, 0x4B, 0x36, 0xB2, 0x48, 0xDA, 0x2B, 0x0D, 0xD8, +0x4C, 0x1B, 0x0A, 0xAF, 0xF6, 0x4A, 0x03, 0x36, 0x60, 0x7A, 0x04, 0x41, 0xC3, 0xEF, 0x60, 0xDF, 0x55, 0xDF, 0x67, 0xA8, +0xEF, 0x8E, 0x6E, 0x31, 0x79, 0xBE, 0x69, 0x46, 0x8C, 0xB3, 0x61, 0xCB, 0x1A, 0x83, 0x66, 0xBC, 0xA0, 0xD2, 0x6F, 0x25, +0x36, 0xE2, 0x68, 0x52, 0x95, 0x77, 0x0C, 0xCC, 0x03, 0x47, 0x0B, 0xBB, 0xB9, 0x16, 0x02, 0x22, 0x2F, 0x26, 0x05, 0x55, +0xBE, 0x3B, 0xBA, 0xC5, 0x28, 0x0B, 0xBD, 0xB2, 0x92, 0x5A, 0xB4, 0x2B, 0x04, 0x6A, 0xB3, 0x5C, 0xA7, 0xFF, 0xD7, 0xC2, +0x31, 0xCF, 0xD0, 0xB5, 0x8B, 0x9E, 0xD9, 0x2C, 0x1D, 0xAE, 0xDE, 0x5B, 0xB0, 0xC2, 0x64, 0x9B, 0x26, 0xF2, 0x63, 0xEC, +0x9C, 0xA3, 0x6A, 0x75, 0x0A, 0x93, 0x6D, 0x02, 0xA9, 0x06, 0x09, 0x9C, 0x3F, 0x36, 0x0E, 0xEB, 0x85, 0x67, 0x07, 0x72, +0x13, 0x57, 0x00, 0x05, 0x82, 0x4A, 0xBF, 0x95, 0x14, 0x7A, 0xB8, 0xE2, 0xAE, 0x2B, 0xB1, 0x7B, 0x38, 0x1B, 0xB6, 0x0C, +0x9B, 0x8E, 0xD2, 0x92, 0x0D, 0xBE, 0xD5, 0xE5, 0xB7, 0xEF, 0xDC, 0x7C, 0x21, 0xDF, 0xDB, 0x0B, 0xD4, 0xD2, 0xD3, 0x86, +0x42, 0xE2, 0xD4, 0xF1, 0xF8, 0xB3, 0xDD, 0x68, 0x6E, 0x83, 0xDA, 0x1F, 0xCD, 0x16, 0xBE, 0x81, 0x5B, 0x26, 0xB9, 0xF6, +0xE1, 0x77, 0xB0, 0x6F, 0x77, 0x47, 0xB7, 0x18, 0xE6, 0x5A, 0x08, 0x88, 0x70, 0x6A, 0x0F, 0xFF, 0xCA, 0x3B, 0x06, 0x66, +0x5C, 0x0B, 0x01, 0x11, 0xFF, 0x9E, 0x65, 0x8F, 0x69, 0xAE, 0x62, 0xF8, 0xD3, 0xFF, 0x6B, 0x61, 0x45, 0xCF, 0x6C, 0x16, +0x78, 0xE2, 0x0A, 0xA0, 0xEE, 0xD2, 0x0D, 0xD7, 0x54, 0x83, 0x04, 0x4E, 0xC2, 0xB3, 0x03, 0x39, 0x61, 0x26, 0x67, 0xA7, +0xF7, 0x16, 0x60, 0xD0, 0x4D, 0x47, 0x69, 0x49, 0xDB, 0x77, 0x6E, 0x3E, 0x4A, 0x6A, 0xD1, 0xAE, 0xDC, 0x5A, 0xD6, 0xD9, +0x66, 0x0B, 0xDF, 0x40, 0xF0, 0x3B, 0xD8, 0x37, 0x53, 0xAE, 0xBC, 0xA9, 0xC5, 0x9E, 0xBB, 0xDE, 0x7F, 0xCF, 0xB2, 0x47, +0xE9, 0xFF, 0xB5, 0x30, 0x1C, 0xF2, 0xBD, 0xBD, 0x8A, 0xC2, 0xBA, 0xCA, 0x30, 0x93, 0xB3, 0x53, 0xA6, 0xA3, 0xB4, 0x24, +0x05, 0x36, 0xD0, 0xBA, 0x93, 0x06, 0xD7, 0xCD, 0x29, 0x57, 0xDE, 0x54, 0xBF, 0x67, 0xD9, 0x23, 0x2E, 0x7A, 0x66, 0xB3, +0xB8, 0x4A, 0x61, 0xC4, 0x02, 0x1B, 0x68, 0x5D, 0x94, 0x2B, 0x6F, 0x2A, 0x37, 0xBE, 0x0B, 0xB4, 0xA1, 0x8E, 0x0C, 0xC3, +0x1B, 0xDF, 0x05, 0x5A, 0x8D, 0xEF, 0x02, 0x2D, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3D, 0x3D, 0x20, 0x65, 0x6E, 0x64, 0x00, +0x00, 0x50, 0xF2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x03, +0x04, 0x08, 0x02, 0x01, 0x01, 0x00, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x04, 0x0B, 0x16, +0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, +0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, 0x56, 0x5F, 0x4D, 0x49, 0x4E, 0x20, 0x3C, 0x3D, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, +0x78, 0x20, 0x26, 0x26, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3C, 0x20, 0x44, 0x42, 0x47, 0x5F, 0x53, 0x45, +0x56, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, +0x63, 0x64, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, +0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, +0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x02, 0x03, 0x02, 0x06, 0x07, 0x00, 0x00, 0x04, 0x03, 0x03, 0x00, 0x06, 0x07, +0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x05, 0x05, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x2C, 0x20, 0x77, 0x6C, 0x61, +0x6E, 0x20, 0x66, 0x63, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x62, 0x6F, +0x6F, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x67, 0x70, 0x69, 0x6F, 0x77, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, +0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, +0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x20, 0x66, 0x69, 0x6C, 0x74, +0x65, 0x72, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x53, +0x65, 0x74, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, +0x3A, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x42, +0x6F, 0x6F, 0x74, 0x20, 0x4E, 0x50, 0x43, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, +0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6D, +0x61, 0x73, 0x6B, 0x3A, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3A, 0x30, 0x78, 0x25, +0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, +0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, +0x47, 0x3A, 0x20, 0x57, 0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x77, 0x69, +0x74, 0x68, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, +0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, +0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, +0x79, 0x3A, 0x20, 0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, +0x20, 0x2F, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x42, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, +0x25, 0x78, 0x2C, 0x20, 0x61, 0x64, 0x64, 0x72, 0x3D, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x64, 0x65, 0x6C, 0x61, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x49, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, +0x62, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x0D, 0x0A, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x46, +0x57, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x0A, 0x00, 0x00, 0x9D, 0x81, 0x44, 0x42, 0x47, 0x3A, 0x20, 0x57, +0x72, 0x69, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, +0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x20, 0x7E, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x5D, 0x20, 0x77, 0x69, +0x74, 0x68, 0x20, 0x7B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x2C, 0x20, 0x2E, 0x2E, 0x2E, 0x7D, 0x2C, 0x20, 0x77, 0x73, +0x74, 0x61, 0x74, 0x75, 0x73, 0x3A, 0x20, 0x25, 0x30, 0x32, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x70, 0x22, 0x17, 0x00, +0x0C, 0x00, 0x00, 0x00, 0x9B, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x20, 0x28, 0x25, 0x73, 0x29, 0x20, 0x61, 0x74, 0x20, +0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x9B, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x20, 0x28, 0x25, 0x73, +0x29, 0x20, 0x61, 0x74, 0x20, 0x25, 0x73, 0x3A, 0x25, 0x64, 0x0A, 0x00, 0x45, 0x72, 0x72, 0x3A, 0x20, 0x55, 0x46, 0x20, +0x68, 0x6F, 0x73, 0x74, 0x20, 0x72, 0x78, 0x20, 0x62, 0x75, 0x66, 0x66, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x0D, 0x0A, 0x00, +0x09, 0x2D, 0x20, 0x00, 0x25, 0x73, 0x25, 0x73, 0x25, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, +0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x00, 0x00, 0x25, 0x30, 0x38, 0x78, 0x3A, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, +0x58, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x20, 0x25, +0x30, 0x32, 0x58, 0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x30, 0x34, 0x58, 0x00, 0x00, 0x00, +0x20, 0x25, 0x30, 0x32, 0x58, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x68, 0x65, 0x6C, +0x70, 0x20, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0x00, 0x68, 0x65, 0x6C, 0x70, 0x00, 0x00, 0x00, 0x00, 0x20, 0x72, 0x20, 0x61, +0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x20, 0x3C, 0x73, 0x7A, 0x3E, 0x00, 0x00, 0x20, 0x77, 0x20, 0x61, +0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x00, 0x77, 0x00, 0x00, 0x00, 0x20, 0x64, 0x62, 0x67, 0x20, 0x6D, 0x73, 0x6B, +0x00, 0x00, 0x00, 0x00, 0x64, 0x6D, 0x00, 0x00, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, 0x28, 0x69, 0x6E, +0x20, 0x73, 0x29, 0x00, 0x77, 0x66, 0x63, 0x74, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x20, 0x63, 0x6D, 0x64, +0x5F, 0x66, 0x72, 0x65, 0x65, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x20, 0x65, 0x6D, 0x70, 0x74, 0x79, 0x0D, 0x0A, 0x00, 0x00, +0x61, 0x69, 0x63, 0x3E, 0x20, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x63, 0x6D, 0x64, 0x73, +0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x65, 0x64, 0x2E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x2A, 0x20, 0x54, +0x6F, 0x6F, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x61, 0x72, 0x67, 0x73, 0x20, 0x28, 0x6D, 0x61, 0x78, 0x2E, 0x20, 0x25, +0x64, 0x29, 0x20, 0x2A, 0x2A, 0x0A, 0x00, 0x00, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x20, 0x63, 0x6F, 0x6D, 0x6D, +0x61, 0x6E, 0x64, 0x20, 0x27, 0x25, 0x73, 0x27, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x25, +0x73, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0D, 0x0A, 0x00, 0x00, +0x63, 0x75, 0x72, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, +0x63, 0x66, 0x67, 0x20, 0x64, 0x62, 0x67, 0x5F, 0x6D, 0x73, 0x6B, 0x3A, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x00, +0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, 0x73, 0x0A, 0x00, 0x00, 0x00, 0x69, 0x6E, 0x76, 0x61, +0x6C, 0x69, 0x64, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, +0x65, 0x3A, 0x0A, 0x20, 0x20, 0x72, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x3C, 0x63, 0x6E, 0x74, 0x3E, 0x0A, 0x00, 0x00, +0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x0D, 0x0A, 0x00, +0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x32, 0x58, 0x0D, 0x0A, 0x00, +0x5B, 0x30, 0x78, 0x25, 0x30, 0x38, 0x58, 0x5D, 0x20, 0x3D, 0x20, 0x30, 0x78, 0x25, 0x30, 0x34, 0x58, 0x0D, 0x0A, 0x00, +0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x20, 0x77, 0x20, 0x61, 0x64, 0x64, 0x72, 0x20, 0x76, 0x61, 0x6C, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x3A, 0x0A, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x76, 0x61, 0x6C, +0x28, 0x69, 0x6E, 0x20, 0x73, 0x29, 0x0A, 0x00, 0x63, 0x75, 0x72, 0x20, 0x77, 0x66, 0x63, 0x74, 0x3A, 0x20, 0x25, 0x75, +0x73, 0x0A, 0x00, 0x00, 0x63, 0x66, 0x67, 0x20, 0x77, 0x66, 0x63, 0x74, 0x20, 0x25, 0x75, 0x73, 0x0A, 0x00, 0x00, 0x00, +0x77, 0x66, 0x63, 0x74, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x0A, 0x00, 0x00, +0x08, 0x20, 0x08, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x07, 0x00, 0x50, +0xF2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, +0x5F, 0x67, 0x65, 0x74, 0x28, 0x64, 0x65, 0x73, 0x74, 0x5F, 0x69, 0x64, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x45, 0x5F, +0x42, 0x55, 0x53, 0x59, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x5F, 0x6D, 0x67, 0x6D, 0x74, 0x5F, 0x65, 0x6E, 0x76, +0x2E, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x5F, 0x76, 0x69, 0x66, 0x20, 0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, +0x4C, 0x49, 0x44, 0x5F, 0x56, 0x49, 0x46, 0x5F, 0x49, 0x44, 0x58, 0x00, 0xD8, 0x22, 0x17, 0x00, 0x18, 0x00, 0x00, 0x00, +0x62, 0x69, 0x74, 0x5F, 0x70, 0x6F, 0x73, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, +0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2D, 0x3E, 0x6C, 0x65, 0x6E, 0x67, 0x74, +0x68, 0x20, 0x21, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, +0x45, 0x29, 0x00, 0x00, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x56, 0x48, 0x54, 0x29, 0x00, +0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x5F, 0x43, 0x41, 0x50, 0x41, 0x28, 0x48, 0x54, 0x29, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, +0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x74, 0x78, 0x74, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, +0x63, 0x75, 0x72, 0x72, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x73, 0x73, 0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x6D, 0x69, 0x63, 0x5F, 0x63, 0x61, 0x6C, 0x63, 0x5F, 0x70, 0x74, 0x72, 0x2D, 0x3E, 0x6C, 0x61, 0x73, 0x74, 0x5F, 0x6D, +0x5F, 0x69, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x20, 0x34, 0x00, 0x00, 0x72, 0x65, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x76, 0x69, 0x66, 0x2D, 0x3E, 0x75, 0x2E, 0x73, 0x74, 0x61, 0x2E, 0x61, 0x70, 0x5F, 0x69, 0x64, +0x20, 0x3D, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, +0x63, 0x6F, 0x6E, 0x6E, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0x20, 0x69, 0x6E, 0x64, 0x0D, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, +0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, +0x20, 0x53, 0x4D, 0x5F, 0x53, 0x43, 0x41, 0x4E, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, +0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, +0x20, 0x53, 0x4D, 0x5F, 0x4A, 0x4F, 0x49, 0x4E, 0x49, 0x4E, 0x47, 0x00, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x3A, 0x20, 0x25, +0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x3A, 0x25, 0x34, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x28, 0x6B, 0x65, 0x5F, +0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, +0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, +0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, +0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, +0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, +0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, +0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, +0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, +0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, +0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, +0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, +0x47, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, +0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, +0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, +0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, +0x20, 0x53, 0x4D, 0x5F, 0x44, 0x49, 0x53, 0x43, 0x4F, 0x4E, 0x4E, 0x45, 0x43, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x00, 0x00, +0x73, 0x6D, 0x20, 0x63, 0x6F, 0x65, 0x78, 0x20, 0x74, 0x73, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x0D, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, +0x4B, 0x5F, 0x53, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x53, 0x4D, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x41, 0x44, 0x44, 0x49, +0x4E, 0x47, 0x00, 0x00, 0x98, 0x23, 0x17, 0x00, 0x15, 0x00, 0x00, 0x00, 0x74, 0x78, 0x20, 0x63, 0x66, 0x6D, 0x3A, 0x25, +0x64, 0x2C, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, +0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x73, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, 0x6E, +0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, 0x72, 0x65, 0x6F, 0x75, 0x72, +0x63, 0x65, 0x73, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x2F, 0x64, 0x69, 0x73, 0x61, 0x73, +0x73, 0x6F, 0x63, 0x3A, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x63, +0x74, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x3A, +0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x61, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x61, 0x75, 0x74, 0x68, +0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x6F, +0x63, 0x5F, 0x72, 0x73, 0x70, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, +0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x61, 0x20, +0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x61, 0x75, +0x74, 0x68, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x3A, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6F, 0x6E, 0x20, 0x63, +0x6F, 0x64, 0x65, 0x20, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x42, 0x53, 0x53, 0x5F, 0x43, 0x41, 0x50, 0x41, +0x28, 0x62, 0x73, 0x73, 0x2C, 0x20, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x29, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x03, 0x00, +0x00, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, 0x73, 0x6D, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x5F, +0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x00, 0x73, 0x6D, 0x5F, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x5F, 0x72, 0x65, 0x71, +0x5F, 0x73, 0x65, 0x6E, 0x64, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, +0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x43, +0x4E, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, +0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, +0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, +0x53, 0x53, 0x5F, 0x50, 0x41, 0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, +0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, +0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x20, 0x7C, 0x7C, +0x20, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, +0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, +0x29, 0x00, 0x00, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, +0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x42, 0x53, 0x53, 0x5F, 0x50, 0x41, +0x52, 0x41, 0x4D, 0x5F, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, +0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, 0x50, +0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x00, 0x00, 0x28, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, +0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x41, +0x50, 0x4D, 0x5F, 0x53, 0x54, 0x4F, 0x50, 0x50, 0x49, 0x4E, 0x47, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6B, 0x65, 0x5F, +0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x41, 0x50, 0x4D, 0x29, 0x20, +0x3D, 0x3D, 0x20, 0x41, 0x50, 0x4D, 0x5F, 0x49, 0x44, 0x4C, 0x45, 0x29, 0x00, 0x00, 0x00, 0x00, 0x61, 0x70, 0x20, 0x73, +0x74, 0x6F, 0x70, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x63, 0x6F, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x5F, 0x69, 0x73, 0x5F, 0x65, +0x6D, 0x70, 0x74, 0x79, 0x28, 0x26, 0x61, 0x70, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x62, 0x73, 0x73, 0x5F, 0x63, 0x6F, +0x6E, 0x66, 0x69, 0x67, 0x29, 0x00, 0x00, 0x00, 0x40, 0x24, 0x17, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, +0x75, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x3A, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, +0x75, 0x20, 0x69, 0x64, 0x6C, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x0D, 0x0A, 0x00, +0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, +0x69, 0x65, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x63, 0x61, +0x6E, 0x75, 0x20, 0x72, 0x65, 0x71, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x21, 0x4D, 0x41, 0x43, +0x5F, 0x41, 0x44, 0x44, 0x52, 0x5F, 0x47, 0x52, 0x4F, 0x55, 0x50, 0x28, 0x26, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x2D, 0x3E, +0x62, 0x73, 0x73, 0x69, 0x64, 0x29, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x20, 0x76, 0x6E, 0x64, 0x72, 0x20, 0x69, +0x65, 0x0D, 0x0A, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x63, 0x65, 0x6C, 0x20, 0x63, 0x66, 0x6D, 0x20, +0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x24, 0x17, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC8, 0x24, 0x17, 0x00, +0x05, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x17, 0x00, 0x07, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x63, 0x6F, +0x6E, 0x66, 0x69, 0x72, 0x6D, 0x3A, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x5B, 0x48, 0x49, 0x44, +0x44, 0x45, 0x4E, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x2D, 0x00, 0x6A, 0x6F, 0x69, 0x6E, +0x3A, 0x25, 0x73, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x66, 0x69, 0x78, 0x3D, 0x25, 0x78, 0x2C, 0x20, 0x6E, 0x6F, 0x5F, 0x73, +0x63, 0x68, 0x65, 0x64, 0x75, 0x6C, 0x65, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x20, 0x25, 0x64, 0x20, +0x25, 0x64, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x20, 0x25, 0x78, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x00, +0x28, 0x69, 0x65, 0x5F, 0x62, 0x75, 0x66, 0x20, 0x2D, 0x20, 0x43, 0x50, 0x55, 0x32, 0x48, 0x57, 0x28, 0x69, 0x65, 0x2D, +0x3E, 0x62, 0x75, 0x66, 0x29, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x53, 0x43, 0x41, 0x4E, 0x5F, 0x4D, 0x41, 0x58, 0x5F, 0x49, +0x45, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, 0x75, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x3A, +0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, +0x72, 0x70, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x69, 0x70, 0x3D, 0x25, 0x78, 0x2E, 0x20, 0x76, 0x69, 0x66, 0x20, 0x69, 0x70, +0x3D, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x20, 0x61, 0x72, 0x70, 0x72, 0x65, 0x73, 0x70, 0x0A, 0x00, +0x72, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x5F, 0x64, 0x65, 0x73, 0x63, 0x2D, 0x3E, 0x76, 0x61, 0x6C, 0x2E, 0x73, 0x74, +0x61, 0x74, 0x75, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x20, 0x73, +0x74, 0x61, 0x74, 0x3A, 0x25, 0x64, 0x00, 0x00, 0x54, 0x4B, 0x49, 0x50, 0x20, 0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, +0x0A, 0x00, 0x00, 0x00, 0x64, 0x65, 0x66, 0x72, 0x61, 0x67, 0x20, 0x21, 0x3D, 0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, +0x72, 0x78, 0x5F, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, 0x6E, +0x74, 0x00, 0x00, 0x00, 0x6F, 0x6C, 0x64, 0x5F, 0x77, 0x69, 0x6E, 0x5F, 0x62, 0x61, 0x72, 0x20, 0x64, 0x65, 0x74, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x2D, 0x3E, 0x6F, 0x6F, 0x6F, 0x5F, 0x70, 0x6B, 0x74, 0x5F, 0x63, +0x6E, 0x74, 0x3C, 0x3D, 0x36, 0x34, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x64, 0x65, 0x61, +0x75, 0x74, 0x68, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x74, 0x61, 0x73, 0x6B, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x21, 0x3D, 0x20, +0x30, 0x78, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6D, 0x61, 0x63, 0x68, 0x64, 0x72, 0x5F, 0x6C, 0x65, 0x6E, 0x67, +0x74, 0x68, 0x20, 0x26, 0x20, 0x30, 0x78, 0x33, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x72, 0x78, 0x20, 0x65, +0x61, 0x70, 0x6F, 0x6C, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x50, 0x20, +0x49, 0x43, 0x56, 0x20, 0x45, 0x52, 0x52, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x72, 0x65, 0x6F, 0x72, 0x64, 0x20, 0x21, 0x3D, +0x20, 0x4E, 0x55, 0x4C, 0x4C, 0x00, 0x00, 0x00, 0x72, 0x78, 0x75, 0x5F, 0x63, 0x6E, 0x74, 0x72, 0x6C, 0x5F, 0x73, 0x70, +0x75, 0x72, 0x69, 0x6F, 0x75, 0x73, 0x5F, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x74, 0x78, 0x75, 0x20, +0x64, 0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x3A, 0x20, 0x25, 0x64, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x64, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x6D, 0x69, 0x74, 0x20, 0x74, 0x78, 0x75, 0x20, 0x64, +0x69, 0x73, 0x63, 0x61, 0x72, 0x64, 0x0A, 0x00, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x66, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x3A, +0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x68, 0x6F, 0x73, 0x74, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, +0x21, 0x3D, 0x20, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, +0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x74, 0x69, 0x64, +0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x61, 0x64, 0x64, 0x62, 0x61, +0x5F, 0x72, 0x73, 0x70, 0x3A, 0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, +0x0A, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x72, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, +0x74, 0x69, 0x64, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, +0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x20, 0x74, 0x78, 0x5F, 0x64, 0x65, 0x6C, 0x62, 0x61, 0x3A, 0x74, 0x69, 0x64, 0x3D, +0x25, 0x64, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x69, 0x64, 0x78, 0x3D, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x2C, 0x25, 0x17, 0x00, +0x05, 0x00, 0x00, 0x00, 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x77, 0x69, 0x6E, 0x20, 0x73, 0x69, 0x6E, 0x63, 0x65, 0x20, 0x66, +0x6C, 0x75, 0x73, 0x68, 0x3A, 0x20, 0x73, 0x75, 0x63, 0x63, 0x3D, 0x25, 0x64, 0x2C, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x70, +0x61, 0x73, 0x74, 0x3D, 0x25, 0x64, 0x0A, 0x00, 0x6B, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5F, 0x67, 0x65, 0x74, +0x28, 0x4B, 0x45, 0x5F, 0x42, 0x55, 0x49, 0x4C, 0x44, 0x5F, 0x49, 0x44, 0x28, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x42, 0x41, +0x4D, 0x2C, 0x20, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x41, 0x4D, 0x5F, +0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x00, 0x00, 0x62, 0x61, 0x6D, 0x5F, 0x69, 0x64, 0x78, 0x20, 0x3C, 0x20, 0x42, 0x41, +0x4D, 0x5F, 0x49, 0x4E, 0x56, 0x41, 0x4C, 0x49, 0x44, 0x5F, 0x54, 0x41, 0x53, 0x4B, 0x5F, 0x49, 0x44, 0x58, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, +0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, +0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, +0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, +0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, +0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, +0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, +0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, +0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, +0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, +0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, +0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, +0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, +0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16, 0xC6, 0xF8, 0xEE, 0xF6, +0xFF, 0xD6, 0xDE, 0x91, 0x60, 0x02, 0xCE, 0x56, 0xE7, 0xB5, 0x4D, 0xEC, 0x8F, 0x1F, 0x89, 0xFA, 0xEF, 0xB2, 0x8E, 0xFB, +0x41, 0xB3, 0x5F, 0x45, 0x23, 0x53, 0xE4, 0x9B, 0x75, 0xE1, 0x3D, 0x4C, 0x6C, 0x7E, 0xF5, 0x83, 0x68, 0x51, 0xD1, 0xF9, +0xE2, 0xAB, 0x62, 0x2A, 0x08, 0x95, 0x46, 0x9D, 0x30, 0x37, 0x0A, 0x2F, 0x0E, 0x24, 0x1B, 0xDF, 0xCD, 0x4E, 0x7F, 0xEA, +0x12, 0x1D, 0x58, 0x34, 0x36, 0xDC, 0xB4, 0x5B, 0xA4, 0x76, 0xB7, 0x7D, 0x52, 0xDD, 0x5E, 0x13, 0xA6, 0xB9, 0x00, 0xC1, +0x40, 0xE3, 0x79, 0xB6, 0xD4, 0x8D, 0x67, 0x72, 0x94, 0x98, 0xB0, 0x85, 0xBB, 0xC5, 0x4F, 0xED, 0x86, 0x9A, 0x66, 0x11, +0x8A, 0xE9, 0x04, 0xFE, 0xA0, 0x78, 0x25, 0x4B, 0xA2, 0x5D, 0x80, 0x05, 0x3F, 0x21, 0x70, 0xF1, 0x63, 0x77, 0xAF, 0x42, +0x20, 0xE5, 0xFD, 0xBF, 0x81, 0x18, 0x26, 0xC3, 0xBE, 0x35, 0x88, 0x2E, 0x93, 0x55, 0xFC, 0x7A, 0xC8, 0xBA, 0x32, 0xE6, +0xC0, 0x19, 0x9E, 0xA3, 0x44, 0x54, 0x3B, 0x0B, 0x8C, 0xC7, 0x6B, 0x28, 0xA7, 0xBC, 0x16, 0xAD, 0xDB, 0x64, 0x74, 0x14, +0x92, 0x0C, 0x48, 0xB8, 0x9F, 0xBD, 0x43, 0xC4, 0x39, 0x31, 0xD3, 0xF2, 0xD5, 0x8B, 0x6E, 0xDA, 0x01, 0xB1, 0x9C, 0x49, +0xD8, 0xAC, 0xF3, 0xCF, 0xCA, 0xF4, 0x47, 0x10, 0x6F, 0xF0, 0x4A, 0x5C, 0x38, 0x57, 0x73, 0x97, 0xCB, 0xA1, 0xE8, 0x3E, +0x96, 0x61, 0x0D, 0x0F, 0xE0, 0x7C, 0x71, 0xCC, 0x90, 0x06, 0xF7, 0x1C, 0xC2, 0x6A, 0xAE, 0x69, 0x17, 0x99, 0x3A, 0x27, +0xD9, 0xEB, 0x2B, 0x22, 0xD2, 0xA9, 0x07, 0x33, 0x2D, 0x3C, 0x15, 0xC9, 0x87, 0xAA, 0x50, 0xA5, 0x03, 0x59, 0x09, 0x1A, +0x65, 0xD7, 0x84, 0xD0, 0x82, 0x29, 0x5A, 0x1E, 0x7B, 0xA8, 0x6D, 0x2C, 0xA5, 0x84, 0x99, 0x8D, 0x0D, 0xBD, 0xB1, 0x54, +0x50, 0x03, 0xA9, 0x7D, 0x19, 0x62, 0xE6, 0x9A, 0x45, 0x9D, 0x40, 0x87, 0x15, 0xEB, 0xC9, 0x0B, 0xEC, 0x67, 0xFD, 0xEA, +0xBF, 0xF7, 0x96, 0x5B, 0xC2, 0x1C, 0xAE, 0x6A, 0x5A, 0x41, 0x02, 0x4F, 0x5C, 0xF4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3F, +0x0C, 0x52, 0x65, 0x5E, 0x28, 0xA1, 0x0F, 0xB5, 0x09, 0x36, 0x9B, 0x3D, 0x26, 0x69, 0xCD, 0x9F, 0x1B, 0x9E, 0x74, 0x2E, +0x2D, 0xB2, 0xEE, 0xFB, 0xF6, 0x4D, 0x61, 0xCE, 0x7B, 0x3E, 0x71, 0x97, 0xF5, 0x68, 0x00, 0x2C, 0x60, 0x1F, 0xC8, 0xED, +0xBE, 0x46, 0xD9, 0x4B, 0xDE, 0xD4, 0xE8, 0x4A, 0x6B, 0x2A, 0xE5, 0x16, 0xC5, 0xD7, 0x55, 0x94, 0xCF, 0x10, 0x06, 0x81, +0xF0, 0x44, 0xBA, 0xE3, 0xF3, 0xFE, 0xC0, 0x8A, 0xAD, 0xBC, 0x48, 0x04, 0xDF, 0xC1, 0x75, 0x63, 0x30, 0x1A, 0x0E, 0x6D, +0x4C, 0x14, 0x35, 0x2F, 0xE1, 0xA2, 0xCC, 0x39, 0x57, 0xF2, 0x82, 0x47, 0xAC, 0xE7, 0x2B, 0x95, 0xA0, 0x98, 0xD1, 0x7F, +0x66, 0x7E, 0xAB, 0x83, 0xCA, 0x29, 0xD3, 0x3C, 0x79, 0xE2, 0x1D, 0x76, 0x3B, 0x56, 0x4E, 0x1E, 0xDB, 0x0A, 0x6C, 0xE4, +0x5D, 0x6E, 0xEF, 0xA6, 0xA8, 0xA4, 0x37, 0x8B, 0x32, 0x43, 0x59, 0xB7, 0x8C, 0x64, 0xD2, 0xE0, 0xB4, 0xFA, 0x07, 0x25, +0xAF, 0x8E, 0xE9, 0x18, 0xD5, 0x88, 0x6F, 0x72, 0x24, 0xF1, 0xC7, 0x51, 0x23, 0x7C, 0x9C, 0x21, 0xDD, 0xDC, 0x86, 0x85, +0x90, 0x42, 0xC4, 0xAA, 0xD8, 0x05, 0x01, 0x12, 0xA3, 0x5F, 0xF9, 0xD0, 0x91, 0x58, 0x27, 0xB9, 0x38, 0x13, 0xB3, 0x33, +0xBB, 0x70, 0x89, 0xA7, 0xB6, 0x22, 0x92, 0x20, 0x49, 0xFF, 0x78, 0x7A, 0x8F, 0xF8, 0x80, 0x17, 0xDA, 0x31, 0xC6, 0xB8, +0xC3, 0xB0, 0x77, 0x11, 0xCB, 0xFC, 0xD6, 0x3A, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x61, 0x74, 0x74, 0x65, 0x6D, +0x70, 0x74, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x72, 0x73, 0x2D, 0x3E, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, +0x73, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x3D, 0x20, 0x46, 0x4F, +0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, +0x54, 0x5F, 0x4D, 0x46, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3C, +0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x00, 0x28, 0x66, 0x6F, 0x72, +0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, +0x5F, 0x48, 0x54, 0x5F, 0x4D, 0x46, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, +0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x48, 0x54, 0x5F, 0x47, +0x46, 0x29, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, +0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x20, 0x7C, 0x7C, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, +0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, +0x4F, 0x4E, 0x5F, 0x48, 0x54, 0x00, 0x00, 0x00, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, +0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x56, 0x48, 0x54, 0x00, 0x28, 0x66, 0x6F, 0x72, +0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, +0x5F, 0x48, 0x45, 0x5F, 0x53, 0x55, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, +0x6F, 0x64, 0x20, 0x3D, 0x3D, 0x20, 0x46, 0x4F, 0x52, 0x4D, 0x41, 0x54, 0x4D, 0x4F, 0x44, 0x5F, 0x4E, 0x4F, 0x4E, 0x5F, +0x48, 0x54, 0x29, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x00, +0x73, 0x67, 0x69, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, +0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, +0x6D, 0x63, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, +0x6D, 0x69, 0x6E, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, +0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, +0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x6C, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, 0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, +0x29, 0x00, 0x00, 0x00, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, +0x73, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x73, 0x68, 0x6F, 0x72, 0x74, 0x5F, +0x67, 0x69, 0x00, 0x00, 0x62, 0x77, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, +0x6D, 0x61, 0x78, 0x00, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, +0x5F, 0x73, 0x73, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, 0x63, +0x73, 0x5F, 0x6D, 0x61, 0x78, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, +0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x74, 0x5B, 0x6E, 0x73, 0x73, 0x5D, 0x20, 0x26, 0x20, 0x43, 0x4F, 0x5F, 0x42, 0x49, +0x54, 0x28, 0x6D, 0x63, 0x73, 0x29, 0x29, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, 0x37, 0x20, 0x2B, 0x20, +0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x76, 0x68, 0x74, +0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, 0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, +0x5F, 0x56, 0x48, 0x54, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, 0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, +0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, +0x3D, 0x20, 0x42, 0x57, 0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x28, 0x6E, 0x73, 0x73, +0x20, 0x3D, 0x3D, 0x20, 0x33, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x36, 0x29, +0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, +0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, +0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x21, 0x3D, 0x20, 0x32, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, +0x73, 0x20, 0x21, 0x3D, 0x20, 0x35, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x00, 0x28, 0x28, 0x6D, 0x63, +0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, +0x5F, 0x38, 0x30, 0x4D, 0x48, 0x5A, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x35, +0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x00, 0x28, 0x28, 0x6D, 0x63, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x39, 0x29, 0x20, +0x26, 0x26, 0x20, 0x28, 0x62, 0x77, 0x20, 0x3D, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x29, +0x20, 0x26, 0x26, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3D, 0x3D, 0x20, 0x32, 0x29, 0x29, 0x20, 0x3D, 0x3D, 0x20, 0x30, +0x00, 0x00, 0x00, 0x00, 0x67, 0x69, 0x20, 0x3C, 0x3D, 0x20, 0x32, 0x00, 0x6D, 0x63, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x28, +0x37, 0x20, 0x2B, 0x20, 0x32, 0x20, 0x2A, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x61, 0x74, 0x65, +0x5F, 0x6D, 0x61, 0x70, 0x2E, 0x68, 0x65, 0x20, 0x3E, 0x3E, 0x20, 0x28, 0x6E, 0x73, 0x73, 0x20, 0x3C, 0x3C, 0x20, 0x31, +0x29, 0x20, 0x26, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x48, 0x45, 0x5F, 0x4D, 0x43, 0x53, 0x5F, 0x4D, 0x41, 0x50, 0x5F, 0x4D, +0x53, 0x4B, 0x29, 0x29, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x61, +0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3E, 0x3D, 0x20, 0x31, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, +0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x52, 0x43, 0x5F, 0x4D, 0x41, 0x58, 0x5F, +0x4E, 0x5F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, +0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x42, 0x57, 0x5F, 0x31, 0x36, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, +0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, 0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x20, 0x38, 0x00, 0x00, 0x00, 0x00, +0x73, 0x74, 0x61, 0x2D, 0x3E, 0x73, 0x74, 0x61, 0x69, 0x64, 0x20, 0x3C, 0x20, 0x4E, 0x58, 0x5F, 0x52, 0x45, 0x4D, 0x4F, +0x54, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x5F, 0x4D, 0x41, 0x58, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, +0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x32, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, +0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, +0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, +0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, +0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, +0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x3D, 0x20, 0x48, 0x57, 0x5F, 0x52, 0x41, 0x54, 0x45, +0x5F, 0x31, 0x31, 0x4D, 0x42, 0x50, 0x53, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, +0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, +0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x29, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6D, +0x63, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x31, 0x30, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x6E, +0x6F, 0x5F, 0x73, 0x73, 0x20, 0x3C, 0x3D, 0x20, 0x33, 0x00, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, +0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, +0x45, 0x54, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x72, 0x5F, 0x69, 0x64, 0x78, +0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3C, 0x20, 0x4D, 0x41, 0x43, 0x5F, 0x52, 0x41, 0x54, 0x45, 0x53, 0x45, 0x54, 0x5F, 0x4C, +0x45, 0x4E, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x73, 0x73, 0x2D, 0x3E, 0x62, 0x77, 0x5F, 0x6D, 0x61, 0x78, 0x20, 0x3D, 0x3D, +0x20, 0x42, 0x57, 0x5F, 0x32, 0x30, 0x4D, 0x48, 0x5A, 0x00, 0x00, 0x00, 0x25, 0x73, 0x3A, 0x20, 0x73, 0x74, 0x61, 0x74, +0x69, 0x6F, 0x6E, 0x5F, 0x69, 0x64, 0x3D, 0x25, 0x69, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x5F, 0x6D, 0x6F, 0x64, +0x3D, 0x25, 0x69, 0x20, 0x70, 0x72, 0x65, 0x5F, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x25, 0x69, 0x20, 0x73, 0x68, 0x6F, 0x72, +0x74, 0x5F, 0x67, 0x69, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x61, 0x78, 0x5F, 0x62, 0x77, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, +0x25, 0x73, 0x3A, 0x20, 0x6E, 0x73, 0x73, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6D, 0x63, 0x73, 0x5F, 0x6D, +0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x72, 0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x69, 0x6E, 0x3D, 0x25, 0x69, 0x20, 0x72, +0x5F, 0x69, 0x64, 0x78, 0x5F, 0x6D, 0x61, 0x78, 0x3D, 0x25, 0x69, 0x20, 0x6E, 0x6F, 0x5F, 0x73, 0x61, 0x6D, 0x70, 0x6C, +0x65, 0x73, 0x3D, 0x25, 0x69, 0x0A, 0x00, 0x00, 0x72, 0x63, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x20, 0x7C, 0x9F, 0x00, +0x20, 0xF3, 0xA0, 0x00, 0xA0, 0x17, 0x52, 0x00, 0xA0, 0x8E, 0x53, 0x00, 0xF8, 0x52, 0x23, 0x00, 0xF8, 0xC9, 0x24, 0x00, +0x18, 0xF5, 0x15, 0x00, 0x18, 0x6C, 0x17, 0x00, 0xF9, 0x06, 0x11, 0x00, 0x62, 0x07, 0x12, 0x00, 0x35, 0x08, 0x14, 0x00, +0xD1, 0x10, 0x04, 0x00, 0x0A, 0x4E, 0x04, 0x00, 0x7D, 0xC8, 0x04, 0x00, 0x7D, 0x83, 0x08, 0x00, 0xB1, 0x03, 0x09, 0x00, +0x1A, 0x04, 0x0A, 0x00, 0x68, 0x08, 0x02, 0x00, 0x05, 0x27, 0x02, 0x00, 0x3F, 0x64, 0x02, 0x00, 0xFE, 0xAC, 0x05, 0x00, +0x76, 0x02, 0x06, 0x00, 0x67, 0xAD, 0x06, 0x00, 0xF0, 0x5A, 0x01, 0x00, 0x59, 0x6F, 0x01, 0x00, 0x2A, 0x98, 0x01, 0x00, +0xBE, 0x41, 0x04, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x0D, 0x02, 0x05, 0x00, 0x34, 0x04, 0x01, 0x00, 0x83, 0x13, 0x01, 0x00, +0x1F, 0x32, 0x01, 0x00, 0x7F, 0xD6, 0x02, 0x00, 0x3B, 0x01, 0x03, 0x00, 0xB3, 0x56, 0x03, 0x00, 0x78, 0xAD, 0x00, 0x00, +0xAC, 0xB7, 0x00, 0x00, 0x15, 0xCC, 0x00, 0x00, 0xDF, 0x20, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x07, 0x81, 0x02, 0x00, +0x1A, 0x82, 0x00, 0x00, 0xC1, 0x89, 0x00, 0x00, 0x10, 0x99, 0x00, 0x00, 0x55, 0xE4, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, +0xCD, 0x39, 0x02, 0x00, 0xA5, 0x73, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, 0x0E, 0x88, 0x00, 0x00, 0xE6, 0xB3, 0x01, 0x00, +0x8A, 0xCD, 0x01, 0x00, 0xD2, 0x00, 0x02, 0x00, 0x15, 0x68, 0x00, 0x00, 0x34, 0x6E, 0x00, 0x00, 0x73, 0x7A, 0x00, 0x00, +0x3F, 0x6B, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0xBC, 0x56, 0x00, 0x00, 0xD6, 0x5B, 0x00, 0x00, +0x0A, 0x66, 0x00, 0x00, 0xEC, 0x46, 0x01, 0x00, 0x27, 0x5A, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0x11, 0x4E, 0x00, 0x00, +0xA8, 0x52, 0x00, 0x00, 0xD7, 0x5B, 0x00, 0x00, 0x99, 0x22, 0x01, 0x00, 0xB1, 0x33, 0x01, 0x00, 0xE1, 0x55, 0x01, 0x00, +0x63, 0x45, 0x00, 0x00, 0x78, 0x49, 0x00, 0x00, 0xA2, 0x51, 0x00, 0x00, 0x8A, 0x05, 0x01, 0x00, 0xEC, 0x14, 0x01, 0x00, +0xB1, 0x33, 0x01, 0x00, 0x74, 0x3E, 0x00, 0x00, 0x21, 0x42, 0x00, 0x00, 0x7A, 0x49, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, +0x3C, 0x5C, 0x29, 0x00, 0xB4, 0xF4, 0x2D, 0x00, 0x00, 0x88, 0x13, 0x00, 0x1E, 0xAE, 0x14, 0x00, 0x5A, 0xFA, 0x16, 0x00, +0x55, 0x05, 0x0D, 0x00, 0x69, 0xC9, 0x0D, 0x00, 0x91, 0x51, 0x0F, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x0F, 0x57, 0x0A, 0x00, +0x2D, 0x7D, 0x0B, 0x00, 0xAA, 0x82, 0x06, 0x00, 0xB4, 0xE4, 0x06, 0x00, 0xC8, 0xA8, 0x07, 0x00, 0x00, 0xE2, 0x04, 0x00, +0x87, 0x2B, 0x05, 0x00, 0x96, 0xBE, 0x05, 0x00, 0x1C, 0x57, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x30, 0x1B, 0x05, 0x00, +0x00, 0xE8, 0x03, 0x00, 0xD2, 0x22, 0x04, 0x00, 0x78, 0x98, 0x04, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, +0x64, 0xD4, 0x03, 0x00, 0x00, 0xEE, 0x02, 0x00, 0x1E, 0x1A, 0x03, 0x00, 0x5A, 0x72, 0x03, 0x00, 0xAA, 0x9A, 0x02, 0x00, +0xE1, 0xC1, 0x02, 0x00, 0x50, 0x10, 0x03, 0x00, 0x00, 0x58, 0x02, 0x00, 0x4B, 0x7B, 0x02, 0x00, 0xE1, 0xC1, 0x02, 0x00, +0x00, 0x04, 0xA6, 0x00, 0x00, 0xC8, 0xAF, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, +0x00, 0xA8, 0x61, 0x00, 0xAA, 0x56, 0x37, 0x00, 0x00, 0x98, 0x3A, 0x00, 0xAA, 0x1A, 0x41, 0x00, 0x00, 0x81, 0x29, 0x00, +0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, +0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x38, 0x72, 0x12, 0x00, 0x00, 0x88, 0x13, 0x00, +0x8E, 0xB3, 0x15, 0x00, 0x00, 0x9A, 0x10, 0x00, 0x00, 0x94, 0x11, 0x00, 0x00, 0x88, 0x13, 0x00, 0xAA, 0xD5, 0x0D, 0x00, +0x00, 0xA6, 0x0E, 0x00, 0xAA, 0x46, 0x10, 0x00, 0x80, 0x73, 0x0C, 0x00, 0x00, 0x2F, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, +0x55, 0x11, 0x0B, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x55, 0x05, 0x0D, 0x00, 0x00, 0xF6, 0x09, 0x00, 0x00, 0x8C, 0x0A, 0x00, +0x00, 0xB8, 0x0B, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x81, 0x29, 0x00, +0x00, 0xF2, 0x2B, 0x00, 0x00, 0xD4, 0x30, 0x00, 0x55, 0xAB, 0x1B, 0x00, 0x00, 0x4C, 0x1D, 0x00, 0x55, 0x8D, 0x20, 0x00, +0x80, 0xC0, 0x14, 0x00, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xAA, 0xD5, 0x0D, 0x00, 0x00, 0xA6, 0x0E, 0x00, +0xAA, 0x46, 0x10, 0x00, 0x40, 0x60, 0x0A, 0x00, 0x80, 0xFC, 0x0A, 0x00, 0x00, 0x35, 0x0C, 0x00, 0x1C, 0x39, 0x09, 0x00, +0x00, 0xC4, 0x09, 0x00, 0xC7, 0xD9, 0x0A, 0x00, 0x00, 0x4D, 0x08, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x00, 0xC4, 0x09, 0x00, +0xD5, 0xEA, 0x06, 0x00, 0x00, 0x53, 0x07, 0x00, 0x55, 0x23, 0x08, 0x00, 0xC0, 0x39, 0x06, 0x00, 0x80, 0x97, 0x06, 0x00, +0x00, 0x53, 0x07, 0x00, 0xAA, 0x88, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0xAA, 0x82, 0x06, 0x00, 0x00, 0xFB, 0x04, 0x00, +0x00, 0x46, 0x05, 0x00, 0x00, 0xDC, 0x05, 0x00, 0x3B, 0x89, 0x16, 0x00, 0x4F, 0x48, 0x14, 0x00, 0xC7, 0xD9, 0x0A, 0x00, +0x00, 0xC4, 0x09, 0x00, 0x0D, 0x02, 0x05, 0x00, 0xD9, 0x81, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, +0x9E, 0x44, 0x0B, 0x00, 0x27, 0x24, 0x0A, 0x00, 0xE4, 0x6C, 0x05, 0x00, 0x00, 0xE2, 0x04, 0x00, 0x07, 0x81, 0x02, 0x00, +0xEC, 0x40, 0x02, 0x00, 0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x14, 0x83, 0x07, 0x00, 0xC5, 0xC2, 0x06, 0x00, +0xED, 0x9D, 0x03, 0x00, 0x55, 0x41, 0x03, 0x00, 0x5A, 0xAB, 0x01, 0x00, 0x9E, 0x80, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, +0x4F, 0xC0, 0x00, 0x00, 0x4F, 0xA2, 0x05, 0x00, 0x14, 0x12, 0x05, 0x00, 0x72, 0xB6, 0x02, 0x00, 0x00, 0x71, 0x02, 0x00, +0x83, 0x40, 0x01, 0x00, 0x76, 0x20, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x8A, 0xC1, 0x03, 0x00, +0x62, 0x61, 0x03, 0x00, 0xF7, 0xCE, 0x01, 0x00, 0xAB, 0xA0, 0x01, 0x00, 0xAD, 0xD5, 0x00, 0x00, 0x4F, 0xC0, 0x00, 0x00, +0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x27, 0xD1, 0x02, 0x00, 0x0A, 0x89, 0x02, 0x00, 0x39, 0x5B, 0x01, 0x00, +0x80, 0x38, 0x01, 0x00, 0x42, 0xA0, 0x00, 0x00, 0x3B, 0x90, 0x00, 0x00, 0x21, 0x50, 0x00, 0x00, 0x1E, 0x48, 0x00, 0x00, +0x07, 0x81, 0x02, 0x00, 0xEC, 0x40, 0x02, 0x00, 0xA4, 0x34, 0x01, 0x00, 0xC7, 0x15, 0x01, 0x00, 0x73, 0x8E, 0x00, 0x00, +0x35, 0x80, 0x00, 0x00, 0x3A, 0x47, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, 0xEC, 0x40, 0x02, 0x00, 0x3B, 0x07, 0x02, 0x00, +0xC7, 0x15, 0x01, 0x00, 0x00, 0xFA, 0x00, 0x00, 0x35, 0x80, 0x00, 0x00, 0x62, 0x73, 0x00, 0x00, 0x1A, 0x40, 0x00, 0x00, +0xB1, 0x39, 0x00, 0x00, 0xC5, 0xE0, 0x01, 0x00, 0xB1, 0xB0, 0x01, 0x00, 0x7B, 0xE7, 0x00, 0x00, 0x55, 0xD0, 0x00, 0x00, +0xD6, 0x6A, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x6B, 0x35, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0xB1, 0xB0, 0x01, 0x00, +0x6C, 0x85, 0x01, 0x00, 0x55, 0xD0, 0x00, 0x00, 0x80, 0xBB, 0x00, 0x00, 0x27, 0x60, 0x00, 0x00, 0x8A, 0x56, 0x00, 0x00, +0x14, 0x30, 0x00, 0x00, 0x45, 0x2B, 0x00, 0x00, 0x00, 0x6A, 0x18, 0x00, 0xE0, 0x4B, 0x10, 0x00, 0x00, 0x35, 0x0C, 0x00, +0xC0, 0x2D, 0x08, 0x00, 0x80, 0x1A, 0x06, 0x00, 0xE0, 0x16, 0x04, 0x00, 0x40, 0x0D, 0x03, 0x00, 0x20, 0xBF, 0x02, 0x00, +0x24, 0xCE, 0x15, 0x00, 0xB4, 0xCE, 0x15, 0x00, 0x94, 0xCD, 0x15, 0x00, 0xB8, 0xD0, 0x15, 0x00, 0x03, 0x00, 0x00, 0x00, +0x00, 0x28, 0x00, 0x00, 0x39, 0x4B, 0x15, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x15, 0x4C, 0x15, 0x00, 0x01, 0x10, 0x00, 0x00, +0xD5, 0x4B, 0x15, 0x00, 0x61, 0x76, 0x61, 0x69, 0x6C, 0x20, 0x3E, 0x3D, 0x20, 0x42, 0x43, 0x4E, 0x5F, 0x46, 0x49, 0x58, +0x45, 0x44, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x5F, 0x46, 0x49, 0x45, 0x4C, 0x44, 0x53, 0x5F, 0x4C, 0x45, 0x4E, 0x00, 0x00, +0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3C, 0x3D, 0x20, 0x62, 0x75, 0x66, 0x5F, 0x6C, 0x65, +0x6E, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x5F, 0x6C, 0x65, 0x6E, 0x20, 0x3E, 0x20, 0x30, 0x00, +0x21, 0x72, 0x6D, 0x5F, 0x6E, 0x6F, 0x5F, 0x6D, 0x6F, 0x72, 0x65, 0x5F, 0x6D, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x5F, +0x74, 0x6F, 0x5F, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x28, 0x29, 0x20, 0x7C, 0x7C, 0x20, 0x28, 0x72, 0x65, 0x71, 0x75, +0x65, 0x73, 0x74, 0x2D, 0x3E, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x73, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x3D, 0x20, +0x30, 0x29, 0x00, 0x00, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x63, 0x6E, +0x74, 0x20, 0x3C, 0x3D, 0x20, 0x43, 0x4F, 0x5F, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x28, 0x72, +0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x63, 0x68, 0x61, 0x6E, 0x5F, 0x6C, 0x69, 0x73, 0x74, 0x29, 0x00, 0x00, +0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2D, 0x3E, 0x74, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x3D, 0x20, 0x4D, 0x41, 0x43, +0x5F, 0x4D, 0x45, 0x41, 0x53, 0x5F, 0x52, 0x45, 0x51, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x42, 0x45, 0x41, 0x43, 0x4F, +0x4E, 0x00, 0x00, 0x00, 0x72, 0x6D, 0x5F, 0x65, 0x6E, 0x76, 0x2E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5F, 0x72, 0x65, +0x71, 0x75, 0x65, 0x73, 0x74, 0x20, 0x3E, 0x3D, 0x20, 0x30, 0x00, 0x00, 0x64, 0x69, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, +0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x34, 0x37, 0x3A, 0x31, 0x34, 0x20, 0x2D, 0x20, 0x67, 0x37, +0x34, 0x32, 0x30, 0x33, 0x31, 0x37, 0x31, 0x00, 0x76, 0x36, 0x2E, 0x34, 0x2E, 0x33, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, +0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, 0x9E, 0x46, 0x70, 0x47, 0xF8, 0xB5, 0x00, 0xBF, 0xF8, 0xBC, 0x08, 0xBC, +0x9E, 0x46, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x74, 0x04, 0x17, 0x00, 0xDC, 0x04, 0x17, 0x00, 0x44, 0x05, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x33, 0xCD, 0xAB, +0x34, 0x12, 0x6D, 0xE6, 0xEC, 0xDE, 0x05, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0E, 0x00, 0x00, 0x04, 0x0E, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x5B, +0x4B, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x32, 0x7B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, +0x26, 0x00, 0x00, 0xF8, 0x11, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x19, 0x48, 0x20, 0x00, 0x00, 0x9C, 0x91, 0x01, 0x00, 0x08, +0x00, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0A, 0x11, 0x44, 0x10, 0x08, 0x00, 0x80, 0x01, 0x38, 0x41, 0x46, 0x00, 0x0C, +0x14, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0x3C, 0x1A, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x38, 0x01, 0x00, 0x00, 0x40, 0x1D, 0x00, 0x00, 0x08, +0x8E, 0x00, 0x08, 0x38, 0x50, 0x00, 0x00, 0x14, 0x20, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x40, 0x7B, 0x00, 0x00, 0xA4, +0x01, 0x01, 0x00, 0x00, 0x9F, 0x33, 0x00, 0x30, 0x00, 0x07, 0x00, 0x41, 0x20, 0x44, 0x10, 0x04, 0x00, 0x00, 0x00, 0x90, +0x00, 0x00, 0x00, 0x49, 0x2F, 0x84, 0x0E, 0xF0, 0x2C, 0x84, 0x0E, 0xEC, 0x2C, 0x84, 0x0E, 0xEC, 0x32, 0x00, 0x00, 0x04, +0x00, 0x00, 0x00, 0x30, 0x01, 0x01, 0x00, 0x48, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x02, 0x02, 0x00, 0x48, +0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x46, 0x11, 0x00, 0x00, 0x04, 0x06, 0x00, 0x01, 0x58, +0x72, 0x04, 0x04, 0x3D, 0x39, 0x44, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, 0xDC, 0x44, 0x20, 0xDC, +0x3C, 0xD4, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0xC3, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, 0x00, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, 0x45, 0x44, 0x10, 0x04, +0x00, 0x80, 0x00, 0x38, 0x9C, 0x10, 0x00, 0x22, 0x48, 0x44, 0x10, 0x08, 0x00, 0x80, 0x00, 0x38, 0x9C, 0x50, 0xD4, 0x23, +0x17, 0x44, 0x10, 0x08, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x00, 0x00, 0x32, 0x63, 0x00, 0x00, 0x18, 0x60, 0x00, 0x00, 0x14, +0x51, 0x00, 0x00, 0x1C, 0x57, 0x00, 0x00, 0x10, 0x00, 0x80, 0x02, 0x38, 0x01, 0x00, 0x00, 0x0C, 0x66, 0x44, 0xD0, 0x08, +0x0F, 0x20, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x38, 0x01, 0x26, 0x00, 0x0C, +0x5A, 0x44, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x30, 0x30, 0x02, 0x02, 0x3D, 0x5D, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, +0x00, 0x01, 0x00, 0x3E, 0x66, 0x00, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x01, 0x16, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, +0x00, 0x80, 0x02, 0x38, 0x01, 0x0A, 0x00, 0x0C, 0x66, 0x44, 0x20, 0x34, 0x04, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0xFF, +0x7B, 0x00, 0x00, 0x08, 0x2F, 0x80, 0x00, 0x38, 0x00, 0x00, 0x00, 0x26, 0x6C, 0x00, 0x00, 0x08, 0xAF, 0x04, 0x04, 0x38, +0x10, 0x10, 0x19, 0x1F, 0x6F, 0x00, 0x00, 0x08, 0xAF, 0x0C, 0x00, 0x20, 0x71, 0x00, 0x00, 0x04, 0xAF, 0x0C, 0x00, 0x60, +0x79, 0x00, 0x70, 0x18, 0x77, 0x00, 0x00, 0x14, 0x75, 0x00, 0x00, 0x10, 0xAF, 0x0C, 0x14, 0x28, 0x84, 0x00, 0xB0, 0x09, +0xAF, 0x0C, 0x0A, 0x28, 0x84, 0x00, 0xB0, 0x09, 0xAF, 0x0C, 0x06, 0x28, 0x84, 0x00, 0xB0, 0x09, 0x86, 0x80, 0x04, 0x28, +0x7D, 0x00, 0x00, 0x08, 0x86, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x22, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, +0x01, 0xF1, 0xF1, 0x0E, 0x83, 0x48, 0x00, 0x36, 0x00, 0x00, 0x02, 0x28, 0x85, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, +0x31, 0x04, 0x04, 0x3D, 0x88, 0x00, 0x00, 0x08, 0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x8B, 0x00, 0x00, 0x08, +0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, 0x8E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, +0x91, 0x00, 0x00, 0x34, 0xCC, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x50, 0x94, 0x00, 0x00, 0x04, 0xFE, 0x95, 0x00, 0x38, +0x00, 0x00, 0x01, 0x32, 0x97, 0x00, 0x00, 0x04, 0xFE, 0x1F, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0x9B, 0x98, 0xC9, 0x6D, +0xB9, 0xD4, 0x19, 0xFC, 0x86, 0x01, 0x00, 0x30, 0x73, 0x03, 0x84, 0x3D, 0x9E, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0x0A, 0xA1, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x22, 0xA4, 0x00, 0x00, 0x04, +0x8E, 0x02, 0x00, 0x90, 0x01, 0x00, 0x01, 0x32, 0xAA, 0x00, 0x40, 0x8E, 0xB0, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x01, 0x00, 0x01, 0x32, 0xCB, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x01, 0x32, 0xB3, 0x00, 0x00, 0x04, +0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0xB6, 0x00, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, +0x97, 0x00, 0x00, 0x04, 0x86, 0x01, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0xBC, 0x00, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, +0x00, 0x00, 0x03, 0x29, 0xBF, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x9A, 0x00, 0x01, 0x01, 0x32, 0xC5, 0x00, 0x00, 0x7C, +0xB0, 0x00, 0x00, 0xCC, 0xB0, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x00, 0x30, 0x00, 0x01, 0x01, 0x32, +0xC8, 0x00, 0x00, 0x04, 0x8E, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x8E, 0x03, 0x00, 0x50, +0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x35, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x01, 0x38, 0x72, 0x04, 0x04, 0x3D, +0xD2, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, 0x41, 0xF1, 0xF1, 0x0E, 0xD5, 0x00, 0x00, 0x34, 0x04, 0x00, 0x04, 0x28, +0xD7, 0x00, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x28, 0xD9, 0x00, 0x00, 0x08, 0x8E, 0x01, 0x00, 0x30, 0x52, 0x00, 0xF1, 0x0E, +0xDC, 0x00, 0x00, 0x34, 0x8E, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x02, 0x38, +0x00, 0x00, 0x00, 0x32, 0xE2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x60, 0xE6, 0x00, 0x00, 0xD8, 0xE9, 0x00, 0x00, 0xD4, +0xEC, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x21, 0xF1, 0xF1, 0x0E, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, +0x21, 0x24, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, 0x00, 0x00, 0x00, 0x30, 0x21, 0x00, 0x00, 0x0C, 0xEF, 0x48, 0x00, 0x36, +0x00, 0x00, 0x02, 0x28, 0x7B, 0x00, 0x00, 0x08, 0xFE, 0x1E, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5A, 0xF5, 0x98, 0xC9, 0x6D, +0xF8, 0xD4, 0x19, 0xFC, 0x8E, 0x02, 0x00, 0x30, 0x40, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x8E, 0x02, 0xEE, 0x3A, +0x80, 0x00, 0x00, 0x32, 0xFB, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0x01, 0xF1, 0xF1, 0x0E, 0xFE, 0x48, 0x00, 0x36, +0x00, 0x00, 0x02, 0x28, 0x00, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x02, 0x38, 0x31, 0x04, 0x04, 0x3D, 0x03, 0x01, 0x00, 0x08, +0x8E, 0x00, 0x05, 0x38, 0x21, 0x18, 0x24, 0x1F, 0x06, 0x01, 0x00, 0x08, 0x8E, 0x00, 0x00, 0x30, 0x21, 0x30, 0x16, 0xA0, +0x09, 0x01, 0x00, 0x04, 0x8E, 0x00, 0x00, 0x30, 0x12, 0x00, 0xF1, 0x0E, 0x0C, 0x01, 0x00, 0x34, 0xF6, 0x14, 0x00, 0x30, +0x00, 0x00, 0x01, 0x32, 0x14, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x11, 0x01, 0x00, 0x04, 0xEC, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0x50, 0xF1, 0x00, 0x00, 0x04, 0xF6, 0x14, 0x00, 0x30, 0x00, 0x00, 0x03, 0x32, 0x17, 0x01, 0x00, 0x04, +0x86, 0x10, 0x00, 0x30, 0x73, 0x04, 0x84, 0x3D, 0x1A, 0x01, 0x00, 0x04, 0x8E, 0x10, 0x00, 0x50, 0x00, 0x00, 0xC0, 0x22, +0xCB, 0xC0, 0x47, 0x8E, 0x1E, 0x01, 0x30, 0xCB, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x04, 0x32, 0x21, 0x01, 0x00, 0x04, +0xB6, 0x19, 0x00, 0x30, 0x31, 0x04, 0x04, 0x3D, 0x24, 0x01, 0x00, 0x04, 0xB6, 0x19, 0x00, 0x30, 0x00, 0x00, 0x80, 0x22, +0x11, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x01, 0x00, 0x30, +0x73, 0x04, 0x84, 0x3D, 0x2D, 0x01, 0x00, 0x04, 0x8E, 0x03, 0x00, 0x50, 0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, +0x31, 0x01, 0x00, 0xC0, 0x0E, 0x80, 0x0C, 0x38, 0x00, 0x00, 0x00, 0xFF, 0x34, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x30, +0x03, 0xF1, 0xF1, 0x0F, 0x37, 0x01, 0x00, 0x34, 0x00, 0x00, 0x02, 0x28, 0x39, 0x01, 0x00, 0x08, 0x8E, 0x03, 0x00, 0x30, +0x00, 0x00, 0x00, 0x29, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x06, 0x00, 0x01, 0x58, 0x72, 0x04, 0x04, 0x3D, 0x43, 0x45, 0x20, 0xDC, 0xD2, 0xD4, 0x1D, 0x08, 0x06, 0x00, 0x0A, 0x48, +0xDC, 0x44, 0x20, 0xDC, 0x46, 0xD5, 0x1D, 0x08, 0x04, 0x00, 0x05, 0x38, 0x41, 0xF1, 0xF1, 0x0E, 0xDC, 0x44, 0x20, 0x34, +0x0E, 0x80, 0x02, 0x28, 0xDC, 0x00, 0x00, 0x08, 0x35, 0x00, 0x00, 0x48, 0x4A, 0x01, 0x00, 0x04, 0x8F, 0x63, 0x96, 0x78, +0x0F, 0x00, 0x00, 0x41, 0x4F, 0x01, 0x00, 0x8C, 0xC4, 0x50, 0x04, 0x08, 0x74, 0x45, 0x10, 0x90, 0x0F, 0x62, 0xC8, 0x88, +0x5A, 0x01, 0x00, 0xC0, 0x74, 0x45, 0x10, 0x90, 0x54, 0x45, 0x10, 0x08, 0x57, 0x45, 0x10, 0x94, 0x8F, 0x62, 0x00, 0x30, +0x00, 0x00, 0x00, 0x29, 0x7A, 0x51, 0x04, 0x94, 0x8F, 0x63, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x7A, 0x45, 0x10, 0x04, +0x05, 0xE0, 0x00, 0x38, 0x31, 0x01, 0x01, 0x3D, 0x5D, 0x45, 0x10, 0x08, 0x0F, 0x60, 0x32, 0xA8, 0x74, 0x45, 0x10, 0x90, +0x54, 0x01, 0x00, 0x08, 0x57, 0x45, 0x10, 0x94, 0x67, 0x45, 0x10, 0xC6, 0x63, 0x55, 0x18, 0xC4, 0x0F, 0xE0, 0x02, 0x58, +0x07, 0xEA, 0xEE, 0x0F, 0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x0F, 0xE0, 0x02, 0x58, 0x07, 0xEA, 0xEE, 0x0E, +0x74, 0x01, 0x00, 0x80, 0x6B, 0x45, 0x20, 0x34, 0x00, 0x40, 0x00, 0x30, 0x01, 0x00, 0x00, 0x33, 0x6E, 0x01, 0x00, 0x04, +0x05, 0x40, 0x03, 0x38, 0x73, 0x03, 0x03, 0x3D, 0x71, 0x01, 0x00, 0x08, 0x07, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x33, +0x74, 0x01, 0x00, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x29, 0x77, 0x51, 0x04, 0x94, 0x8F, 0x60, 0x00, 0x40, +0x7D, 0x45, 0x10, 0xA0, 0x7A, 0x45, 0x10, 0x04, 0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x11, 0x44, 0x10, 0x04, +0x8F, 0x60, 0x00, 0x30, 0x01, 0x01, 0x00, 0x64, 0x80, 0x45, 0x10, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x01, 0x00, 0x00, 0x42, +0x83, 0x01, 0x00, 0x04, 0x00, 0x80, 0x02, 0x38, 0x00, 0x00, 0x00, 0x32, 0x86, 0x45, 0x10, 0x08, 0x8F, 0x61, 0x0A, 0x28, +0x88, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x0A, 0x48, 0x8B, 0x01, 0x00, 0xBC, 0x8E, 0x01, 0x00, 0x08, 0x8F, 0x61, 0x00, 0x30, +0x01, 0x00, 0x00, 0x34, 0x05, 0x00, 0x00, 0x04, 0x8F, 0x61, 0x00, 0x30, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0x04, +0x8F, 0x00, 0x00, 0x30, 0x0F, 0xED, 0xEA, 0x0E, 0x94, 0x01, 0x00, 0x36, 0x00, 0x80, 0x03, 0x38, 0x00, 0x00, 0x00, 0x34, +0x97, 0x01, 0x00, 0x08, 0x05, 0x80, 0x02, 0x38, 0x02, 0x00, 0x01, 0x29, 0x9A, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, +0x9C, 0x20, 0x00, 0x22, 0x9D, 0x01, 0x00, 0x04, 0x8F, 0x02, 0x00, 0x30, 0x9C, 0x50, 0xD4, 0x23, 0xA0, 0x01, 0x00, 0x04, +0x8F, 0x02, 0x14, 0x28, 0xA2, 0x01, 0x00, 0x08, 0x8F, 0x02, 0x00, 0x30, 0x01, 0x02, 0x01, 0x43, 0xA5, 0x01, 0x00, 0x04, +0x8F, 0x12, 0x00, 0x30, 0x00, 0x01, 0x00, 0x32, 0xA8, 0x01, 0x00, 0x04, 0x8F, 0x13, 0xEE, 0x5A, 0x0F, 0x00, 0x00, 0x41, +0xAC, 0x01, 0x00, 0x7C, 0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x2C, 0x59, 0x00, 0x00, 0x00, 0x29, 0xB0, 0x01, 0x00, 0x8C, +0xF9, 0x00, 0x00, 0x08, 0x8F, 0x13, 0x00, 0x20, 0x11, 0x50, 0x04, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, +0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x72, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, +0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x7B, 0x76, 0x76, 0x00, 0x70, 0xF8, 0xF8, 0x1D, +0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x70, 0xF8, 0xF8, 0x1D, 0x85, 0x7E, 0x7E, 0x00, 0x76, 0xF8, 0xF4, 0x1D, +0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF4, 0x1D, 0x76, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, +0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8D, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, +0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x8A, 0x81, 0x81, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, +0x7C, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x40, 0x7E, 0x7E, 0x00, 0x7B, 0xF8, 0xF8, 0x1D, +0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x7B, 0xF8, 0xF8, 0x1D, 0x92, 0x8B, 0x8B, 0x00, 0x87, 0xF8, 0xF8, 0x1D, +0x89, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x87, 0xF8, 0xF8, 0x1D, 0x55, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x89, 0xF8, 0xF8, 0x1D, 0x54, 0x51, 0x51, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x88, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, +0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, +0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4F, 0x4F, 0x00, 0x4A, 0xF8, 0xF8, 0x1D, +0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, +0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x52, 0x4D, 0x4D, 0x00, 0x47, 0xF8, 0xF8, 0x1D, +0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x47, 0xF8, 0xF8, 0x1D, 0x55, 0x4F, 0x4F, 0x00, 0x4B, 0xF8, 0xF8, 0x1D, +0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x53, 0x4E, 0x4E, 0x00, 0x49, 0xF8, 0xF8, 0x1D, +0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x4D, 0x49, 0x49, 0x00, 0x44, 0xF8, 0xF8, 0x1D, +0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x44, 0xF8, 0xF8, 0x1D, 0x8F, 0x51, 0x51, 0x00, 0x49, 0xF8, 0xF8, 0x1D, +0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x48, 0xF8, 0xF8, 0x1D, 0x77, 0x42, 0x42, 0x00, 0x3F, 0xF8, 0xF8, 0x1D, +0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x75, 0x42, 0x42, 0x00, 0x9E, 0xF8, 0xF8, 0x1D, +0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x3C, 0xF8, 0xF8, 0x1D, 0x5C, 0x55, 0x55, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5C, 0x53, 0x53, 0x00, 0x4C, 0xF8, 0xF8, 0x1D, +0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x4B, 0xF8, 0xF8, 0x1D, 0x9E, 0xF8, 0xF8, 0x00, 0x8C, 0xF8, 0xF8, 0x1D, +0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x89, 0x89, 0x00, 0x46, 0xF8, 0xF8, 0x18, +0x45, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x44, 0xF8, 0xCF, 0x18, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, +0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x5E, 0x55, 0x55, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, +0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x56, 0x56, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, +0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x4F, 0xF8, 0xF8, 0x1D, 0x61, 0x55, 0x55, 0x00, 0x50, 0xF8, 0xF8, 0x1D, +0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x5F, 0x53, 0x53, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x5F, 0x55, 0x55, 0x00, 0x4F, 0xF8, 0xF8, 0x1D, +0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xAA, 0x55, 0x55, 0x00, 0x54, 0xF8, 0xF8, 0x1D, +0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0x4E, 0xF8, 0xF8, 0x1D, 0xA6, 0x59, 0x59, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x9B, 0x4F, 0x4F, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, +0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0x46, 0xF8, 0xF8, 0x1D, 0xA5, 0xF8, 0xF8, 0x00, 0x94, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0xA4, 0x98, 0x98, 0x00, 0x4D, 0xF8, 0xF8, 0x1D, +0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x86, 0x46, 0x46, 0x00, 0xB3, 0xF8, 0xF8, 0x1D, +0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x3D, 0xF8, 0xF8, 0x1D, 0x40, 0x8E, 0x8E, 0x00, 0x48, 0xF8, 0xF8, 0x1A, +0x48, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x46, 0xF8, 0xDF, 0x1A, 0x40, 0x7F, 0x7F, 0x00, 0x75, 0xD2, 0xD2, 0x18, +0x3A, 0xD2, 0xD2, 0x18, 0x3A, 0xD2, 0xD2, 0x18, 0x39, 0xD2, 0xD2, 0x18, 0x40, 0x45, 0x45, 0x00, 0x64, 0x86, 0x86, 0x0F, +0x3E, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x3D, 0x86, 0x86, 0x0F, 0x64, 0x5C, 0x5C, 0x00, 0x56, 0xF8, 0xF8, 0x1D, +0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x68, 0x5B, 0x5B, 0x00, 0x58, 0xF8, 0xF8, 0x1D, +0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x55, 0xF8, 0xF8, 0x1D, 0x64, 0x5A, 0x5A, 0x00, 0x55, 0xF8, 0xF8, 0x1D, +0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB5, 0x5A, 0x5A, 0x00, 0x5B, 0xF8, 0xF8, 0x1D, +0x55, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0x54, 0xF8, 0xF8, 0x1D, 0xB0, 0xF8, 0xF8, 0x00, 0xA3, 0xF8, 0xF8, 0x1D, +0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0xAE, 0xA4, 0xA4, 0x00, 0x54, 0xF8, 0xF8, 0x1D, +0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x52, 0xF8, 0xF8, 0x1D, 0x40, 0x9A, 0x9A, 0x00, 0x4E, 0xF8, 0xF8, 0x1D, +0x4D, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x4C, 0xF8, 0xF8, 0x1D, 0x40, 0x9C, 0x9C, 0x00, 0x95, 0xF8, 0xF8, 0x1D, +0x49, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x4A, 0xF8, 0xF8, 0x1D, 0x40, 0x49, 0x49, 0x00, 0x6F, 0x97, 0x97, 0x11, +0x42, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x41, 0x97, 0x97, 0x11, 0x74, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xF8, 0x1D, +0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x69, 0xF8, 0xF8, 0x1D, 0x40, 0x6E, 0x6E, 0x00, 0x69, 0xF8, 0xDE, 0x1A, +0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x69, 0xF8, 0xDE, 0x1A, 0x40, 0x75, 0x75, 0x00, 0x6E, 0xF8, 0x78, 0x0D, +0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x78, 0x0D, 0x6E, 0xF8, 0x79, 0x0D, 0x85, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, +0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0xF8, 0x1D, +0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x73, 0xF8, 0xF8, 0x1D, 0x40, 0x78, 0x78, 0x00, 0x73, 0xF8, 0x81, 0x0E, +0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x81, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x73, 0xF8, 0x82, 0x0E, +0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x73, 0xF8, 0x82, 0x0E, 0x40, 0x81, 0x81, 0x00, 0x7E, 0xF8, 0x92, 0x10, +0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x40, 0x40, 0x00, 0x7E, 0xF8, 0x92, 0x10, +0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x7E, 0xF8, 0x92, 0x10, 0x40, 0x73, 0x73, 0x00, 0x6B, 0xB2, 0xB2, 0x14, +0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x35, 0xB2, 0xB2, 0x14, 0x40, 0x40, 0x40, 0x00, 0x60, 0x82, 0x82, 0x0E, +0x3D, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x3C, 0x82, 0x82, 0x0E, 0x40, 0x40, 0x40, 0x00, 0x66, 0x8B, 0x8B, 0x0F, +0x3F, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x3D, 0x8B, 0x8B, 0x0F, 0x40, 0x40, 0x40, 0x00, 0x3D, 0x68, 0x68, 0x0B, +0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x1E, 0x68, 0x68, 0x0B, 0x40, 0x22, 0x22, 0x00, 0x18, 0x43, 0x43, 0x06, +0x29, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x18, 0x43, 0x43, 0x06, 0x40, 0x40, 0x40, 0x00, 0x72, 0x9D, 0x9D, 0x12, +0x43, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x41, 0x9D, 0x9D, 0x12, 0x40, 0x40, 0x40, 0x00, 0x42, 0x75, 0x75, 0x0D, +0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x20, 0x75, 0x75, 0x0D, 0x40, 0x23, 0x23, 0x00, 0x19, 0x4C, 0x4C, 0x08, +0x2C, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x19, 0x4C, 0x4C, 0x08, 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, +0xB8, 0xC8, 0xD8, 0xF8, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0x08, 0x58, 0x68, 0x78, 0x88, +0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, 0x09, 0x01, 0x03, 0x1E, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x75, 0x19, 0x03, +0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, +0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, +0xB4, 0x00, 0x0F, 0x04, 0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, +0x61, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, +0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, +0xB4, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, +0xB4, 0x00, 0x0F, 0x84, 0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, +0x60, 0xCB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, +0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, +0x34, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x3E, 0x2A, 0x00, +0xB5, 0x5A, 0x3F, 0x04, 0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, +0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, +0x80, 0x80, 0x80, 0x80, 0xD8, 0x3F, 0x2A, 0x00, 0xB5, 0x5A, 0x3F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, +0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, +0xB4, 0x00, 0x0F, 0x04, 0x63, 0xA3, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, +0x62, 0x03, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x61, 0x03, 0x8D, 0x0F, +0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x60, 0x23, 0x8D, 0x0F, 0x80, 0x80, 0x80, 0x80, +0x58, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x60, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0x39, 0x00, +0xB4, 0x00, 0x0F, 0x44, 0x60, 0xE3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, +0x60, 0xC3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x22, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x04, 0x60, 0xCB, 0x0C, 0x0E, +0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x60, 0xB3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, +0x34, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x60, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x2A, 0x00, +0xB5, 0x5A, 0x2F, 0x44, 0x60, 0x1B, 0x0F, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xA2, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0x04, +0x60, 0x9B, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x2E, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, +0x80, 0x80, 0x80, 0x80, 0x58, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, +0xD8, 0x2F, 0x2A, 0x00, 0xB5, 0x5A, 0x2F, 0xC4, 0x60, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, +0x6C, 0x00, 0x0F, 0x03, 0x60, 0xE7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x2F, 0x03, +0x60, 0xD7, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x03, 0x60, 0x9F, 0x0D, 0xE8, +0x80, 0x80, 0x80, 0x80, 0x6D, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0xEF, 0x83, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, +0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, +0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, +0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, +0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, +0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, +0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, +0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, +0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, +0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, +0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, +0x70, 0xE3, 0xAC, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x63, 0x8C, 0x0F, +0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, +0x46, 0x3E, 0x39, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x39, 0x00, +0xB4, 0x00, 0x19, 0x44, 0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0xC4, +0x70, 0xE3, 0x0C, 0x0F, 0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xC3, 0x8C, 0x0E, +0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, +0x34, 0x3E, 0xB9, 0x00, 0xB4, 0x00, 0x19, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xB9, 0x00, +0xB4, 0x00, 0x19, 0x84, 0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, +0x70, 0xF3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x84, 0x70, 0x3B, 0x0D, 0x0E, +0x80, 0x80, 0x80, 0x80, 0xB4, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, +0xEB, 0x3E, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0xAA, 0x00, +0xB5, 0x5A, 0x39, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0xAA, 0x00, 0xB5, 0x5A, 0x39, 0x04, +0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xE3, 0xAC, 0x0F, +0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x63, 0x8C, 0x0F, 0x80, 0x80, 0x80, 0x80, +0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0x03, 0x11, 0x0F, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0x39, 0x00, +0xB4, 0x00, 0x0F, 0x84, 0x70, 0x43, 0x8D, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0x39, 0x00, 0xB4, 0x00, 0x0F, 0x44, +0x70, 0xE3, 0x10, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x58, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0xC4, 0x70, 0xE3, 0x0C, 0x0F, +0x80, 0x80, 0x80, 0x80, 0xB4, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x44, 0x70, 0xC3, 0x8C, 0x0E, 0x80, 0x80, 0x80, 0x80, +0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, 0x70, 0x03, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x34, 0x2E, 0xB9, 0x00, +0xB4, 0x00, 0x0F, 0x44, 0x70, 0xEB, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xB9, 0x00, 0xB4, 0x00, 0x0F, 0x84, +0x70, 0xD3, 0x0C, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0xF3, 0x0C, 0x0E, +0x80, 0x80, 0x80, 0x80, 0x46, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x84, 0x70, 0x3B, 0x0D, 0x0E, 0x80, 0x80, 0x80, 0x80, +0xB4, 0x2E, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x44, 0x70, 0xBB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2E, 0xAA, 0x00, +0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, +0x70, 0xFB, 0x11, 0x0E, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x2F, 0xAA, 0x00, 0xB5, 0x5A, 0x2F, 0x04, 0x70, 0xFB, 0x11, 0x0E, +0x7F, 0xC1, 0x9F, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, 0x10, 0x01, 0x83, 0x00, +0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x60, 0x01, 0x84, 0x00, 0x67, 0x01, 0x93, 0x00, 0x67, 0x41, 0x99, 0x00, +0x7F, 0x41, 0x99, 0x00, 0x7F, 0xC1, 0x99, 0x00, 0x7F, 0x81, 0x9A, 0x00, 0x7F, 0x81, 0x9B, 0x00, 0x3F, 0xC1, 0x9C, 0x00, +0x3F, 0xC1, 0x8F, 0x00, 0x08, 0x01, 0x82, 0x00, 0x0A, 0x01, 0x82, 0x00, 0x0C, 0x81, 0x82, 0x00, 0x10, 0x81, 0x82, 0x00, +0x10, 0x01, 0x83, 0x00, 0x16, 0x01, 0x83, 0x00, 0x16, 0x01, 0x84, 0x00, 0x20, 0x01, 0x84, 0x00, 0x20, 0x01, 0x85, 0x00, +0x20, 0x01, 0x8C, 0x00, 0x27, 0x81, 0x8C, 0x00, 0x27, 0x01, 0x8E, 0x00, 0x27, 0x01, 0x9B, 0x00, 0x3F, 0x01, 0x9B, 0x00, +0x3F, 0xC1, 0x9C, 0x00, 0x3F, 0xC1, 0x8F, 0x00, 0x00, 0xC6, 0xFF, 0x00, 0x00, 0xC6, 0x40, 0x00, 0x00, 0x06, 0x41, 0x00, +0x00, 0x46, 0x41, 0x00, 0x00, 0x86, 0x90, 0x00, 0x00, 0xC6, 0x90, 0x00, 0x00, 0x06, 0xB1, 0x00, 0x00, 0x46, 0xB1, 0x00, +0x00, 0x86, 0xB1, 0x00, 0x00, 0x06, 0xB2, 0x00, 0x00, 0xC6, 0xB2, 0x00, 0x00, 0x46, 0xB9, 0x00, 0x00, 0xC6, 0xB9, 0x00, +0x00, 0x46, 0xBA, 0x00, 0x00, 0x46, 0xBB, 0x00, 0x00, 0xC6, 0xBC, 0x00, 0x82, 0x01, 0x83, 0x01, 0x40, 0x02, 0x41, 0x02, +0x80, 0x02, 0x81, 0x02, 0x82, 0x02, 0x83, 0x02, 0x40, 0x03, 0x41, 0x03, 0x80, 0x03, 0x81, 0x03, 0x00, 0x04, 0x01, 0x04, +0x40, 0x04, 0x41, 0x04, 0x60, 0x60, 0x00, 0x00, 0x3B, 0x18, 0xB3, 0x03, 0x68, 0x51, 0x2E, 0x1A, 0x48, 0x51, 0x2E, 0x1A, +0x00, 0x00, 0x00, 0x00, 0x84, 0x18, 0x20, 0x56, 0x84, 0x18, 0x20, 0x56, 0x00, 0x00, 0x00, 0x00, 0x08, 0x50, 0x2A, 0x7A, +0xC8, 0x50, 0x1B, 0x79, 0xC8, 0xD0, 0x2A, 0x7A, 0x40, 0x40, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x32, 0x00, 0x00, +0x00, 0x87, 0x93, 0x03, 0x00, 0x20, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x30, 0x75, 0x00, 0x00, 0xB0, 0xAD, 0x01, 0x00, +0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x20, 0xA1, 0x07, 0x00, 0x10, 0x27, 0x00, 0x00, +0x40, 0x0D, 0x03, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x27, 0x50, 0xC3, 0xA0, 0x0F, 0x40, 0x1F, 0x84, 0x03, 0x05, 0x08, +0x01, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1A, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x20, 0x1A, 0x00, 0xE0, 0x57, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, +0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, +0x00, 0x00, 0x19, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x19, 0x00, 0xF4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xE0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x71, 0x04, 0x00, 0x10, 0x0E, 0x00, +0x03, 0x01, 0x08, 0x8F, 0x03, 0xE6, 0xE0, 0xD0, 0xD6, 0x06, 0xD6, 0x06, 0x00, 0x00, 0x01, 0xF3, 0x01, 0x0A, 0x00, 0x0F, +0x08, 0x01, 0x09, 0x08, 0x08, 0x08, 0x08, 0x0A, 0x09, 0x09, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +0x03, 0x01, 0x00, 0x00, 0xBC, 0x06, 0x04, 0x04, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x0A, 0x02, 0x04, +0x01, 0x00, 0xF0, 0x00, 0x08, 0x04, 0x00, 0x04, 0x04, 0x04, 0x09, 0x06, 0x04, 0x01, 0x04, 0x01, 0x05, 0x14, 0x38, 0x01, +0x38, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, +0x7D, 0xA6, 0x12, 0x00, 0x91, 0xA1, 0x12, 0x00, 0xA5, 0xA6, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x99, 0xA1, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0xA1, 0x12, 0x00, 0xD1, 0xA1, 0x12, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xA3, 0x12, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x6D, 0x12, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8C, 0x00, 0x00, 0x00, +0x05, 0xC7, 0x12, 0x00, 0xE1, 0xB8, 0x14, 0x00, 0x75, 0xBB, 0x14, 0x00, 0x2D, 0xBE, 0x14, 0x00, 0xE9, 0xBC, 0x14, 0x00, +0x81, 0xBC, 0x14, 0x00, 0x29, 0xAC, 0x14, 0x00, 0xFD, 0x0C, 0x15, 0x00, 0x1D, 0x0B, 0x15, 0x00, 0x6D, 0x08, 0x15, 0x00, +0x0D, 0x07, 0x15, 0x00, 0x59, 0xC8, 0x13, 0x00, 0xF5, 0xE7, 0x13, 0x00, 0xA1, 0xCE, 0x13, 0x00, 0x3D, 0xD1, 0x13, 0x00, +0x4D, 0xD0, 0x13, 0x00, 0xF9, 0xD0, 0x13, 0x00, 0x05, 0xDD, 0x13, 0x00, 0xF1, 0xDD, 0x13, 0x00, 0x95, 0xDE, 0x13, 0x00, +0x85, 0xE4, 0x13, 0x00, 0xF5, 0xE0, 0x13, 0x00, 0xC1, 0xE3, 0x13, 0x00, 0xED, 0xCE, 0x13, 0x00, 0x59, 0xD6, 0x13, 0x00, +0xF5, 0xD9, 0x13, 0x00, 0x3D, 0xD5, 0x13, 0x00, 0xA9, 0xD4, 0x13, 0x00, 0x91, 0xD8, 0x13, 0x00, 0x31, 0xD9, 0x13, 0x00, +0xC1, 0xD8, 0x13, 0x00, 0x21, 0xD4, 0x13, 0x00, 0x4D, 0xDB, 0x13, 0x00, 0x71, 0xCA, 0x13, 0x00, 0xE5, 0xC9, 0x13, 0x00, +0xAD, 0xC0, 0x13, 0x00, 0xCD, 0xC6, 0x13, 0x00, 0x39, 0xC0, 0x13, 0x00, 0x79, 0xD6, 0x13, 0x00, 0xE5, 0xD7, 0x13, 0x00, +0xF1, 0xC7, 0x13, 0x00, 0xDD, 0xE4, 0x13, 0x00, 0xA1, 0xE6, 0x13, 0x00, 0x21, 0xD2, 0x13, 0x00, 0x6D, 0xD4, 0x13, 0x00, +0x99, 0xEA, 0x13, 0x00, 0x71, 0x50, 0x14, 0x00, 0x71, 0x58, 0x14, 0x00, 0x25, 0x06, 0x12, 0x00, 0x7D, 0x4B, 0x14, 0x00, +0x19, 0x4B, 0x14, 0x00, 0xF9, 0x5E, 0x12, 0x00, 0xD1, 0x5E, 0x12, 0x00, 0xF1, 0x1C, 0x14, 0x00, 0x19, 0x1E, 0x14, 0x00, +0xE9, 0x14, 0x14, 0x00, 0xD9, 0x16, 0x14, 0x00, 0x91, 0x17, 0x14, 0x00, 0xC9, 0x1A, 0x14, 0x00, 0xF1, 0x19, 0x14, 0x00, +0x3D, 0x15, 0x14, 0x00, 0xA5, 0x1B, 0x14, 0x00, 0x25, 0x1B, 0x14, 0x00, 0x1D, 0x90, 0x12, 0x00, 0x7D, 0x93, 0x12, 0x00, +0xD1, 0x9E, 0x12, 0x00, 0x71, 0x8E, 0x12, 0x00, 0xF5, 0xAA, 0x12, 0x00, 0xC5, 0x78, 0x12, 0x00, 0x05, 0x69, 0x12, 0x00, +0x39, 0x69, 0x12, 0x00, 0x8D, 0x52, 0x12, 0x00, 0x7D, 0x50, 0x12, 0x00, 0xD9, 0x55, 0x12, 0x00, 0xC1, 0x51, 0x12, 0x00, +0x79, 0x51, 0x12, 0x00, 0x5D, 0xB2, 0x12, 0x00, 0x8D, 0x0C, 0x15, 0x00, 0x61, 0x4C, 0x14, 0x00, 0xF9, 0x0E, 0x12, 0x00, +0x49, 0x07, 0x12, 0x00, 0x55, 0x59, 0x14, 0x00, 0xD5, 0x58, 0x14, 0x00, 0x49, 0x5A, 0x14, 0x00, 0x05, 0x5A, 0x14, 0x00, +0xD9, 0x80, 0x14, 0x00, 0xD9, 0x5A, 0x14, 0x00, 0x45, 0x79, 0x14, 0x00, 0x7D, 0x7D, 0x13, 0x00, 0xA1, 0x78, 0x13, 0x00, +0xB5, 0x7E, 0x13, 0x00, 0xF1, 0x85, 0x13, 0x00, 0xD5, 0xB6, 0x13, 0x00, 0x91, 0xBC, 0x13, 0x00, 0xF1, 0xB5, 0x13, 0x00, +0x19, 0xBB, 0x13, 0x00, 0x5D, 0xBB, 0x13, 0x00, 0xD5, 0xBC, 0x13, 0x00, 0xDD, 0xB8, 0x13, 0x00, 0x8D, 0xB8, 0x13, 0x00, +0xFD, 0xBD, 0x13, 0x00, 0x21, 0xB8, 0x13, 0x00, 0xC5, 0x8C, 0x13, 0x00, 0x09, 0x8C, 0x13, 0x00, 0xE9, 0x72, 0x13, 0x00, +0x59, 0x87, 0x13, 0x00, 0xCD, 0x73, 0x13, 0x00, 0x31, 0x84, 0x13, 0x00, 0x25, 0x80, 0x13, 0x00, 0x35, 0x83, 0x13, 0x00, +0xFD, 0x80, 0x13, 0x00, 0xE9, 0x8B, 0x13, 0x00, 0x01, 0x8E, 0x13, 0x00, 0x55, 0x89, 0x13, 0x00, 0xD9, 0x89, 0x13, 0x00, +0x91, 0x7D, 0x13, 0x00, 0x4D, 0x75, 0x13, 0x00, 0xA5, 0xB3, 0x13, 0x00, 0x19, 0xB0, 0x13, 0x00, 0x01, 0xAF, 0x13, 0x00, +0x21, 0xAF, 0x13, 0x00, 0x25, 0x05, 0x14, 0x00, 0xA9, 0xFF, 0x13, 0x00, 0xB1, 0xFE, 0x13, 0x00, 0xC5, 0xFF, 0x13, 0x00, +0x81, 0xFF, 0x13, 0x00, 0x69, 0x06, 0x14, 0x00, 0x49, 0x03, 0x14, 0x00, 0x2D, 0x0A, 0x14, 0x00, 0x25, 0x08, 0x14, 0x00, +0x3D, 0x09, 0x14, 0x00, 0xF9, 0x07, 0x14, 0x00, 0x59, 0xFB, 0x13, 0x00, 0x35, 0x04, 0x14, 0x00, 0xF5, 0xF6, 0x13, 0x00, +0x89, 0xF4, 0x13, 0x00, 0xA5, 0x13, 0x12, 0x00, 0x5D, 0x10, 0x12, 0x00, 0xC1, 0x0B, 0x12, 0x00, 0x49, 0x11, 0x12, 0x00, +0x4D, 0x02, 0x12, 0x00, 0xDD, 0xEA, 0x13, 0x00, 0x01, 0xEE, 0x13, 0x00, 0xA9, 0xF0, 0x13, 0x00, 0x79, 0xEF, 0x13, 0x00, +0x49, 0xF1, 0x13, 0x00, 0xE5, 0xF1, 0x13, 0x00, 0x85, 0xEC, 0x13, 0x00, 0x45, 0xED, 0x13, 0x00, 0xA5, 0xED, 0x13, 0x00, +0x3D, 0xEB, 0x13, 0x00, 0x45, 0xEF, 0x13, 0x00, 0xA1, 0xF2, 0x13, 0x00, 0xC5, 0xF3, 0x13, 0x00, 0x85, 0x49, 0x15, 0x00, +0x01, 0x35, 0x15, 0x00, 0xCD, 0x42, 0x12, 0x00, 0x71, 0xCB, 0x12, 0x00, 0x35, 0xCF, 0x12, 0x00, 0xAD, 0xD3, 0x12, 0x00, +0x9D, 0xCB, 0x12, 0x00, 0xFD, 0xD4, 0x12, 0x00, 0xFD, 0x48, 0x13, 0x00, 0x69, 0x4B, 0x13, 0x00, 0x21, 0x4C, 0x13, 0x00, +0x15, 0x46, 0x13, 0x00, 0x99, 0x50, 0x13, 0x00, 0x9D, 0x5C, 0x13, 0x00, 0x79, 0x5C, 0x13, 0x00, 0xED, 0x53, 0x13, 0x00, +0xE5, 0x56, 0x13, 0x00, 0x81, 0x4F, 0x13, 0x00, 0x61, 0x4E, 0x13, 0x00, 0x29, 0x4D, 0x13, 0x00, 0x01, 0x40, 0x13, 0x00, +0xED, 0x4C, 0x13, 0x00, 0x1D, 0x52, 0x13, 0x00, 0xDD, 0xDB, 0x14, 0x00, 0xB5, 0xEB, 0x14, 0x00, 0x19, 0xD9, 0x14, 0x00, +0xA5, 0xDF, 0x14, 0x00, 0xB5, 0xE0, 0x14, 0x00, 0xE9, 0xDE, 0x14, 0x00, 0x15, 0xE3, 0x14, 0x00, 0xD9, 0xE5, 0x14, 0x00, +0x5D, 0xD7, 0x14, 0x00, 0xED, 0xD6, 0x14, 0x00, 0x21, 0x13, 0x14, 0x00, 0x85, 0x14, 0x14, 0x00, 0x05, 0xD1, 0x14, 0x00, +0x8D, 0x85, 0x12, 0x00, 0xD1, 0x80, 0x12, 0x00, 0xCD, 0x7D, 0x12, 0x00, 0xED, 0x7F, 0x12, 0x00, 0x45, 0x7A, 0x12, 0x00, +0x01, 0x7F, 0x12, 0x00, 0xD5, 0x99, 0x14, 0x00, 0xED, 0x9A, 0x14, 0x00, 0x31, 0x62, 0x13, 0x00, 0x29, 0x5F, 0x13, 0x00, +0x65, 0x63, 0x13, 0x00, 0x41, 0x61, 0x13, 0x00, 0x71, 0x5F, 0x12, 0x00, 0xB9, 0x24, 0x12, 0x00, 0xD9, 0x0D, 0x14, 0x00, +0x61, 0x0C, 0x14, 0x00, 0x79, 0x20, 0x14, 0x00, 0x05, 0x20, 0x14, 0x00, 0xC1, 0x20, 0x14, 0x00, 0x55, 0xD6, 0x12, 0x00, +0x4D, 0x1B, 0x13, 0x00, 0x99, 0x0E, 0x13, 0x00, 0x11, 0x0C, 0x13, 0x00, 0x65, 0x0D, 0x13, 0x00, 0xD1, 0x19, 0x13, 0x00, +0x5D, 0x13, 0x13, 0x00, 0x79, 0x0A, 0x13, 0x00, 0x8D, 0x21, 0x13, 0x00, 0x2D, 0x15, 0x13, 0x00, 0x19, 0x21, 0x13, 0x00, +0x79, 0x07, 0x13, 0x00, 0xCD, 0xF3, 0x12, 0x00, 0x31, 0xD7, 0x12, 0x00, 0x41, 0xD8, 0x12, 0x00, 0xA1, 0xD8, 0x12, 0x00, +0x69, 0xFC, 0x12, 0x00, 0x15, 0xFD, 0x12, 0x00, 0xF5, 0xE7, 0x12, 0x00, 0xB5, 0xE2, 0x12, 0x00, 0xE5, 0xEA, 0x12, 0x00, +0xF5, 0xEB, 0x12, 0x00, 0xED, 0xE6, 0x12, 0x00, 0xF9, 0xDD, 0x12, 0x00, 0x89, 0xE2, 0x12, 0x00, 0xD1, 0xFD, 0x12, 0x00, +0xD5, 0xE7, 0x12, 0x00, 0xD5, 0x30, 0x13, 0x00, 0x91, 0x36, 0x13, 0x00, 0xD5, 0x3A, 0x13, 0x00, 0x7D, 0x3C, 0x13, 0x00, +0xDD, 0x26, 0x13, 0x00, 0x49, 0x27, 0x13, 0x00, 0xA9, 0x25, 0x13, 0x00, 0xCD, 0x35, 0x13, 0x00, 0x71, 0x25, 0x13, 0x00, +0x89, 0x2C, 0x13, 0x00, 0x75, 0x30, 0x13, 0x00, 0x81, 0x3A, 0x13, 0x00, 0x05, 0x3A, 0x13, 0x00, 0x49, 0x3D, 0x13, 0x00, +0xB1, 0x2B, 0x13, 0x00, 0x21, 0x2F, 0x13, 0x00, 0xBD, 0x39, 0x13, 0x00, 0x59, 0x28, 0x13, 0x00, 0xCD, 0x2A, 0x13, 0x00, +0x61, 0x37, 0x13, 0x00, 0x01, 0xDB, 0x12, 0x00, 0xF1, 0xE2, 0x12, 0x00, 0x81, 0xD9, 0x12, 0x00, 0x35, 0xEE, 0x12, 0x00, +0xC5, 0xEF, 0x12, 0x00, 0x49, 0xED, 0x12, 0x00, 0x69, 0xFD, 0x14, 0x00, 0x39, 0xF9, 0x14, 0x00, 0x71, 0xF4, 0x14, 0x00, +0x79, 0xF9, 0x14, 0x00, 0x09, 0xFC, 0x14, 0x00, 0xC5, 0xF3, 0x14, 0x00, 0xDD, 0x60, 0x12, 0x00, 0xB1, 0xAD, 0x12, 0x00, +0xBD, 0xAE, 0x12, 0x00, 0x29, 0xAF, 0x12, 0x00, 0xA5, 0xA4, 0x12, 0x00, 0xD1, 0xA5, 0x12, 0x00, 0xD9, 0x6C, 0x13, 0x00, +0xF5, 0x6E, 0x13, 0x00, 0x1D, 0x64, 0x13, 0x00, 0x2D, 0x6E, 0x13, 0x00, 0x51, 0x65, 0x13, 0x00, 0xB5, 0x6E, 0x13, 0x00, +0x2D, 0x6F, 0x13, 0x00, 0xC1, 0x68, 0x13, 0x00, 0x91, 0xBE, 0x12, 0x00, 0x29, 0xC4, 0x12, 0x00, 0x95, 0xBB, 0x12, 0x00, +0xDD, 0x03, 0x12, 0x00, 0x19, 0xC5, 0x12, 0x00, 0xCD, 0xC6, 0x12, 0x00, 0x2D, 0x1E, 0x12, 0x00, 0x61, 0x1B, 0x12, 0x00, +0x69, 0x1D, 0x12, 0x00, 0x7D, 0x9D, 0x12, 0x00, 0xA9, 0x9D, 0x12, 0x00, 0x39, 0x12, 0x14, 0x00, 0x99, 0x71, 0x13, 0x00, +0xC1, 0x21, 0x12, 0x00, 0x51, 0x09, 0x12, 0x00, 0x9D, 0x0A, 0x12, 0x00, 0xA1, 0x0A, 0x12, 0x00, 0xBD, 0x0B, 0x12, 0x00, +0x41, 0x1C, 0x12, 0x00, 0xD5, 0xCF, 0x12, 0x00, 0x21, 0xD1, 0x12, 0x00, 0xD1, 0x3C, 0x12, 0x00, 0xC5, 0x4B, 0x12, 0x00, +0xA1, 0x4D, 0x12, 0x00, 0x6D, 0x4C, 0x12, 0x00, 0xAD, 0x4A, 0x12, 0x00, 0x71, 0xC0, 0x12, 0x00, 0x19, 0xC2, 0x12, 0x00, +0x79, 0xB8, 0x12, 0x00, 0x29, 0x9A, 0x12, 0x00, 0x39, 0x93, 0x12, 0x00, 0xA1, 0x65, 0x12, 0x00, 0xCD, 0xB1, 0x12, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x58, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xC2, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x75, 0x95, 0x13, 0x00, +0x04, 0x00, 0x00, 0x00, 0xFD, 0x8F, 0x13, 0x00, 0x06, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x08, 0x00, 0x00, 0x00, +0xF1, 0xA9, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x93, 0x13, 0x00, 0x10, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, +0x16, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x14, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x12, 0x00, 0x00, 0x00, +0xF1, 0xA9, 0x13, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, +0x1A, 0x00, 0x00, 0x00, 0xCD, 0x90, 0x13, 0x00, 0x6B, 0x00, 0x00, 0x00, 0xF5, 0x96, 0x13, 0x00, 0x6D, 0x00, 0x00, 0x00, +0xD1, 0x97, 0x13, 0x00, 0x71, 0x00, 0x00, 0x00, 0x19, 0x93, 0x13, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x79, 0x91, 0x13, 0x00, +0x20, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x1E, 0x00, 0x00, 0x00, +0xF1, 0xA9, 0x13, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x22, 0x00, 0x00, 0x00, 0x09, 0xA0, 0x13, 0x00, +0x84, 0x00, 0x00, 0x00, 0xAD, 0xA0, 0x13, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x4D, 0x8E, 0x13, 0x00, 0x24, 0x00, 0x00, 0x00, +0xA9, 0x93, 0x13, 0x00, 0x26, 0x00, 0x00, 0x00, 0x4D, 0x94, 0x13, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x9D, 0x8E, 0x13, 0x00, +0x0C, 0x00, 0x00, 0x00, 0x9D, 0x91, 0x13, 0x00, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x2A, 0x00, 0x00, 0x00, +0xF1, 0x97, 0x13, 0x00, 0x39, 0x00, 0x00, 0x00, 0xC5, 0x91, 0x13, 0x00, 0x3B, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, +0x46, 0x00, 0x00, 0x00, 0xCD, 0x8E, 0x13, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x21, 0x8E, 0x13, 0x00, 0x41, 0x00, 0x00, 0x00, +0x91, 0x98, 0x13, 0x00, 0x31, 0x00, 0x00, 0x00, 0x35, 0x8E, 0x13, 0x00, 0x4B, 0x00, 0x00, 0x00, 0xA9, 0x94, 0x13, 0x00, +0x51, 0x00, 0x00, 0x00, 0x59, 0x8F, 0x13, 0x00, 0x52, 0x00, 0x00, 0x00, 0xB5, 0x9F, 0x13, 0x00, 0x56, 0x00, 0x00, 0x00, +0x15, 0x95, 0x13, 0x00, 0x87, 0x00, 0x00, 0x00, 0xF1, 0xA9, 0x13, 0x00, 0x61, 0x00, 0x00, 0x00, 0x21, 0x97, 0x13, 0x00, +0x63, 0x00, 0x00, 0x00, 0x9D, 0x98, 0x13, 0x00, 0x65, 0x00, 0x00, 0x00, 0xE9, 0x91, 0x13, 0x00, 0x67, 0x00, 0x00, 0x00, +0x0D, 0x96, 0x13, 0x00, 0x69, 0x00, 0x00, 0x00, 0xF1, 0x9C, 0x13, 0x00, 0x73, 0x00, 0x00, 0x00, 0xE9, 0x98, 0x13, 0x00, +0x75, 0x00, 0x00, 0x00, 0x0D, 0x8F, 0x13, 0x00, 0x77, 0x00, 0x00, 0x00, 0xA5, 0x92, 0x13, 0x00, 0x79, 0x00, 0x00, 0x00, +0xCD, 0x92, 0x13, 0x00, 0x7B, 0x00, 0x00, 0x00, 0xE1, 0x9B, 0x13, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x59, 0x99, 0x13, 0x00, +0x80, 0x00, 0x00, 0x00, 0xBD, 0x96, 0x13, 0x00, 0x82, 0x00, 0x00, 0x00, 0x11, 0x9B, 0x13, 0x00, 0x00, 0x08, 0x00, 0x00, +0xB9, 0x0E, 0x14, 0x00, 0x85, 0x00, 0x00, 0x00, 0x4D, 0x0F, 0x14, 0x00, 0x86, 0x00, 0x00, 0x00, 0xC9, 0x0F, 0x14, 0x00, +0x03, 0x08, 0x00, 0x00, 0x71, 0x10, 0x14, 0x00, 0x0D, 0xCD, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xB0, 0x13, 0x00, +0x00, 0x00, 0x00, 0x00, 0xA1, 0x28, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9D, 0x2F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x84, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, +0x00, 0x00, 0x00, 0x00, 0xB5, 0x7F, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, +0x85, 0x4A, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x48, 0x13, 0x00, +0x00, 0x00, 0x00, 0x00, 0xD1, 0x78, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, +0xD1, 0xF4, 0x12, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, +0x02, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF9, 0x4C, 0x14, 0x00, 0x04, 0x00, 0x00, 0x00, 0xD1, 0xF4, 0x12, 0x00, 0x05, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, +0x03, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0xF9, 0x4C, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, +0xF9, 0x4C, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x69, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x6D, 0x12, 0x00, +0x00, 0x00, 0x00, 0x00, 0x69, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, +0xBD, 0x6D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x15, 0x4A, 0x14, 0x00, 0x02, 0x04, 0x00, 0x00, 0xB5, 0x49, 0x14, 0x00, +0x04, 0x04, 0x00, 0x00, 0x2D, 0x48, 0x14, 0x00, 0x06, 0x04, 0x00, 0x00, 0xF9, 0x47, 0x14, 0x00, 0x09, 0x04, 0x00, 0x00, +0x95, 0x49, 0x14, 0x00, 0x11, 0x04, 0x00, 0x00, 0x11, 0x49, 0x14, 0x00, 0x0B, 0x04, 0x00, 0x00, 0xC1, 0x4A, 0x14, 0x00, +0x0D, 0x04, 0x00, 0x00, 0x45, 0x4A, 0x14, 0x00, 0x0F, 0x04, 0x00, 0x00, 0x61, 0x48, 0x14, 0x00, 0x1B, 0x04, 0x00, 0x00, +0x91, 0x47, 0x14, 0x00, 0x1E, 0x04, 0x00, 0x00, 0x75, 0x47, 0x14, 0x00, 0x1F, 0x04, 0x00, 0x00, 0x59, 0x47, 0x14, 0x00, +0x01, 0x00, 0x00, 0x00, 0x28, 0x34, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0xBD, 0x68, 0x14, 0x00, 0x02, 0x14, 0x00, 0x00, +0xED, 0x65, 0x14, 0x00, 0x04, 0x14, 0x00, 0x00, 0x01, 0x67, 0x14, 0x00, 0x07, 0x14, 0x00, 0x00, 0x01, 0x6A, 0x14, 0x00, +0x09, 0x14, 0x00, 0x00, 0x75, 0x67, 0x14, 0x00, 0x17, 0x14, 0x00, 0x00, 0xB1, 0x72, 0x14, 0x00, 0x19, 0x14, 0x00, 0x00, +0xB5, 0x6E, 0x14, 0x00, 0x0C, 0x14, 0x00, 0x00, 0x01, 0x68, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, +0x23, 0x00, 0x00, 0x00, 0x45, 0x6F, 0x14, 0x00, 0x13, 0x14, 0x00, 0x00, 0x45, 0x73, 0x14, 0x00, 0x32, 0x00, 0x00, 0x00, +0x9D, 0x6F, 0x14, 0x00, 0x15, 0x14, 0x00, 0x00, 0x11, 0x66, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, +0x3C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x42, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, +0x89, 0x31, 0x14, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, +0x70, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0E, 0x14, 0x00, 0x00, +0xF5, 0x6F, 0x14, 0x00, 0x10, 0x14, 0x00, 0x00, 0xF1, 0x70, 0x14, 0x00, 0x11, 0x14, 0x00, 0x00, 0x91, 0x71, 0x14, 0x00, +0x00, 0x18, 0x00, 0x00, 0x1D, 0x8A, 0x14, 0x00, 0x03, 0x18, 0x00, 0x00, 0x6D, 0x92, 0x14, 0x00, 0x01, 0x10, 0x00, 0x00, +0xA1, 0x8C, 0x14, 0x00, 0x03, 0x10, 0x00, 0x00, 0x09, 0x8D, 0x14, 0x00, 0x08, 0x18, 0x00, 0x00, 0x71, 0x8C, 0x14, 0x00, +0x43, 0x00, 0x00, 0x00, 0x21, 0x8C, 0x14, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x8D, 0x92, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, +0xA5, 0x90, 0x14, 0x00, 0x19, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, +0x15, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x72, 0x00, 0x00, 0x00, 0xE5, 0x8F, 0x14, 0x00, 0x1B, 0x00, 0x00, 0x00, +0xE5, 0x8F, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xD9, 0x94, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x7D, 0x8F, 0x14, 0x00, +0x4C, 0x00, 0x00, 0x00, 0x89, 0x31, 0x14, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x25, 0x90, 0x14, 0x00, 0x3A, 0x00, 0x00, 0x00, +0x65, 0x90, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, 0x99, 0x91, 0x14, 0x00, 0x07, 0x18, 0x00, 0x00, 0xFD, 0x91, 0x14, 0x00, +0x09, 0x18, 0x00, 0x00, 0x19, 0x92, 0x14, 0x00, 0x00, 0x1C, 0x00, 0x00, 0xF5, 0xB3, 0x14, 0x00, 0x02, 0x1C, 0x00, 0x00, +0xD5, 0xB6, 0x14, 0x00, 0x18, 0x14, 0x00, 0x00, 0xD9, 0xB7, 0x14, 0x00, 0x40, 0x00, 0x00, 0x00, 0xBD, 0xB2, 0x14, 0x00, +0x19, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0xB6, 0x14, 0x00, 0x15, 0x00, 0x00, 0x00, +0x01, 0xB6, 0x14, 0x00, 0x1A, 0x14, 0x00, 0x00, 0x9D, 0xB5, 0x14, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x81, 0xB6, 0x14, 0x00, +0x3A, 0x00, 0x00, 0x00, 0x41, 0xB6, 0x14, 0x00, 0x04, 0x1C, 0x00, 0x00, 0x01, 0xB3, 0x14, 0x00, 0x06, 0x1C, 0x00, 0x00, +0x39, 0xB7, 0x14, 0x00, 0x08, 0x1C, 0x00, 0x00, 0x59, 0xB5, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, +0x02, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x05, 0x10, 0x00, 0x00, 0x8D, 0x31, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, +0x89, 0x31, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0x95, 0xBF, 0x14, 0x00, 0x02, 0x10, 0x00, 0x00, 0xF5, 0xC0, 0x14, 0x00, +0x05, 0x10, 0x00, 0x00, 0xF5, 0xBF, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xF1, 0xC1, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, +0x7D, 0xC0, 0x14, 0x00, 0x01, 0x08, 0x00, 0x00, 0x39, 0xC2, 0x14, 0x00, 0x02, 0x08, 0x00, 0x00, 0x85, 0xC2, 0x14, 0x00, +0x00, 0x28, 0x00, 0x00, 0xA1, 0xC2, 0x14, 0x00, 0x0A, 0x10, 0x00, 0x00, 0x51, 0xC0, 0x14, 0x00, 0x04, 0x08, 0x00, 0x00, +0x4D, 0xC2, 0x14, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD5, 0xC0, 0x14, 0x00, 0x07, 0x10, 0x00, 0x00, 0xA1, 0xC0, 0x14, 0x00, +0xDC, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x45, 0x04, 0x15, 0x00, 0x01, 0x20, 0x00, 0x00, 0x69, 0x04, 0x15, 0x00, +0x2B, 0x00, 0x00, 0x00, 0xC5, 0x00, 0x15, 0x00, 0x29, 0x00, 0x00, 0x00, 0x55, 0xFF, 0x14, 0x00, 0x00, 0x28, 0x00, 0x00, +0x35, 0x01, 0x15, 0x00, 0x0D, 0x26, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, +}; + +char fw_adid_u03[1208] = { +0x61, 0xBD, 0x08, 0x00, 0xFD, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x03, 0x08, 0x00, +0x71, 0x02, 0x08, 0x00, 0x21, 0x04, 0x08, 0x00, 0xD9, 0x0A, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x0F, 0x08, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDD, 0x15, 0x08, 0x00, +0x6D, 0x18, 0x08, 0x00, 0xD1, 0x18, 0x08, 0x00, 0x15, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF5, 0x1D, 0x08, 0x00, +0xA1, 0x24, 0x08, 0x00, 0x05, 0x26, 0x08, 0x00, 0x3D, 0x2A, 0x08, 0x00, 0x9D, 0x55, 0x08, 0x00, 0x39, 0x76, 0x08, 0x00, +0x91, 0x76, 0x08, 0x00, 0x9D, 0x7C, 0x08, 0x00, 0xE5, 0x7C, 0x08, 0x00, 0x5D, 0x80, 0x08, 0x00, 0x75, 0xA9, 0x08, 0x00, +0x9D, 0xBE, 0x08, 0x00, 0xD5, 0xBE, 0x08, 0x00, 0x39, 0xC0, 0x08, 0x00, 0x6D, 0xC2, 0x08, 0x00, 0x3D, 0x05, 0x09, 0x00, +0xF1, 0x3B, 0x09, 0x00, 0x31, 0x3E, 0x09, 0x00, 0xFD, 0x40, 0x09, 0x00, 0x65, 0x9D, 0x09, 0x00, 0x25, 0xC0, 0x09, 0x00, +0xF9, 0xBB, 0x09, 0x00, 0x05, 0xA2, 0x09, 0x00, 0x91, 0xD7, 0x09, 0x00, 0x4D, 0xB2, 0x0A, 0x00, 0x25, 0xB6, 0x0A, 0x00, +0x75, 0xB8, 0x0A, 0x00, 0x2D, 0xB9, 0x0A, 0x00, 0x8D, 0xBB, 0x0A, 0x00, 0x99, 0xBC, 0x0A, 0x00, 0xA1, 0xC5, 0x0A, 0x00, +0x31, 0xCD, 0x0A, 0x00, 0x09, 0xDE, 0x0A, 0x00, 0xB9, 0xEE, 0x0A, 0x00, 0x35, 0x58, 0x09, 0x00, 0xB1, 0x58, 0x09, 0x00, +0x15, 0x54, 0x09, 0x00, 0xBD, 0x56, 0x09, 0x00, 0x11, 0x5B, 0x09, 0x00, 0xED, 0x5C, 0x09, 0x00, 0x15, 0x6C, 0x09, 0x00, +0xB9, 0x60, 0x09, 0x00, 0xDD, 0x29, 0x0B, 0x00, 0x05, 0x76, 0x09, 0x00, 0x75, 0x76, 0x09, 0x00, 0x3D, 0x7A, 0x09, 0x00, +0x5D, 0x7E, 0x09, 0x00, 0x69, 0x78, 0x09, 0x00, 0x61, 0x79, 0x09, 0x00, 0xD9, 0x7E, 0x09, 0x00, 0x35, 0x41, 0x0B, 0x00, +0xB5, 0x08, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCD, 0x0C, 0x0B, 0x00, 0x85, 0x6F, 0x09, 0x00, 0xD5, 0x7B, 0x0B, 0x00, +0x75, 0x7C, 0x0B, 0x00, 0xDD, 0x6C, 0x09, 0x00, 0xA9, 0x6D, 0x09, 0x00, 0x75, 0x6E, 0x09, 0x00, 0xE9, 0x1F, 0x0B, 0x00, +0x35, 0x23, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x1B, 0x0B, 0x00, 0x45, 0x27, 0x0B, 0x00, 0x85, 0x1A, 0x0B, 0x00, +0x69, 0x17, 0x0B, 0x00, 0xDD, 0x27, 0x0B, 0x00, 0x31, 0x2B, 0x0B, 0x00, 0x25, 0x78, 0x0B, 0x00, 0x15, 0x65, 0x0B, 0x00, +0x3D, 0x6B, 0x0B, 0x00, 0x9D, 0x67, 0x0B, 0x00, 0x99, 0x6B, 0x0B, 0x00, 0xC5, 0x6C, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, +0x2D, 0xAF, 0x0B, 0x00, 0x3D, 0x99, 0x0C, 0x00, 0xC5, 0xD9, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x95, 0x0C, 0x00, 0x3D, 0xD5, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF5, 0xA4, 0x08, 0x00, 0xB5, 0xA5, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFD, 0x50, 0x08, 0x00, 0x9D, 0x7D, 0x08, 0x00, 0xBD, 0x7D, 0x08, 0x00, 0xDD, 0x7D, 0x08, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x91, 0x08, 0x00, +0xAB, 0x91, 0x08, 0x00, 0xAD, 0x91, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x71, 0xD5, 0x09, 0x00, 0x6D, 0x0E, 0x08, 0x00, +}; + +char fw_patch_table_u03[1256] = { +0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x54, 0x5F, 0x54, 0x41, 0x47, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, +0x54, 0x5F, 0x54, 0x52, 0x41, 0x50, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, +0x00, 0xF0, 0x16, 0x00, 0x04, 0x23, 0xA3, 0x55, 0x00, 0x10, 0x08, 0x40, 0x88, 0x48, 0x0C, 0x00, 0x04, 0xF0, 0x16, 0x00, +0x00, 0x2B, 0x05, 0xE0, 0x04, 0x10, 0x08, 0x40, 0x58, 0x58, 0x0B, 0x00, 0x08, 0xF0, 0x16, 0x00, 0x00, 0x2B, 0xB1, 0xE7, +0x08, 0x10, 0x08, 0x40, 0x30, 0x5A, 0x0B, 0x00, 0x14, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x18, 0xEA, 0x16, 0x00, +0x00, 0xB5, 0x02, 0x4B, 0x1C, 0xEA, 0x16, 0x00, 0xDB, 0x6E, 0x00, 0xBD, 0x20, 0xEA, 0x16, 0x00, 0xD7, 0xCB, 0x0A, 0x00, +0x24, 0xEA, 0x16, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x0C, 0xF0, 0x16, 0x00, 0xC1, 0xF0, 0x1F, 0xFF, 0x0C, 0x10, 0x08, 0x40, +0xD2, 0xCB, 0x0A, 0x00, 0x00, 0xEA, 0x16, 0x00, 0x02, 0x49, 0x8E, 0x46, 0x04, 0xEA, 0x16, 0x00, 0x00, 0xB5, 0x02, 0x4B, +0x08, 0xEA, 0x16, 0x00, 0xDA, 0x6E, 0x00, 0xBD, 0x0C, 0xEA, 0x16, 0x00, 0xC1, 0xE6, 0x0A, 0x00, 0x10, 0xEA, 0x16, 0x00, +0xAC, 0x2B, 0x16, 0x00, 0x10, 0xF0, 0x16, 0x00, 0xC0, 0xF0, 0xA0, 0xF9, 0x10, 0x10, 0x08, 0x40, 0xBC, 0xE6, 0x0A, 0x00, +0x14, 0xF0, 0x16, 0x00, 0x43, 0x1C, 0x05, 0xE0, 0x14, 0x10, 0x08, 0x40, 0x1C, 0xFD, 0x0C, 0x00, 0x30, 0xEA, 0x16, 0x00, +0x01, 0x4B, 0x98, 0x47, 0x34, 0xEA, 0x16, 0x00, 0x01, 0x4B, 0x9F, 0x46, 0x38, 0xEA, 0x16, 0x00, 0xD9, 0x97, 0x10, 0x00, +0x3C, 0xEA, 0x16, 0x00, 0x59, 0x1E, 0x0D, 0x00, 0x18, 0xF0, 0x16, 0x00, 0x9C, 0xF0, 0x92, 0xFF, 0x18, 0x10, 0x08, 0x40, +0x08, 0x1B, 0x0D, 0x00, 0x1C, 0xF0, 0x16, 0x00, 0xEC, 0xE1, 0x10, 0x00, 0x1C, 0x10, 0x08, 0x40, 0x30, 0xB8, 0x0B, 0x00, +0x84, 0x10, 0x08, 0x40, 0x00, 0xF0, 0x16, 0x00, 0x80, 0x10, 0x08, 0x40, 0xFF, 0x00, 0x00, 0x00, 0x58, 0x00, 0x10, 0x40, +0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x42, 0x34, 0x00, +0x02, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x38, 0x1B, 0x16, 0x00, 0x99, 0x12, 0x10, 0x00, 0x98, 0x19, 0x16, 0x00, +0xA9, 0x23, 0x10, 0x00, 0x18, 0x1B, 0x16, 0x00, 0x81, 0x07, 0x10, 0x00, 0x20, 0x1B, 0x16, 0x00, 0xCD, 0x09, 0x10, 0x00, +0x28, 0x1B, 0x16, 0x00, 0xF1, 0x0B, 0x10, 0x00, 0xB0, 0x19, 0x16, 0x00, 0x21, 0x25, 0x10, 0x00, 0x70, 0x1A, 0x16, 0x00, +0xB9, 0x30, 0x10, 0x00, 0x6C, 0x1A, 0x16, 0x00, 0x19, 0x64, 0x10, 0x00, 0xE0, 0x1A, 0x16, 0x00, 0xB9, 0x69, 0x10, 0x00, +0xE0, 0x19, 0x16, 0x00, 0xCB, 0x09, 0x10, 0x00, 0xDC, 0x19, 0x16, 0x00, 0xC9, 0x09, 0x10, 0x00, 0x38, 0x19, 0x16, 0x00, +0x89, 0x54, 0x10, 0x00, 0x1C, 0x1B, 0x16, 0x00, 0x69, 0x56, 0x10, 0x00, 0x24, 0x1B, 0x16, 0x00, 0x75, 0x58, 0x10, 0x00, +0x7C, 0x1D, 0x16, 0x00, 0xDD, 0x5B, 0x10, 0x00, 0xB0, 0x1A, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0xB0, 0x1D, 0x16, 0x00, +0x31, 0x6D, 0x10, 0x00, 0x8C, 0x1D, 0x16, 0x00, 0x19, 0x6E, 0x10, 0x00, 0x88, 0x1D, 0x16, 0x00, 0x49, 0x6E, 0x10, 0x00, +0x40, 0x19, 0x16, 0x00, 0xF5, 0x6E, 0x10, 0x00, 0x2C, 0x1B, 0x16, 0x00, 0x51, 0x6F, 0x10, 0x00, 0x80, 0x1D, 0x16, 0x00, +0xC1, 0x5F, 0x10, 0x00, 0xF4, 0x19, 0x16, 0x00, 0x89, 0x6F, 0x10, 0x00, 0xEC, 0x19, 0x16, 0x00, 0x0D, 0x70, 0x10, 0x00, +0x54, 0x19, 0x16, 0x00, 0x31, 0x93, 0x10, 0x00, 0x14, 0x1B, 0x16, 0x00, 0x35, 0x94, 0x10, 0x00, 0x8C, 0x19, 0x16, 0x00, +0xE9, 0x71, 0x10, 0x00, 0x88, 0x19, 0x16, 0x00, 0xB9, 0x7A, 0x10, 0x00, 0x04, 0x1B, 0x16, 0x00, 0x35, 0x97, 0x10, 0x00, +0x90, 0x19, 0x16, 0x00, 0xFD, 0x9E, 0x10, 0x00, 0x94, 0x19, 0x16, 0x00, 0x5D, 0x9F, 0x10, 0x00, 0xE8, 0x19, 0x16, 0x00, +0x3D, 0xA2, 0x10, 0x00, 0xE4, 0x1A, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xD4, 0x1A, 0x16, 0x00, 0x69, 0xA2, 0x10, 0x00, +0x64, 0x1A, 0x16, 0x00, 0x29, 0x33, 0x10, 0x00, 0x08, 0x1B, 0x16, 0x00, 0x55, 0x91, 0x10, 0x00, 0xBC, 0x19, 0x16, 0x00, +0x31, 0x38, 0x10, 0x00, 0x68, 0x1A, 0x16, 0x00, 0x79, 0x61, 0x10, 0x00, 0x40, 0x1A, 0x16, 0x00, 0x8D, 0x40, 0x10, 0x00, +0x3C, 0x1A, 0x16, 0x00, 0x41, 0x07, 0x10, 0x00, 0x4C, 0x1A, 0x16, 0x00, 0x85, 0x54, 0x10, 0x00, 0xB8, 0x19, 0x16, 0x00, +0x9D, 0x3B, 0x10, 0x00, 0x7C, 0x1A, 0x16, 0x00, 0x41, 0x2A, 0x10, 0x00, 0x68, 0xAD, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, +0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x4D, 0x4F, 0x44, 0x45, 0x5F, 0x54, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, +0x09, 0x00, 0x00, 0x00, 0xA4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x54, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xA8, 0xE5, 0x10, 0x00, +0x02, 0x00, 0x00, 0x00, 0xB8, 0xE5, 0x10, 0x00, 0x60, 0xE3, 0x16, 0x00, 0xBC, 0xE5, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, +0xAC, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xE5, 0x10, 0x00, 0x20, 0x60, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, +0x54, 0x5F, 0x50, 0x4F, 0x57, 0x45, 0x52, 0x5F, 0x4F, 0x4E, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x3C, 0x00, 0x50, 0x40, 0x00, 0x00, 0x08, 0x00, 0x24, 0x01, 0x50, 0x40, 0x40, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, +0x54, 0x5F, 0x50, 0x41, 0x54, 0x43, 0x48, 0x5F, 0x54, 0x41, 0x46, 0x00, 0x05, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, +0x24, 0x0A, 0x16, 0x00, 0x65, 0x7E, 0x10, 0x00, 0xA4, 0x12, 0x16, 0x00, 0x1D, 0x84, 0x10, 0x00, 0xBC, 0x12, 0x16, 0x00, +0xFD, 0xA3, 0x10, 0x00, 0xC4, 0x12, 0x16, 0x00, 0xE9, 0xB2, 0x10, 0x00, 0x0C, 0x08, 0x16, 0x00, 0x1D, 0xA3, 0x10, 0x00, +0x5C, 0x07, 0x16, 0x00, 0x45, 0xA3, 0x10, 0x00, 0x84, 0x15, 0x16, 0x00, 0xB9, 0x89, 0x10, 0x00, 0x4C, 0x18, 0x16, 0x00, +0x65, 0x8B, 0x10, 0x00, 0x6C, 0x18, 0x16, 0x00, 0xE9, 0x8B, 0x10, 0x00, 0xDC, 0x18, 0x16, 0x00, 0x35, 0x8C, 0x10, 0x00, +0xF4, 0x1A, 0x16, 0x00, 0x99, 0x05, 0x10, 0x00, 0xAC, 0x12, 0x16, 0x00, 0x35, 0x76, 0x10, 0x00, 0x04, 0x10, 0x16, 0x00, +0xD1, 0x8E, 0x10, 0x00, 0x0C, 0x10, 0x16, 0x00, 0x25, 0x90, 0x10, 0x00, 0x84, 0x10, 0x16, 0x00, 0x41, 0xAA, 0x10, 0x00, +0x9C, 0x10, 0x16, 0x00, 0xB1, 0xAA, 0x10, 0x00, 0xA4, 0x10, 0x16, 0x00, 0x71, 0xAB, 0x10, 0x00, 0x4C, 0x10, 0x16, 0x00, +0x5D, 0xAC, 0x10, 0x00, 0xE4, 0x0F, 0x16, 0x00, 0x65, 0x90, 0x10, 0x00, 0xEC, 0x13, 0x16, 0x00, 0xC5, 0xA7, 0x10, 0x00, +0x0C, 0x13, 0x16, 0x00, 0x55, 0xB3, 0x10, 0x00, 0xFC, 0x12, 0x16, 0x00, 0x1D, 0x26, 0x10, 0x00, 0x74, 0x0A, 0x16, 0x00, +0xED, 0x27, 0x10, 0x00, 0x74, 0x13, 0x16, 0x00, 0x35, 0xA8, 0x10, 0x00, 0x04, 0x14, 0x16, 0x00, 0xD9, 0xA8, 0x10, 0x00, +0x4C, 0x14, 0x16, 0x00, 0xB1, 0xAE, 0x10, 0x00, 0x3C, 0x0A, 0x16, 0x00, 0x05, 0xAF, 0x10, 0x00, 0x44, 0x0A, 0x16, 0x00, +0xF1, 0xAF, 0x10, 0x00, 0x04, 0x15, 0x16, 0x00, 0x51, 0x91, 0x10, 0x00, 0x2C, 0x13, 0x16, 0x00, 0xA1, 0x42, 0x10, 0x00, +0xD4, 0x0A, 0x16, 0x00, 0xED, 0xAD, 0x10, 0x00, 0x44, 0x11, 0x16, 0x00, 0x51, 0xAD, 0x10, 0x00, 0xE4, 0x12, 0x16, 0x00, +0x09, 0xA7, 0x10, 0x00, 0x7C, 0x09, 0x16, 0x00, 0x15, 0xCD, 0x10, 0x00, 0x8C, 0x09, 0x16, 0x00, 0x4D, 0xCD, 0x10, 0x00, +0x94, 0x09, 0x16, 0x00, 0xC1, 0xCD, 0x10, 0x00, 0x6C, 0x14, 0x16, 0x00, 0x71, 0xCD, 0x10, 0x00, 0x70, 0x30, 0x50, 0x40, +0x00, 0x00, 0x00, 0x00, 0x74, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x78, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, +0x7C, 0x30, 0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x43, 0x42, 0x54, 0x5F, 0x56, 0x45, 0x52, 0x5F, 0x49, 0x4E, +0x46, 0x4F, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, +0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, 0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, +0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +char fw_patch_u03[59704] = { +0x10, 0xB5, 0x15, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x02, 0xD0, 0x14, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0x13, 0x4B, 0x1B, 0x68, +0x3F, 0x22, 0x9A, 0x5C, 0x00, 0x2A, 0xF6, 0xD1, 0x3D, 0x32, 0x9C, 0x5C, 0x10, 0x4B, 0x1A, 0x78, 0x01, 0x32, 0xD2, 0xB2, +0x10, 0x2A, 0x10, 0xD8, 0x1A, 0x70, 0x0D, 0x49, 0x0A, 0x78, 0x12, 0x03, 0x92, 0xB2, 0x62, 0x23, 0x63, 0x43, 0x0B, 0x4C, +0x1C, 0x19, 0x22, 0x80, 0x0A, 0x78, 0x12, 0x09, 0x09, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1A, 0x80, 0xDD, 0xE7, 0x05, 0x4B, +0x00, 0x22, 0x1A, 0x70, 0xEB, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xC1, 0xE9, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, +0xB0, 0xE6, 0x10, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, +0x00, 0x2B, 0x03, 0xD0, 0x3A, 0x22, 0x9B, 0x5C, 0x01, 0x2B, 0x06, 0xD0, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x62, 0x68, +0x07, 0x4B, 0x1A, 0x60, 0x10, 0xBD, 0x07, 0x49, 0x0B, 0x68, 0x07, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, +0x0B, 0x60, 0xEF, 0xE7, 0x18, 0x27, 0x16, 0x00, 0x25, 0xC3, 0x0C, 0x00, 0x30, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, +0xFF, 0xFF, 0xDF, 0xFF, 0x10, 0xB5, 0x18, 0x4A, 0x00, 0x23, 0x00, 0x24, 0x14, 0x57, 0x84, 0x42, 0x04, 0xDA, 0x01, 0x33, +0xDB, 0xB2, 0x01, 0x32, 0x08, 0x2B, 0xF6, 0xD1, 0x12, 0x4A, 0xD2, 0x56, 0x82, 0x42, 0x05, 0xD0, 0x00, 0x29, 0x03, 0xD1, +0x00, 0x2B, 0x01, 0xD0, 0x01, 0x3B, 0xDB, 0xB2, 0x1A, 0x1C, 0x07, 0x2B, 0x00, 0xD9, 0x07, 0x22, 0xD2, 0xB2, 0x0C, 0x4B, +0x99, 0x5C, 0x0C, 0x4A, 0x95, 0x23, 0x9B, 0x00, 0xD3, 0x5C, 0x1A, 0x1C, 0xDB, 0xB2, 0x8B, 0x42, 0x00, 0xD9, 0x0A, 0x1C, +0x07, 0x49, 0x08, 0x4B, 0xCB, 0x5C, 0x18, 0x1C, 0xDB, 0xB2, 0xD1, 0xB2, 0x8B, 0x42, 0x00, 0xD2, 0x10, 0x1C, 0xC0, 0xB2, +0x10, 0xBD, 0xC0, 0x46, 0x28, 0xE0, 0x10, 0x00, 0xBC, 0xDF, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x55, 0x02, 0x00, 0x00, +0x10, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, 0x1E, 0x2B, 0x13, 0xD0, +0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x0D, 0x48, 0x09, 0x5C, 0x09, 0x19, 0x01, 0x20, 0x8B, 0x42, 0x09, 0xDB, 0x1B, 0x1B, +0xDB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, 0x10, 0xBD, +0x0E, 0x3B, 0xE9, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, 0x57, 0x02, 0x00, 0x00, +0x55, 0x02, 0x00, 0x00, 0x30, 0xB5, 0x62, 0x22, 0x42, 0x43, 0x0F, 0x4B, 0x9C, 0x46, 0x62, 0x44, 0x13, 0x88, 0xDB, 0xB2, +0x1E, 0x2B, 0x12, 0xD0, 0x0C, 0x49, 0x0D, 0x48, 0x0C, 0x5C, 0x1D, 0x19, 0x03, 0x38, 0x09, 0x5C, 0x01, 0x20, 0x8D, 0x42, +0x08, 0xDC, 0xEB, 0xB2, 0x10, 0x2B, 0x08, 0xD0, 0x11, 0x88, 0xFF, 0x20, 0x81, 0x43, 0x0B, 0x43, 0x13, 0x80, 0x00, 0x20, +0x30, 0xBD, 0x0E, 0x3B, 0xEA, 0xE7, 0x0E, 0x33, 0xF4, 0xE7, 0xC0, 0x46, 0x0C, 0x65, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, +0x57, 0x02, 0x00, 0x00, 0x70, 0x47, 0x70, 0x47, 0x70, 0xB5, 0x00, 0x28, 0x1C, 0xD0, 0x12, 0x4B, 0x1D, 0x68, 0x00, 0x2D, +0x18, 0xD0, 0xE9, 0x78, 0x09, 0x02, 0x01, 0x23, 0x19, 0x43, 0x03, 0x33, 0xFF, 0x22, 0x0E, 0x48, 0x81, 0xF7, 0xFA, 0xFE, +0x04, 0x1E, 0x0E, 0xD0, 0x20, 0x00, 0x81, 0xF7, 0x1F, 0xFF, 0xAB, 0xF7, 0x23, 0xFB, 0x03, 0x00, 0x09, 0x48, 0x6A, 0x68, +0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x43, 0x60, 0xD6, 0xF7, 0x9E, 0xFE, 0x70, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x3F, 0x06, 0x00, 0x00, 0xFC, 0xE6, 0x10, 0x00, +0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x22, 0x4B, 0x23, 0x4A, 0x13, 0x60, 0x02, 0x22, 0xFF, 0x32, 0x9C, 0x5C, +0x21, 0x4B, 0xE2, 0x18, 0x12, 0x01, 0x13, 0x88, 0x9B, 0x06, 0x5B, 0x0F, 0x01, 0x2B, 0x04, 0xD0, 0x13, 0x88, 0x9B, 0x06, +0x5B, 0x0F, 0x02, 0x2B, 0x0F, 0xD1, 0x23, 0x01, 0x18, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x1B, 0x7B, 0x00, 0x2B, 0x05, 0xD1, +0x13, 0x88, 0x38, 0x21, 0x8B, 0x43, 0x20, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x15, 0x48, 0x83, 0xF7, 0xB9, 0xFF, 0x15, 0x4B, +0x2A, 0x68, 0x9A, 0x42, 0x0F, 0xD0, 0x14, 0x4F, 0xDE, 0x26, 0x76, 0x00, 0x00, 0x23, 0xBB, 0x51, 0x28, 0x00, 0xD7, 0xF7, +0x4B, 0xF9, 0x11, 0x4B, 0xBB, 0x51, 0xAB, 0xF7, 0xD5, 0xFA, 0xA4, 0x00, 0x0F, 0x4B, 0x18, 0x51, 0xF8, 0xBD, 0x0F, 0x4B, +0x1B, 0x68, 0x02, 0x2B, 0xEB, 0xD1, 0x2B, 0x7C, 0x9B, 0x00, 0x0D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0x0C, 0x4A, +0x12, 0x68, 0x1A, 0x66, 0x1A, 0x61, 0xE0, 0xE7, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, +0xF8, 0xCD, 0x10, 0x00, 0xD1, 0x1F, 0x0D, 0x00, 0x28, 0x19, 0x16, 0x00, 0x35, 0x02, 0x10, 0x00, 0xE0, 0xE5, 0x10, 0x00, +0x50, 0xE0, 0x10, 0x00, 0xF4, 0x29, 0x16, 0x00, 0xE8, 0xE1, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x32, 0xD0, +0x9E, 0x23, 0xC5, 0x5C, 0x1B, 0x4B, 0x00, 0x93, 0x43, 0x68, 0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, +0x04, 0x95, 0x18, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, +0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, +0xFB, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x47, 0x3A, 0x6A, 0x43, 0x0C, 0x4B, 0x9C, 0x46, 0x62, 0x44, +0x13, 0x88, 0xFF, 0x21, 0x8B, 0x43, 0x01, 0x21, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xA0, 0x23, 0xE1, 0x54, 0x09, 0xB0, +0x30, 0xBD, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xF6, 0xE7, 0xD1, 0xBD, 0x10, 0x00, +0xDE, 0x05, 0x00, 0x00, 0x1E, 0x65, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x03, 0x00, 0x0D, 0x00, +0x89, 0x00, 0x2B, 0x4A, 0x8C, 0x58, 0x00, 0x2C, 0x36, 0xD0, 0xA6, 0x22, 0xA2, 0x5C, 0x12, 0x1A, 0x03, 0x20, 0x10, 0x40, +0xC0, 0x18, 0x00, 0x01, 0x00, 0x09, 0x63, 0x68, 0xC3, 0x1A, 0x1A, 0x01, 0x12, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8A, 0x42, +0x26, 0xD8, 0x1B, 0x01, 0x20, 0x2B, 0x23, 0xD9, 0x20, 0x4B, 0x00, 0x93, 0x01, 0x90, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, +0x1D, 0x76, 0x04, 0x95, 0x1D, 0x4B, 0x03, 0x93, 0xA3, 0x7D, 0x6A, 0x46, 0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, +0x93, 0x75, 0xB0, 0x22, 0xA2, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, 0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, +0xD7, 0xF7, 0xA0, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x01, 0xD0, +0x09, 0xB0, 0x30, 0xBD, 0xA3, 0x6F, 0x9B, 0xB2, 0x62, 0x21, 0x4D, 0x43, 0x0D, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0xA3, 0x6F, +0x1B, 0x0C, 0x0C, 0x4A, 0xAA, 0x18, 0x13, 0x80, 0x0B, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x0B, 0x4B, 0x1B, 0x68, 0xDB, 0x03, +0xFF, 0x22, 0xD2, 0x03, 0x1A, 0x40, 0x23, 0x6D, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0xE3, 0xE7, 0x38, 0xE6, 0x10, 0x00, +0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, +0xC8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x00, 0x28, 0x08, 0xD0, 0x08, 0x4B, 0x98, 0x47, 0x08, 0x4B, 0x1B, 0x68, 0xD9, 0x6A, +0x05, 0x20, 0xD7, 0xF7, 0x5B, 0xFF, 0x10, 0xBD, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0xF7, 0xE7, 0xC0, 0x46, 0x85, 0xC0, 0x0A, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, +0x98, 0x47, 0x04, 0x4B, 0x1B, 0x68, 0x59, 0x6B, 0x06, 0x20, 0xD7, 0xF7, 0x43, 0xFF, 0x10, 0xBD, 0xA5, 0xD7, 0x0A, 0x00, +0x24, 0x27, 0x16, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x04, 0x1E, 0x5A, 0xD0, 0x9F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x04, 0xD0, +0xA0, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x09, 0xB0, 0x30, 0xBD, 0x9D, 0x33, 0xC5, 0x5C, 0x2B, 0x4B, 0x00, 0x93, 0x43, 0x68, +0x01, 0x93, 0x83, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1D, 0x76, 0x04, 0x95, 0x27, 0x4B, 0x03, 0x93, 0x83, 0x7D, 0x6A, 0x46, +0x13, 0x75, 0x01, 0x33, 0x53, 0x75, 0x00, 0x23, 0x93, 0x75, 0xB0, 0x22, 0x82, 0x5C, 0x69, 0x46, 0xCA, 0x75, 0x8B, 0x76, +0xCB, 0x76, 0x01, 0x33, 0x4B, 0x76, 0x68, 0x46, 0xD7, 0xF7, 0x1A, 0xF8, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, +0x9F, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0xD3, 0xD1, 0x23, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0xA2, 0x6F, 0x91, 0xB2, 0x62, 0x22, +0x55, 0x43, 0x17, 0x4A, 0xAA, 0x18, 0x11, 0x80, 0xA2, 0x6F, 0x12, 0x0C, 0x15, 0x49, 0x69, 0x18, 0x0A, 0x80, 0x15, 0x4A, +0x94, 0x46, 0x65, 0x44, 0x01, 0x33, 0x5B, 0x08, 0x13, 0x4A, 0x13, 0x43, 0x9B, 0xB2, 0x2B, 0x80, 0x9F, 0x23, 0xE3, 0x5C, +0x01, 0x2B, 0xB7, 0xD1, 0xA5, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, 0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, +0x0C, 0x48, 0xD7, 0xF7, 0x3D, 0xF9, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA4, 0xE7, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, 0xFA, 0x64, 0x61, 0x40, +0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x7D, 0x03, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, +0x00, 0x09, 0x01, 0x4B, 0x18, 0x56, 0x70, 0x47, 0x28, 0xE0, 0x10, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, +0xC0, 0xB5, 0x8A, 0x46, 0x5B, 0x49, 0x09, 0x78, 0x06, 0x29, 0x23, 0xD0, 0x5A, 0x49, 0x0C, 0x78, 0x01, 0x2C, 0x07, 0xD0, +0x20, 0x21, 0x55, 0x46, 0x69, 0x5C, 0x1E, 0x29, 0x08, 0xD8, 0x56, 0x49, 0x01, 0x25, 0x0D, 0x70, 0x20, 0x21, 0x55, 0x46, +0x69, 0x5C, 0x1F, 0x29, 0x00, 0xD9, 0x9B, 0xE0, 0x52, 0x4F, 0xE6, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x79, 0x51, 0x51, 0x46, +0x50, 0x4E, 0xB0, 0x47, 0x50, 0x4B, 0x7B, 0x51, 0x4C, 0x4B, 0x1C, 0x70, 0x00, 0x20, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xA2, 0x46, 0xF0, 0xBD, 0x00, 0x21, 0xE5, 0x20, 0x81, 0xF7, 0xC8, 0xFD, 0x80, 0x46, 0x00, 0x28, 0x14, 0xD0, 0x20, 0x23, +0x52, 0x46, 0xD7, 0x5C, 0x04, 0x33, 0xD1, 0x5C, 0x53, 0x8C, 0xC9, 0x18, 0x89, 0xB2, 0x45, 0x4B, 0x9C, 0x46, 0x61, 0x44, +0x3A, 0x00, 0x40, 0x46, 0xD8, 0xF7, 0xDC, 0xFB, 0x00, 0x2F, 0x64, 0xD0, 0x45, 0x46, 0x41, 0x4B, 0x99, 0x46, 0x14, 0xE0, +0x3B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xE3, 0xE7, 0x05, 0x2C, 0x27, 0xD0, 0x4B, 0x46, +0x1A, 0x88, 0x3B, 0x4B, 0x9A, 0x42, 0x36, 0xD0, 0xE2, 0x43, 0xBF, 0x18, 0xFF, 0xB2, 0x01, 0x34, 0x2D, 0x19, 0x00, 0x2F, +0x4B, 0xD0, 0x2C, 0x78, 0x6E, 0x78, 0x16, 0x2E, 0xED, 0xD0, 0xFF, 0x2E, 0xED, 0xD1, 0x0D, 0x2C, 0xEB, 0xD1, 0xAB, 0x78, +0x5D, 0x2B, 0xE8, 0xD1, 0xEB, 0x78, 0x00, 0x2B, 0xE5, 0xD1, 0x2B, 0x79, 0x03, 0x2B, 0xE2, 0xD1, 0x6B, 0x79, 0x00, 0x2B, +0xDF, 0xD1, 0x2D, 0x48, 0x83, 0xF7, 0xB6, 0xFD, 0x2C, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xD7, 0xE7, 0xAB, 0x78, +0x01, 0x2B, 0xD4, 0xD1, 0xEB, 0x78, 0xFD, 0x2B, 0xD1, 0xD1, 0x2B, 0x79, 0x00, 0x2B, 0xCE, 0xD1, 0x6B, 0x79, 0x01, 0x2B, +0xCB, 0xD1, 0x25, 0x48, 0x83, 0xF7, 0xA2, 0xFD, 0x22, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xC3, 0xE7, 0x1D, 0x4B, +0x5B, 0x88, 0xB3, 0x42, 0xC4, 0xD1, 0x1B, 0x4B, 0x9B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x19, 0x4B, 0x9A, 0x79, 0xA9, 0x1C, +0x98, 0x68, 0xD8, 0xF7, 0x5F, 0xFB, 0x00, 0x28, 0xB8, 0xD1, 0x18, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0xB3, 0xE7, +0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEB, 0xE7, 0x20, 0x23, 0x52, 0x46, 0xD3, 0x5C, +0x00, 0x2B, 0x03, 0xD1, 0x40, 0x46, 0x81, 0xF7, 0xEB, 0xFD, 0x73, 0xE7, 0x50, 0x8C, 0xBA, 0xF7, 0xAD, 0xFD, 0xF7, 0xE7, +0x53, 0x46, 0x58, 0x8C, 0xBA, 0xF7, 0xA8, 0xFD, 0x6A, 0xE7, 0xC0, 0x46, 0xD0, 0xE5, 0x10, 0x00, 0x59, 0xA9, 0x16, 0x00, +0x28, 0x19, 0x16, 0x00, 0x45, 0xF8, 0x0B, 0x00, 0x99, 0x05, 0x10, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC4, 0xE5, 0x10, 0x00, +0x88, 0xAC, 0x00, 0x00, 0x10, 0xCE, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x00, 0xCE, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, +0x07, 0x4E, 0x8A, 0x25, 0x6D, 0x00, 0x00, 0x21, 0x71, 0x51, 0x21, 0x00, 0xB3, 0xF7, 0xF0, 0xFC, 0xA4, 0x00, 0x04, 0x4B, +0xE3, 0x58, 0x04, 0x4A, 0xDA, 0x61, 0x04, 0x4B, 0x73, 0x51, 0x70, 0xBD, 0x28, 0x19, 0x16, 0x00, 0x54, 0x27, 0x16, 0x00, +0x21, 0x61, 0x10, 0x00, 0x41, 0x07, 0x10, 0x00, 0x10, 0xB5, 0xD2, 0x23, 0x5B, 0x00, 0x1B, 0x68, 0x98, 0x47, 0x10, 0xBD, +0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0xE3, 0xB0, 0x01, 0xAC, 0xC2, 0x25, 0x6D, 0x00, 0x2A, 0x00, 0x00, 0x21, +0x20, 0x00, 0x7F, 0xF7, 0xAB, 0xFC, 0x7A, 0x4E, 0x2A, 0x00, 0x00, 0x21, 0x30, 0x68, 0x7F, 0xF7, 0xA5, 0xFC, 0x31, 0x68, +0x2A, 0x00, 0x01, 0xA8, 0xD8, 0xF7, 0x14, 0xFB, 0x75, 0x48, 0x83, 0xF7, 0x1D, 0xFD, 0x50, 0x22, 0x00, 0x21, 0x4E, 0xA8, +0x7F, 0xF7, 0x98, 0xFC, 0x00, 0x26, 0x9A, 0x23, 0x5B, 0x00, 0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x8B, 0xF7, 0x3A, 0xF8, +0x86, 0x3D, 0xC0, 0x23, 0x5B, 0x00, 0xE5, 0x54, 0x80, 0x3B, 0xFF, 0x3B, 0x98, 0x46, 0x82, 0x33, 0xFF, 0x33, 0x42, 0x46, +0xE2, 0x54, 0x03, 0x27, 0x82, 0x23, 0xFF, 0x33, 0xE7, 0x54, 0x0D, 0x3B, 0xE7, 0x54, 0x36, 0x23, 0xFF, 0x33, 0x99, 0x46, +0xE6, 0x54, 0x4E, 0xA9, 0x00, 0x20, 0x87, 0xF7, 0x6B, 0xFE, 0x4B, 0x46, 0xE0, 0x5C, 0x4E, 0xA9, 0x8B, 0xF7, 0x6A, 0xF8, +0x50, 0x22, 0x00, 0x21, 0x3A, 0xA8, 0x7F, 0xF7, 0x6D, 0xFC, 0xE4, 0x23, 0xE6, 0x54, 0x3A, 0xA9, 0x00, 0x20, 0x8B, 0xF7, +0x11, 0xF8, 0x32, 0x23, 0xFF, 0x33, 0xE5, 0x54, 0x30, 0x3B, 0xFF, 0x3B, 0x99, 0x22, 0x52, 0x00, 0xA3, 0x54, 0x02, 0x3A, +0xA3, 0x54, 0x0C, 0x3A, 0xA3, 0x54, 0x19, 0x3D, 0x43, 0x46, 0x63, 0x55, 0x3A, 0xA9, 0x01, 0x20, 0x87, 0xF7, 0x48, 0xFE, +0x60, 0x5D, 0x3A, 0xA9, 0x8B, 0xF7, 0x48, 0xF8, 0x4E, 0x4B, 0x1E, 0x60, 0x4E, 0x4D, 0x2E, 0x60, 0x4E, 0x4B, 0x42, 0x46, +0x1A, 0x60, 0x4E, 0x49, 0x0B, 0x68, 0x4E, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4C, +0x27, 0x60, 0x4C, 0x4B, 0x19, 0x68, 0x4C, 0x48, 0xD7, 0xF7, 0x60, 0xFE, 0x0F, 0x23, 0x03, 0x40, 0x22, 0x68, 0x80, 0x21, +0x8A, 0x43, 0x0A, 0x43, 0x22, 0x60, 0x06, 0x09, 0xFF, 0x22, 0x16, 0x40, 0x46, 0x4F, 0x3E, 0x60, 0x00, 0x0B, 0x10, 0x40, +0x28, 0x60, 0x5A, 0x08, 0x9B, 0x1A, 0x1B, 0x01, 0x9B, 0x18, 0x43, 0x4A, 0x13, 0x60, 0x23, 0x68, 0x8B, 0x43, 0x23, 0x60, +0x41, 0x4B, 0x1B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3F, 0x4A, 0x13, 0x6F, 0x71, 0x39, 0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, +0x13, 0x67, 0x3C, 0x4B, 0x5B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x3A, 0x4A, 0x53, 0x6F, 0x0F, 0x21, 0x8B, 0x43, 0x0D, 0x39, +0x0B, 0x43, 0x53, 0x67, 0x36, 0x4B, 0x9B, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x34, 0x4A, 0x93, 0x6F, 0x0F, 0x21, 0x8B, 0x43, +0x0D, 0x39, 0x0B, 0x43, 0x93, 0x67, 0x31, 0x4B, 0xDB, 0x6F, 0x1B, 0x07, 0x06, 0xD1, 0x2F, 0x4A, 0xD3, 0x6F, 0x0F, 0x21, +0x8B, 0x43, 0x0D, 0x39, 0x0B, 0x43, 0xD3, 0x67, 0x2B, 0x4B, 0x19, 0x69, 0x0F, 0x24, 0xA1, 0x43, 0x03, 0x20, 0x01, 0x43, +0x19, 0x61, 0x59, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x59, 0x61, 0x99, 0x69, 0xA1, 0x43, 0x01, 0x43, 0x99, 0x61, 0xDA, 0x69, +0xA2, 0x43, 0x02, 0x43, 0xDA, 0x61, 0x18, 0x4B, 0x07, 0x22, 0x1A, 0x60, 0x01, 0xAA, 0x00, 0x23, 0x20, 0x21, 0x53, 0x54, +0x06, 0x93, 0x05, 0x93, 0x02, 0x93, 0x01, 0x93, 0x15, 0x4A, 0x13, 0x68, 0x1E, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x1B, 0x4B, +0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, 0x13, 0x68, 0x1E, 0x31, 0x0B, 0x43, 0x13, 0x60, 0x18, 0x4B, 0x9A, 0x68, 0x84, 0x23, +0x17, 0x49, 0xD1, 0x50, 0x17, 0x4B, 0x80, 0x22, 0x92, 0x01, 0x1A, 0x60, 0xC2, 0x22, 0x05, 0x4B, 0x18, 0x68, 0x52, 0x00, +0x01, 0xA9, 0xD8, 0xF7, 0x2F, 0xFA, 0x63, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0xFC, 0xE1, 0x10, 0x00, +0x20, 0xCE, 0x10, 0x00, 0x08, 0x20, 0x04, 0x40, 0x04, 0x20, 0x04, 0x40, 0x24, 0x20, 0x04, 0x40, 0x10, 0x20, 0x04, 0x40, +0xFF, 0xFE, 0xFF, 0xFF, 0x0C, 0x20, 0x04, 0x40, 0xB8, 0xE5, 0x10, 0x00, 0x00, 0x75, 0x19, 0x03, 0x00, 0x20, 0x04, 0x40, +0x28, 0x20, 0x04, 0x40, 0x00, 0x30, 0x50, 0x40, 0xBC, 0xE5, 0x10, 0x00, 0x00, 0xED, 0x00, 0xE0, 0xC5, 0x88, 0x08, 0x00, +0x00, 0xE1, 0x00, 0xE0, 0x70, 0x47, 0x70, 0x47, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x8D, 0x22, 0x12, 0x03, +0x1A, 0x60, 0x3D, 0x4B, 0x3D, 0x4A, 0x1A, 0x60, 0x3D, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, 0x3E, 0x4B, 0x3E, 0x4A, 0x1A, 0x60, +0x3E, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x3F, 0x4A, 0x1A, 0x60, 0x3F, 0x4B, 0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, +0x40, 0x4A, 0x1A, 0x60, 0x40, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x41, 0x4A, 0x1A, 0x60, 0x41, 0x4B, 0x42, 0x4A, +0x1A, 0x60, 0x42, 0x4B, 0x42, 0x4A, 0x1A, 0x60, 0x42, 0x4B, 0x43, 0x4A, 0x1A, 0x60, 0x43, 0x4B, 0x43, 0x4A, 0x1A, 0x60, +0x43, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x44, 0x4A, 0x1A, 0x60, 0x44, 0x4B, 0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, +0x45, 0x4A, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x88, 0x22, +0x52, 0x01, 0x1A, 0x60, 0x45, 0x4B, 0x46, 0x4A, 0x1A, 0x60, 0x46, 0x4B, 0x46, 0x4A, 0x13, 0x60, 0x46, 0x4A, 0x47, 0x49, +0x11, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4A, 0x13, 0x60, 0x47, 0x4B, 0x47, 0x4A, 0x1A, 0x60, +0x47, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x48, 0x4A, 0x1A, 0x60, 0x48, 0x4B, 0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, +0x49, 0x4A, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0xFF, 0x22, +0x12, 0x02, 0x1A, 0x60, 0x49, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x74, 0x22, +0x1A, 0x60, 0x4A, 0x4B, 0x4A, 0x4A, 0x1A, 0x60, 0x4A, 0x4B, 0x4B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x01, 0x58, 0x40, +0xFB, 0x33, 0x09, 0x00, 0x1C, 0x20, 0x62, 0x40, 0x28, 0x20, 0x62, 0x40, 0x20, 0x20, 0x91, 0x48, 0x14, 0x20, 0x62, 0x40, +0x83, 0x89, 0x01, 0x00, 0x54, 0x20, 0x62, 0x40, 0x34, 0x8F, 0x00, 0x00, 0x48, 0x07, 0x62, 0x40, 0xA0, 0x01, 0x1A, 0x02, +0x28, 0x07, 0x62, 0x40, 0x20, 0x00, 0x01, 0x00, 0x38, 0x07, 0x62, 0x40, 0xD4, 0x0F, 0x80, 0x04, 0x3C, 0x07, 0x62, 0x40, +0x64, 0x00, 0xC8, 0x00, 0x2C, 0x20, 0x62, 0x40, 0x20, 0xB2, 0x0C, 0x00, 0x0C, 0x20, 0x62, 0x40, 0x45, 0x2B, 0xAD, 0xE9, +0x30, 0x20, 0x62, 0x40, 0xD2, 0x30, 0x0C, 0x14, 0x34, 0x20, 0x62, 0x40, 0x02, 0x16, 0x00, 0x00, 0x54, 0x07, 0x62, 0x40, +0xFD, 0x20, 0x42, 0x21, 0x58, 0x07, 0x62, 0x40, 0x1E, 0xF0, 0x07, 0x00, 0x1C, 0x07, 0x62, 0x40, 0x33, 0x0A, 0x00, 0x00, +0x18, 0x20, 0x62, 0x40, 0x24, 0x41, 0x12, 0x00, 0x0C, 0x00, 0x62, 0x40, 0x00, 0x00, 0x04, 0x04, 0x90, 0x00, 0x62, 0x40, +0x82, 0x90, 0x06, 0x00, 0x34, 0x10, 0x62, 0x40, 0x80, 0x30, 0x00, 0x02, 0x14, 0x10, 0x62, 0x40, 0x7A, 0x11, 0x45, 0x04, +0x24, 0x20, 0x62, 0x40, 0x04, 0x20, 0x62, 0x40, 0xC0, 0xA9, 0x01, 0x00, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, +0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, 0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, +0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, 0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, +0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, 0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, +0xA0, 0x05, 0x62, 0x40, 0x00, 0x0C, 0x15, 0x14, 0xA4, 0x05, 0x62, 0x40, 0x24, 0x36, 0x2D, 0x36, 0xF0, 0x05, 0x62, 0x40, +0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, 0x30, 0x05, 0x62, 0x40, 0x00, 0x12, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, +0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, 0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x2A, 0x49, 0x0B, 0x68, +0x2A, 0x4A, 0x1A, 0x40, 0xFC, 0x23, 0x9B, 0x05, 0x13, 0x43, 0x0B, 0x60, 0x28, 0x4B, 0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, +0x29, 0x4A, 0x1A, 0x60, 0x29, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2A, 0x4A, 0x1A, 0x60, 0x2A, 0x4B, 0x2B, 0x4A, +0x1A, 0x60, 0x2B, 0x4B, 0x2B, 0x4A, 0x1A, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x2C, 0x49, 0x11, 0x60, +0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4A, 0x13, 0x60, 0x2C, 0x4B, 0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, +0x2D, 0x4A, 0x1A, 0x60, 0x2D, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2E, 0x4A, 0x1A, 0x60, 0x2E, 0x4B, 0x2F, 0x4A, +0x1A, 0x60, 0x2F, 0x4B, 0x2F, 0x4A, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, +0x30, 0x4B, 0xFF, 0x22, 0x12, 0x02, 0x1A, 0x60, 0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x76, 0x22, 0x1A, 0x60, +0x2F, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x30, 0x4A, 0x1A, 0x60, 0x30, 0x4B, 0x31, 0x4A, 0x1A, 0x60, 0x31, 0x4B, +0x31, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x0C, 0x00, 0x58, 0x40, 0xFF, 0xFF, 0xFF, 0xC0, 0x04, 0x01, 0x58, 0x40, +0xFB, 0x33, 0x09, 0x00, 0x20, 0x40, 0x34, 0x40, 0x77, 0x0B, 0x00, 0x00, 0x24, 0x40, 0x34, 0x40, 0x94, 0xC5, 0x6E, 0x00, +0x28, 0x40, 0x34, 0x40, 0x02, 0x94, 0x00, 0x00, 0x2C, 0x40, 0x34, 0x40, 0x84, 0x18, 0x20, 0x56, 0x30, 0x40, 0x34, 0x40, +0x68, 0x51, 0x2E, 0x1A, 0x34, 0x08, 0x50, 0x00, 0x8C, 0x04, 0x60, 0x40, 0x10, 0x01, 0x60, 0x40, 0x58, 0x00, 0x7E, 0x02, +0x80, 0x08, 0x60, 0x40, 0x84, 0x08, 0x60, 0x40, 0x88, 0x08, 0x60, 0x40, 0x8C, 0x08, 0x60, 0x40, 0x34, 0x08, 0x00, 0x00, +0x18, 0x05, 0x62, 0x40, 0x0A, 0x88, 0x92, 0x36, 0x14, 0x05, 0x62, 0x40, 0x10, 0x1A, 0x0C, 0xA8, 0x2C, 0x05, 0x62, 0x40, +0x03, 0x14, 0x0C, 0x9C, 0x0C, 0x05, 0x62, 0x40, 0x13, 0x20, 0x20, 0x20, 0x08, 0x05, 0x62, 0x40, 0x32, 0x31, 0x55, 0x54, +0xA0, 0x05, 0x62, 0x40, 0x00, 0x16, 0x17, 0x0F, 0xA4, 0x05, 0x62, 0x40, 0x36, 0x36, 0x28, 0x36, 0xF0, 0x05, 0x62, 0x40, +0x30, 0x05, 0x62, 0x40, 0x00, 0x1A, 0x17, 0x13, 0x34, 0x05, 0x62, 0x40, 0xB0, 0x05, 0x62, 0x40, 0x55, 0x53, 0x00, 0x00, +0x1C, 0x05, 0x62, 0x40, 0x66, 0x57, 0x4B, 0x96, 0x90, 0x00, 0x62, 0x40, 0x32, 0x00, 0x05, 0x00, 0x10, 0x10, 0x62, 0x40, +0x43, 0x01, 0x00, 0x12, 0x10, 0xB5, 0x01, 0x28, 0x03, 0xD0, 0x02, 0x38, 0x01, 0x28, 0x05, 0xD9, 0x10, 0xBD, 0x87, 0xF7, +0x99, 0xFF, 0xFF, 0xF7, 0x2B, 0xFE, 0xF9, 0xE7, 0x88, 0xF7, 0x96, 0xF8, 0x0A, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x05, +0x0B, 0x43, 0x13, 0x60, 0xFF, 0xF7, 0x32, 0xFF, 0x07, 0x4B, 0x1B, 0x68, 0x9B, 0x02, 0xEB, 0xD4, 0x05, 0x49, 0x0B, 0x68, +0x05, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xE2, 0xE7, 0xC0, 0x46, 0x1C, 0x20, 0x34, 0x40, +0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0x7F, 0xFF, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, +0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x00, 0x24, 0x25, 0x4A, 0x26, 0x4B, 0x9B, 0x46, 0xE0, 0x23, 0xDB, 0x04, 0x9A, 0x46, +0xC0, 0x23, 0x9B, 0x05, 0x99, 0x46, 0x23, 0x4B, 0x98, 0x46, 0x23, 0x4B, 0x00, 0x93, 0x23, 0x4F, 0x23, 0x4E, 0x13, 0x68, +0x58, 0x46, 0x03, 0x40, 0x50, 0x46, 0x20, 0x40, 0x03, 0x43, 0x13, 0x60, 0x13, 0x68, 0x48, 0x46, 0x03, 0x43, 0x13, 0x60, +0x43, 0x46, 0x1B, 0x68, 0x00, 0x98, 0x00, 0x68, 0x1B, 0x04, 0x3B, 0x40, 0x40, 0x04, 0x40, 0x0C, 0x03, 0x43, 0x08, 0xC5, +0x13, 0x68, 0x33, 0x40, 0x13, 0x60, 0x80, 0x23, 0x5B, 0x04, 0x9C, 0x46, 0x64, 0x44, 0x80, 0x23, 0xDB, 0x04, 0x9C, 0x42, +0xDF, 0xD1, 0x04, 0x20, 0x01, 0x9B, 0x01, 0x2B, 0x06, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, +0xAB, 0x46, 0xF0, 0xBD, 0x0E, 0x4B, 0x1B, 0x68, 0x0B, 0x61, 0x0E, 0x4B, 0x1B, 0x68, 0x4B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, +0x8B, 0x61, 0x0D, 0x4B, 0x1B, 0x68, 0xCB, 0x61, 0x0C, 0x4B, 0x1B, 0x68, 0x0B, 0x62, 0x05, 0x30, 0xE7, 0xE7, 0xC0, 0x46, +0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0x8C, 0x08, 0x62, 0x40, 0x90, 0x08, 0x62, 0x40, 0x00, 0x00, 0xFF, 0x7F, +0xFF, 0xFF, 0xFF, 0xCF, 0x30, 0x07, 0x62, 0x40, 0x34, 0x07, 0x62, 0x40, 0x5C, 0x07, 0x62, 0x40, 0x60, 0x07, 0x62, 0x40, +0x20, 0x20, 0x62, 0x40, 0x12, 0x04, 0x12, 0x4B, 0x1A, 0x40, 0x49, 0x04, 0x49, 0x0C, 0x0A, 0x43, 0x10, 0x4B, 0x1A, 0x60, +0x10, 0x4B, 0x1A, 0x68, 0x00, 0x06, 0xE0, 0x21, 0xC9, 0x04, 0x08, 0x40, 0x0E, 0x49, 0x0A, 0x40, 0x10, 0x43, 0x18, 0x60, +0x19, 0x68, 0x80, 0x22, 0x12, 0x06, 0x0A, 0x43, 0x1A, 0x60, 0x19, 0x68, 0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, +0x1A, 0x68, 0x08, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x52, 0x00, 0x52, 0x08, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, +0x00, 0x00, 0xFF, 0x7F, 0x44, 0x05, 0x62, 0x40, 0x28, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, +0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x1C, 0x49, 0x0B, 0x68, 0x99, 0x46, 0x1C, 0x4A, +0x1A, 0x40, 0x1C, 0x4B, 0x13, 0x43, 0x0B, 0x60, 0x1B, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x9A, 0x46, +0x00, 0x24, 0xF0, 0x23, 0x47, 0x46, 0x9F, 0x43, 0x16, 0x4E, 0xE5, 0xB2, 0x00, 0x22, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, +0xB1, 0xFF, 0x23, 0x01, 0x3B, 0x43, 0x33, 0x60, 0x88, 0xF7, 0x3D, 0xF9, 0x69, 0x46, 0x01, 0xA8, 0x88, 0xF7, 0x4A, 0xF9, +0x00, 0x9A, 0x01, 0x99, 0x28, 0x00, 0xFF, 0xF7, 0xA3, 0xFF, 0x01, 0x34, 0x04, 0x2C, 0xE8, 0xD1, 0x07, 0x4B, 0x4A, 0x46, +0x1A, 0x60, 0x09, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x08, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, +0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x1C, 0x05, 0x62, 0x40, 0xFF, 0xFF, 0x8F, 0x7F, 0x0A, 0x00, 0x20, 0x00, +0x08, 0x05, 0x62, 0x40, 0x04, 0x00, 0x62, 0x40, 0x70, 0xB5, 0x0C, 0x4D, 0x2C, 0x68, 0x2A, 0x68, 0x0B, 0x4E, 0x32, 0x40, +0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x2B, 0x60, 0x26, 0x20, 0x88, 0xF7, 0x3F, 0xFF, 0xFF, 0xF7, 0xA7, 0xFF, 0x88, 0xF7, +0x81, 0xFF, 0x2B, 0x68, 0xE4, 0x05, 0xE4, 0x0F, 0x24, 0x02, 0x33, 0x40, 0x1C, 0x43, 0x2C, 0x60, 0x70, 0xBD, 0xC0, 0x46, +0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0x10, 0xB5, 0x26, 0x20, 0x88, 0xF7, 0x62, 0xF9, 0xFF, 0xF7, 0x92, 0xFF, +0x88, 0xF7, 0xBA, 0xF9, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, +0x8B, 0xB0, 0x82, 0x46, 0x0C, 0x00, 0x03, 0x68, 0x7F, 0x22, 0x1A, 0x40, 0x93, 0x46, 0x1E, 0x09, 0x0F, 0x25, 0x2E, 0x40, +0x1D, 0x40, 0x01, 0x95, 0x0C, 0x22, 0x13, 0x42, 0x05, 0xD0, 0x35, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, +0x98, 0x47, 0x01, 0x9B, 0x9E, 0x42, 0x05, 0xD9, 0x30, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x2E, 0x4B, 0x98, 0x46, 0x1F, 0x68, 0x1A, 0x68, 0x2D, 0x4B, 0x99, 0x46, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, +0x42, 0x46, 0x13, 0x60, 0x58, 0x46, 0x88, 0xF7, 0xF1, 0xFE, 0x53, 0x46, 0x19, 0x68, 0x03, 0xA8, 0x89, 0xF7, 0x0E, 0xF9, +0x88, 0xF7, 0x30, 0xFF, 0x43, 0x46, 0x1B, 0x68, 0xFF, 0x05, 0xFF, 0x0F, 0x3F, 0x02, 0x4A, 0x46, 0x13, 0x40, 0x1F, 0x43, +0x43, 0x46, 0x1F, 0x60, 0x01, 0x9B, 0x9E, 0x42, 0x30, 0xD8, 0x37, 0x00, 0x20, 0x36, 0x36, 0x01, 0x1D, 0x4B, 0xF6, 0x18, +0x03, 0xA9, 0x1D, 0x4B, 0x98, 0x46, 0xF0, 0x23, 0x1B, 0x05, 0x9C, 0x46, 0x23, 0x1D, 0x99, 0x46, 0x05, 0xE0, 0x01, 0x37, +0x10, 0x36, 0xFB, 0xB2, 0x01, 0x9A, 0x9A, 0x42, 0x1C, 0xD3, 0x7B, 0x18, 0x1A, 0x7D, 0x12, 0x02, 0xDB, 0x7B, 0x1A, 0x43, +0x43, 0x46, 0x1A, 0x43, 0x32, 0x60, 0x7B, 0x5C, 0x18, 0x05, 0x65, 0x46, 0x28, 0x40, 0x1B, 0x07, 0x5B, 0x0F, 0x5B, 0x07, +0x03, 0x43, 0x70, 0x68, 0x00, 0x02, 0x00, 0x0A, 0x03, 0x43, 0x73, 0x60, 0x00, 0x2C, 0xE2, 0xD0, 0xFB, 0x00, 0xE2, 0x50, +0x4A, 0x46, 0x70, 0x68, 0xD0, 0x50, 0xDC, 0xE7, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, +0xF0, 0xBD, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xD8, 0x99, 0x16, 0x00, +0x00, 0x00, 0x80, 0x80, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x05, 0x00, +0x01, 0x91, 0x03, 0x68, 0x5A, 0x02, 0x52, 0x0E, 0x90, 0x46, 0x1C, 0x09, 0x0F, 0x26, 0x34, 0x40, 0x1E, 0x40, 0x0C, 0x22, +0x13, 0x42, 0x05, 0xD0, 0x38, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0x42, 0x2F, 0xD9, +0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x40, 0x46, 0x88, 0xF7, 0xAD, 0xF8, 0x29, 0x68, +0x02, 0xA8, 0x88, 0xF7, 0x09, 0xFB, 0x88, 0xF7, 0x03, 0xF9, 0x80, 0x22, 0x52, 0x00, 0x2D, 0x49, 0x2D, 0x48, 0xD7, 0xF7, +0x49, 0xFE, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x01, 0x35, 0xEB, 0xB2, +0x9E, 0x42, 0xEE, 0xD3, 0x2B, 0x01, 0xA8, 0x00, 0x63, 0x44, 0x1A, 0x68, 0x22, 0x40, 0x02, 0xA9, 0x41, 0x58, 0x00, 0x91, +0xC9, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x01, 0x9B, 0x00, 0x2B, 0xED, 0xD0, 0x1A, 0x50, 0xEB, 0xE7, 0x40, 0x46, 0x88, 0xF7, +0x83, 0xF8, 0x29, 0x68, 0x02, 0xA8, 0x88, 0xF7, 0xDF, 0xFA, 0x25, 0x00, 0xA2, 0x00, 0x02, 0xAB, 0x9C, 0x46, 0x62, 0x44, +0xFC, 0x23, 0x1B, 0x01, 0x98, 0x46, 0xF8, 0x23, 0x5B, 0x02, 0x9C, 0x46, 0x3F, 0x20, 0xF8, 0x23, 0x9B, 0x03, 0x9B, 0x46, +0x13, 0x68, 0x1F, 0x0A, 0x41, 0x46, 0x0F, 0x40, 0xB9, 0x46, 0xD9, 0x00, 0x0F, 0x00, 0x61, 0x46, 0x0F, 0x40, 0xBA, 0x46, +0x4F, 0x46, 0x51, 0x46, 0x0F, 0x43, 0xB9, 0x46, 0x19, 0x0D, 0x0F, 0x00, 0x07, 0x40, 0xBA, 0x46, 0x4F, 0x46, 0x51, 0x46, +0x0F, 0x43, 0x5B, 0x03, 0x59, 0x46, 0x0B, 0x40, 0x3B, 0x43, 0x08, 0xC2, 0x01, 0x34, 0xE4, 0xB2, 0xA6, 0x42, 0xE1, 0xD2, +0x88, 0xF7, 0xAC, 0xF8, 0x02, 0x4B, 0x9C, 0x46, 0x03, 0x4C, 0xB5, 0xE7, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x97, 0x16, 0x00, +0x00, 0x50, 0x1E, 0x00, 0x7F, 0x00, 0x00, 0xE0, 0x70, 0xB5, 0x8E, 0xB0, 0x87, 0xF7, 0x76, 0xFF, 0x04, 0x00, 0x01, 0x28, +0x05, 0xD0, 0x83, 0x1E, 0xDB, 0xB2, 0x01, 0x2B, 0x24, 0xD9, 0x0E, 0xB0, 0x70, 0xBD, 0x1C, 0x4B, 0x00, 0x93, 0x1C, 0x4C, +0x25, 0x68, 0xF0, 0x23, 0x2A, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x70, 0x22, 0x13, 0x43, 0x23, 0x60, 0x01, 0xA9, 0x68, 0x46, +0xFF, 0xF7, 0x56, 0xFF, 0x25, 0x60, 0x16, 0x4B, 0x00, 0x93, 0x00, 0x21, 0x68, 0x46, 0x88, 0xF7, 0xE9, 0xFC, 0x00, 0x20, +0x88, 0xF7, 0xD0, 0xFB, 0x05, 0xA9, 0x01, 0x20, 0xFF, 0xF7, 0xB0, 0xFD, 0x01, 0x20, 0x89, 0xF7, 0x43, 0xFA, 0xFF, 0xF7, +0xAF, 0xFE, 0xDA, 0xE7, 0x0A, 0x4B, 0x00, 0x93, 0x0A, 0x4D, 0x2E, 0x68, 0xF0, 0x23, 0x32, 0x00, 0x9A, 0x43, 0x13, 0x00, +0x70, 0x22, 0x13, 0x43, 0x2B, 0x60, 0x01, 0xA9, 0x68, 0x46, 0xFF, 0xF7, 0xA9, 0xFE, 0x2E, 0x60, 0x20, 0x00, 0x89, 0xF7, +0x2D, 0xFA, 0xFF, 0xF7, 0x7B, 0xFE, 0xC4, 0xE7, 0x03, 0x42, 0x26, 0x00, 0x08, 0x05, 0x62, 0x40, 0x0F, 0x30, 0x02, 0x00, +0x30, 0xB5, 0x83, 0xB0, 0x41, 0x4B, 0x18, 0x78, 0x87, 0xF7, 0x12, 0xFF, 0x40, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x06, 0x21, +0xD1, 0x50, 0x3F, 0x4B, 0x5A, 0x68, 0x3F, 0x49, 0x0A, 0x40, 0x5A, 0x60, 0x59, 0x68, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, +0x5A, 0x60, 0x19, 0x00, 0x44, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x04, 0x2B, 0xFB, 0xD1, 0x39, 0x4B, 0x18, 0x68, 0x39, 0x49, +0xD7, 0xF7, 0x32, 0xF9, 0xA0, 0x23, 0x5B, 0x03, 0x03, 0x43, 0x37, 0x4A, 0x13, 0x60, 0x37, 0x49, 0x08, 0x43, 0x10, 0x60, +0x13, 0x60, 0x30, 0x4B, 0x59, 0x68, 0x35, 0x4A, 0x0A, 0x43, 0x5A, 0x60, 0x2C, 0x49, 0x9A, 0x22, 0x52, 0x00, 0x80, 0x20, +0x40, 0x01, 0x88, 0x50, 0x1A, 0x68, 0x40, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x18, 0x68, 0x02, 0x24, 0x20, 0x43, 0x18, 0x60, +0x48, 0x6F, 0x01, 0x22, 0x10, 0x43, 0x48, 0x67, 0x59, 0x6D, 0x2B, 0x4A, 0x11, 0x40, 0x59, 0x65, 0x5A, 0x6D, 0x22, 0x43, +0x5A, 0x65, 0x5A, 0x6D, 0x28, 0x49, 0x0A, 0x40, 0x5A, 0x65, 0x87, 0xF7, 0xE1, 0xFE, 0x04, 0x00, 0x80, 0x22, 0x52, 0x00, +0x25, 0x49, 0x26, 0x48, 0xD7, 0xF7, 0x4C, 0xFD, 0x80, 0x22, 0x25, 0x49, 0x25, 0x48, 0xD7, 0xF7, 0x47, 0xFD, 0x01, 0x2C, +0x05, 0xD1, 0x17, 0x4B, 0xDB, 0x6D, 0x9B, 0x07, 0x0D, 0xD5, 0x03, 0xB0, 0x30, 0xBD, 0xC0, 0x22, 0x92, 0x00, 0x20, 0x49, +0x20, 0x48, 0xD7, 0xF7, 0x39, 0xFD, 0x80, 0x22, 0x1F, 0x49, 0x20, 0x48, 0xD7, 0xF7, 0x34, 0xFD, 0xED, 0xE7, 0x20, 0x00, +0x87, 0xF7, 0xD2, 0xFE, 0x20, 0x00, 0xFF, 0xF7, 0xF1, 0xFC, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0xFF, 0xF7, 0x39, 0xFF, 0x05, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xDF, 0xD1, 0x16, 0x4A, 0x13, 0x68, 0x01, 0x21, +0x8B, 0x43, 0x13, 0x60, 0xD9, 0xE7, 0xC0, 0x46, 0xB4, 0xE5, 0x10, 0x00, 0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, +0xFF, 0xFF, 0xFB, 0xFF, 0xB0, 0x06, 0x16, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x08, 0x00, 0x58, 0x40, 0x00, 0x00, 0x14, 0x80, +0x02, 0x88, 0x01, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x58, 0xE0, 0x10, 0x00, 0xD8, 0x97, 0x16, 0x00, +0x58, 0xE1, 0x10, 0x00, 0xD8, 0x98, 0x16, 0x00, 0x18, 0xE2, 0x10, 0x00, 0xD8, 0x99, 0x16, 0x00, 0x18, 0xE5, 0x10, 0x00, +0x58, 0x99, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x38, 0x27, 0x16, 0x00, +0x80, 0x00, 0x01, 0x4B, 0xC0, 0x58, 0x70, 0x47, 0x54, 0x27, 0x16, 0x00, 0x80, 0x00, 0x01, 0x4B, 0x19, 0x50, 0x70, 0x47, +0x54, 0x27, 0x16, 0x00, 0x03, 0x23, 0x03, 0x40, 0x8B, 0x42, 0x05, 0xD8, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0x00, 0x01, +0x00, 0x09, 0x70, 0x47, 0x03, 0x30, 0x03, 0x23, 0x98, 0x43, 0x40, 0x18, 0xF7, 0xE7, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, +0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x06, 0xAB, 0x04, 0xCB, 0x90, 0x46, 0x1A, 0x78, 0x1B, 0x4B, 0x1B, 0x78, +0x00, 0x2B, 0x01, 0xD0, 0x00, 0x2A, 0x06, 0xD0, 0x18, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x00, 0x21, 0x99, 0x70, 0xD9, 0x70, +0x5A, 0x70, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x18, 0x00, 0x13, 0x49, 0xD7, 0xF7, 0x63, 0xF8, 0x06, 0x00, +0x10, 0x4B, 0x5D, 0x60, 0x9F, 0x60, 0xDC, 0x60, 0x18, 0x61, 0x00, 0x2C, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0A, 0x4D, 0x21, 0x00, 0x38, 0x00, 0xD7, 0xF7, 0xD6, 0xF8, 0x29, 0x77, 0x43, 0x46, +0x6B, 0x61, 0xA4, 0x1B, 0x62, 0x01, 0x12, 0x1B, 0x92, 0x00, 0x12, 0x19, 0x90, 0x00, 0x12, 0x18, 0x78, 0x3A, 0xAA, 0x61, +0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x74, 0xE6, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, +0xF0, 0xB5, 0xDE, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x01, 0x92, 0x99, 0x46, +0x40, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x05, 0xD0, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA3, 0x46, 0xF0, 0xBD, +0x3C, 0x4B, 0x1E, 0x68, 0xB4, 0x68, 0x00, 0x2C, 0xF4, 0xD0, 0x00, 0x25, 0x1F, 0x23, 0x9B, 0x46, 0x01, 0x27, 0x03, 0xE0, +0x3B, 0x00, 0x83, 0x40, 0x9C, 0x43, 0x0D, 0xD0, 0x20, 0x00, 0xD7, 0xF7, 0x8B, 0xF9, 0x5B, 0x46, 0x18, 0x1A, 0x43, 0x1C, +0xDB, 0x00, 0xF3, 0x18, 0x5B, 0x68, 0x00, 0x2B, 0xF0, 0xD0, 0x01, 0x35, 0xED, 0xB2, 0xED, 0xE7, 0x01, 0x2D, 0xDB, 0xD1, +0x2C, 0x4B, 0x5C, 0x68, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1E, 0x00, 0x2B, 0x49, 0x18, 0x00, 0xD6, 0xF7, +0xFD, 0xFF, 0x05, 0x00, 0x64, 0x68, 0x04, 0x19, 0x27, 0x49, 0x30, 0x00, 0xD7, 0xF7, 0x7C, 0xF8, 0x4B, 0x46, 0x9B, 0x68, +0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0x4B, 0x46, 0x99, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, +0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x54, 0xFF, 0x04, 0x00, 0x43, 0x46, 0x1B, 0x68, 0xE1, 0x1A, 0x0A, 0x01, 0x12, 0x09, +0x80, 0x20, 0x00, 0x05, 0x82, 0x42, 0x11, 0xD8, 0x09, 0x01, 0x0F, 0xD0, 0x15, 0x4A, 0xD1, 0x68, 0xCB, 0x18, 0xE2, 0x1A, +0x12, 0x01, 0x12, 0x09, 0x82, 0x42, 0x07, 0xD8, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x1A, 0x1B, 0x01, 0x02, 0xD0, 0x64, 0x1A, +0x24, 0x01, 0x24, 0x09, 0x43, 0x46, 0x1C, 0x60, 0x0C, 0x4B, 0xDA, 0x68, 0x55, 0x1B, 0x68, 0x01, 0x40, 0x1B, 0x80, 0x00, +0x40, 0x19, 0x82, 0x00, 0x80, 0x18, 0x0B, 0x4A, 0x94, 0x46, 0x60, 0x44, 0x00, 0x9A, 0x10, 0x60, 0xD8, 0x68, 0x60, 0x28, +0x02, 0xD8, 0x01, 0x9B, 0x18, 0x60, 0x87, 0xE7, 0x24, 0x21, 0xD6, 0xF7, 0xB1, 0xFF, 0x01, 0x9B, 0x18, 0x60, 0x81, 0xE7, +0x74, 0xE6, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x1E, 0xFB, 0xFF, 0xFF, 0x03, 0x4B, 0x1B, 0x78, +0x00, 0x2B, 0x02, 0xD0, 0x01, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0x74, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, +0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x01, 0x92, 0x38, 0x4B, 0x38, 0x4A, 0x13, 0x60, +0x9C, 0x68, 0x00, 0x2C, 0x08, 0xD0, 0x43, 0x68, 0x9B, 0x46, 0x36, 0x4B, 0x99, 0x46, 0x36, 0x4B, 0x98, 0x46, 0x33, 0x4B, +0x9A, 0x46, 0x0F, 0xE0, 0xD5, 0xF7, 0x8C, 0xF9, 0x04, 0x1E, 0x5B, 0xD0, 0x73, 0x68, 0x9B, 0x46, 0xF1, 0xE7, 0x75, 0x60, +0x53, 0x46, 0x1B, 0x68, 0x9B, 0x68, 0xA3, 0x42, 0x46, 0xD0, 0x24, 0x68, 0x00, 0x2C, 0x47, 0xD0, 0x21, 0x00, 0x30, 0x00, +0xC8, 0x47, 0x00, 0x28, 0x43, 0xD0, 0x05, 0x28, 0xF0, 0xD0, 0xA3, 0x68, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, +0x41, 0x46, 0x18, 0x00, 0xD6, 0xF7, 0x64, 0xFF, 0x63, 0x68, 0xC5, 0x18, 0x41, 0x46, 0x38, 0x00, 0xD6, 0xF7, 0xE4, 0xFF, +0xB3, 0x68, 0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x6D, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, +0x03, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0xBE, 0xFE, 0x05, 0x00, 0x5B, 0x46, 0xEB, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, +0x12, 0x05, 0x93, 0x42, 0x04, 0xD9, 0x5B, 0x46, 0x5B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x01, 0x9A, 0x93, 0x42, +0xC1, 0xD9, 0x63, 0x7E, 0x0B, 0x2B, 0x03, 0xD8, 0x10, 0x4A, 0xDA, 0x40, 0xD3, 0x07, 0xBA, 0xD4, 0xA3, 0x7D, 0xB2, 0x7D, +0x01, 0x20, 0x9A, 0x42, 0x07, 0xD8, 0x01, 0x33, 0xB3, 0x75, 0x04, 0xE0, 0xD5, 0xF7, 0x38, 0xF9, 0x04, 0x00, 0xB5, 0xE7, +0x00, 0x20, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x00, 0x20, 0xF6, 0xE7, +0x64, 0x2A, 0x16, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x51, 0x62, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x6A, 0x0C, 0x00, 0x00, +0x01, 0x4B, 0x18, 0x68, 0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x18, 0x40, +0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x80, 0x07, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, +0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0xC0, 0x07, 0x70, 0x47, 0xC0, 0x46, 0x48, 0x30, 0x34, 0x40, +0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x48, 0x30, 0x34, 0x40, 0x02, 0x4B, 0x18, 0x68, 0x40, 0x07, 0xC0, 0x0F, +0x70, 0x47, 0xC0, 0x46, 0x94, 0x40, 0x04, 0x40, 0x03, 0x4B, 0x1B, 0x68, 0x14, 0x20, 0x18, 0x40, 0x43, 0x1E, 0x98, 0x41, +0xC0, 0xB2, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x02, 0x4B, 0x18, 0x68, 0xC0, 0x06, 0xC0, 0x0F, 0x70, 0x47, 0xC0, 0x46, +0x94, 0x40, 0x04, 0x40, 0x01, 0x4B, 0x18, 0x68, 0xC0, 0x0F, 0x70, 0x47, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0x10, 0x4B, +0x1A, 0x68, 0x00, 0x23, 0x01, 0x2A, 0x02, 0xD9, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFF, 0x00, 0x23, +0x00, 0x28, 0xF7, 0xD0, 0xFF, 0xF7, 0xE2, 0xFF, 0x00, 0x28, 0x03, 0xD1, 0x08, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x05, 0xDA, +0xFF, 0xF7, 0xB2, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, 0xE9, 0xE7, 0xFF, 0xF7, 0xC2, 0xFF, 0x00, 0x23, 0x00, 0x28, +0xE4, 0xD0, 0xF3, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0x98, 0x40, 0x04, 0x40, 0x10, 0xB5, 0xFF, 0xF7, 0xB7, 0xFF, 0x00, 0x23, +0x00, 0x28, 0x02, 0xD1, 0x01, 0x20, 0x18, 0x40, 0x10, 0xBD, 0xFF, 0xF7, 0x99, 0xFF, 0x01, 0x23, 0x43, 0x40, 0xDB, 0xB2, +0xF6, 0xE7, 0x00, 0x00, 0x05, 0x4B, 0x1B, 0x68, 0x00, 0x28, 0x04, 0xD0, 0x08, 0x22, 0x13, 0x43, 0x02, 0x4A, 0x13, 0x60, +0x70, 0x47, 0x08, 0x22, 0x93, 0x43, 0xF9, 0xE7, 0x94, 0x40, 0x04, 0x40, 0x04, 0x4A, 0x13, 0x68, 0x40, 0x01, 0x04, 0x49, +0x0B, 0x40, 0x04, 0x49, 0x08, 0x40, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x94, 0x40, 0x04, 0x40, 0x1F, 0x00, 0xFE, 0xFF, +0xE0, 0xFF, 0x01, 0x00, 0x03, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x01, 0x22, 0x9A, 0x42, 0x40, 0x41, 0xC0, 0xB2, 0x70, 0x47, +0x50, 0xE0, 0x10, 0x00, 0x02, 0x4B, 0x18, 0x68, 0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0x50, 0xE0, 0x10, 0x00, +0x70, 0xB5, 0x01, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x0F, 0xD0, 0x70, 0xBD, 0x0E, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x02, 0x22, +0x02, 0x21, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, 0x80, 0x22, 0x2B, 0x68, 0x92, 0x01, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, +0xEF, 0xE7, 0x80, 0x21, 0x89, 0x01, 0x06, 0x4C, 0xEA, 0x25, 0x6D, 0x00, 0x0A, 0x00, 0x20, 0x00, 0x2B, 0x68, 0x98, 0x47, +0x2B, 0x68, 0x02, 0x22, 0x00, 0x21, 0x20, 0x00, 0x98, 0x47, 0xE0, 0xE7, 0x00, 0x10, 0x01, 0x50, 0x70, 0xB5, 0x05, 0x00, +0x0C, 0x00, 0x39, 0x4B, 0x1B, 0x68, 0x01, 0x20, 0x00, 0x2B, 0x45, 0xD1, 0x00, 0x29, 0x43, 0xD0, 0x00, 0x2D, 0x1A, 0xD0, +0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x4E, 0xD1, 0x72, 0xB6, 0x31, 0x4B, 0x1B, 0x68, +0x00, 0x2B, 0x41, 0xD1, 0x00, 0x20, 0x00, 0x2E, 0x4A, 0xD1, 0x62, 0xB6, 0x27, 0xE0, 0x20, 0x00, 0xFF, 0xF7, 0xBA, 0xFF, +0x2B, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0x00, 0x2E, 0x20, 0xD1, 0xF3, 0xE7, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, +0x16, 0x00, 0x1E, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x1B, 0xD1, 0x01, 0x20, +0x87, 0xF7, 0x51, 0xFC, 0x20, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x14, 0xD1, 0x01, 0x20, 0x87, 0xF7, 0x4A, 0xFC, 0x28, 0x00, +0x00, 0x2E, 0x00, 0xD1, 0x62, 0xB6, 0x1C, 0x4A, 0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x00, 0x28, 0x1E, 0xD0, 0x00, 0x23, +0x19, 0x4A, 0x13, 0x60, 0x19, 0x4A, 0x13, 0x60, 0x16, 0x4A, 0x13, 0x60, 0x70, 0xBD, 0x20, 0x00, 0xFF, 0xF7, 0x88, 0xFF, +0x12, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x01, 0x20, 0x87, 0xF7, 0x2F, 0xFC, 0x01, 0x20, 0xE3, 0xE7, 0x08, 0x00, 0xFF, 0xF7, +0x7D, 0xFF, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x28, 0x00, 0xB8, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xB6, 0xD1, +0x09, 0x4B, 0x1B, 0x68, 0x00, 0x20, 0x05, 0x2B, 0xDB, 0xD8, 0x08, 0x4B, 0x1C, 0x60, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0x07, 0x48, 0x82, 0xF7, 0x2F, 0xFC, 0x00, 0x20, 0xD8, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0x5C, 0x40, 0x04, 0x40, +0x54, 0xE6, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x2C, 0xCE, 0x10, 0x00, 0xF0, 0xB5, 0xCE, 0x46, +0x00, 0xB5, 0x86, 0xB0, 0x2A, 0x4B, 0x1C, 0x68, 0x21, 0x00, 0x2A, 0x48, 0x82, 0xF7, 0x16, 0xFC, 0x03, 0xAA, 0x29, 0x4B, +0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, 0x00, 0x2C, 0x0D, 0xDB, 0x0A, 0x22, 0x03, 0xA9, 0x25, 0x48, 0xD7, 0xF7, +0xFD, 0xF9, 0x0A, 0x22, 0x03, 0xA9, 0x24, 0x48, 0xD7, 0xF7, 0xF8, 0xF9, 0x06, 0xB0, 0x04, 0xBC, 0x91, 0x46, 0xF0, 0xBD, +0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, 0x11, 0xD0, 0x24, 0x04, 0x24, 0x0C, 0x1D, 0x4B, +0xE7, 0x18, 0x1D, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0xFB, 0x43, 0xDB, 0x17, 0x1F, 0x40, 0x4E, 0x2C, 0x00, 0xDD, 0x4E, 0x24, +0x03, 0xAD, 0x00, 0x26, 0x00, 0x23, 0x01, 0x93, 0x1B, 0xE0, 0x24, 0x04, 0x24, 0x0C, 0x16, 0x4B, 0xE7, 0x18, 0x16, 0x4B, +0x9C, 0x46, 0x64, 0x44, 0xEC, 0xE7, 0x8B, 0x40, 0x1A, 0x43, 0xD2, 0xB2, 0x01, 0x31, 0x08, 0x29, 0x07, 0xD0, 0x88, 0x19, +0x01, 0x23, 0xB8, 0x42, 0xF5, 0xDB, 0xA0, 0x42, 0xF3, 0xDC, 0x01, 0x9B, 0xF1, 0xE7, 0x4B, 0x46, 0x1A, 0x70, 0x01, 0x35, +0x08, 0x36, 0x50, 0x2E, 0xBC, 0xD0, 0xA9, 0x46, 0x00, 0x22, 0x00, 0x21, 0xED, 0xE7, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, +0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, +0xA7, 0xF6, 0xFF, 0xFF, 0x8A, 0xF6, 0xFF, 0xFF, 0xB1, 0xF6, 0xFF, 0xFF, 0x10, 0xB5, 0x84, 0xB0, 0x98, 0x4B, 0x1C, 0x68, +0x21, 0x00, 0x98, 0x48, 0x82, 0xF7, 0xAC, 0xFB, 0x01, 0xAA, 0x97, 0x4B, 0x03, 0xCB, 0x03, 0xC2, 0x1B, 0x88, 0x13, 0x80, +0x00, 0x2C, 0x0B, 0xDB, 0x0A, 0x22, 0x01, 0xA9, 0x93, 0x48, 0xD7, 0xF7, 0x93, 0xF9, 0x0A, 0x22, 0x01, 0xA9, 0x92, 0x48, +0xD7, 0xF7, 0x8E, 0xF9, 0x04, 0xB0, 0x10, 0xBD, 0xFF, 0x23, 0x1B, 0x04, 0x23, 0x40, 0x80, 0x22, 0x52, 0x02, 0x93, 0x42, +0x00, 0xD1, 0x02, 0xE1, 0x24, 0x04, 0x24, 0x0C, 0x8B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0xE4, 0xD8, 0xA4, 0x00, +0x89, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, +0xD8, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0x1A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x9A, 0x70, 0xFC, 0x32, 0xDA, 0x70, +0x14, 0x29, 0xCD, 0xD1, 0x00, 0x22, 0x1A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xC8, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, +0x01, 0xAB, 0x03, 0x22, 0x5A, 0x70, 0x00, 0x22, 0x9A, 0x70, 0xC0, 0x32, 0xDA, 0x70, 0x14, 0x29, 0xBC, 0xD1, 0x00, 0x22, +0x1A, 0x70, 0x5A, 0x70, 0xDA, 0x70, 0x1A, 0x71, 0xF0, 0x32, 0x5A, 0x71, 0xB4, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, +0x01, 0xAB, 0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0xF0, 0x32, 0x1A, 0x71, 0x14, 0x29, 0xA9, 0xD1, 0xED, 0x3A, 0x1A, 0x70, +0x00, 0x22, 0x5A, 0x70, 0x1A, 0x71, 0x5A, 0x71, 0xA2, 0xE7, 0x14, 0x21, 0xEE, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, +0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xFC, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x95, 0xD1, 0x00, 0x22, 0x5A, 0x70, +0x9A, 0x70, 0x5A, 0x71, 0xF0, 0x32, 0x9A, 0x71, 0x8E, 0xE7, 0x14, 0x21, 0xEC, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, +0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xC0, 0x32, 0x5A, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x81, 0xE7, 0x81, 0x3A, 0x5A, 0x70, +0x00, 0x22, 0x9A, 0x70, 0xDA, 0x70, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x78, 0xE7, 0x14, 0x21, 0xEA, 0xE7, 0x0A, 0x21, +0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0x5A, 0x71, 0xFC, 0x32, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, +0x6A, 0xE7, 0xF9, 0x3A, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x9A, 0x71, 0xC0, 0x32, 0xDA, 0x71, 0x62, 0xE7, 0x14, 0x21, +0xEA, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x0F, 0x22, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x14, 0x29, 0x00, 0xD0, +0x56, 0xE7, 0x3F, 0x32, 0x9A, 0x70, 0x00, 0x22, 0xDA, 0x70, 0x1A, 0x71, 0xDA, 0x71, 0x4F, 0xE7, 0x14, 0x21, 0xED, 0xE7, +0x0A, 0x21, 0x01, 0xAB, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0xF0, 0x32, 0xDA, 0x71, 0x14, 0x29, 0x00, 0xD0, 0x43, 0xE7, +0xE1, 0x3A, 0xDA, 0x70, 0x00, 0x22, 0x1A, 0x71, 0xDA, 0x71, 0x1A, 0x72, 0x3C, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, +0x01, 0xAB, 0x3F, 0x22, 0x5A, 0x71, 0x00, 0x22, 0x9A, 0x71, 0xDA, 0x71, 0xFC, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, +0x2E, 0xE7, 0xED, 0x3A, 0x1A, 0x71, 0x00, 0x22, 0x5A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x27, 0xE7, 0x14, 0x21, 0xEB, 0xE7, +0x0A, 0x21, 0x01, 0xAB, 0x03, 0x22, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xC0, 0x32, 0x1A, 0x72, 0x14, 0x29, 0x00, 0xD0, +0x1A, 0xE7, 0x00, 0x22, 0x5A, 0x71, 0x9A, 0x71, 0x1A, 0x72, 0x5A, 0x72, 0x14, 0xE7, 0x14, 0x21, 0xED, 0xE7, 0x0A, 0x21, +0x01, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x1A, 0x72, 0xF0, 0x32, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0x08, 0xE7, 0x00, 0x22, +0x9A, 0x71, 0x5A, 0x72, 0x04, 0xE7, 0x14, 0x21, 0xF0, 0xE7, 0x0A, 0x21, 0x01, 0xAB, 0x3F, 0x22, 0xDA, 0x71, 0x00, 0x22, +0x1A, 0x72, 0x5A, 0x72, 0x14, 0x29, 0x00, 0xD0, 0xF8, 0xE6, 0x0F, 0x32, 0x9A, 0x71, 0x00, 0x22, 0xDA, 0x71, 0xF3, 0xE6, +0x14, 0x21, 0xEF, 0xE7, 0x01, 0xAB, 0x00, 0x22, 0x1A, 0x70, 0x5A, 0x70, 0x9A, 0x70, 0xDA, 0x70, 0xFC, 0x32, 0x1A, 0x71, +0xE8, 0xE6, 0x24, 0x04, 0x24, 0x0C, 0x0A, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x3C, 0x2C, 0x00, 0xD9, 0xE0, 0xE6, 0xA4, 0x00, +0x08, 0x4B, 0x1B, 0x59, 0x9F, 0x46, 0xC0, 0x46, 0x98, 0x40, 0x04, 0x40, 0x34, 0xCE, 0x10, 0x00, 0x48, 0xCE, 0x10, 0x00, +0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x94, 0xF6, 0xFF, 0xFF, 0x54, 0xCE, 0x10, 0x00, 0x48, 0xCF, 0x10, 0x00, +0x10, 0xB5, 0x08, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x06, 0x4B, 0x1A, 0x6B, 0x06, 0x4B, 0x19, 0x68, +0x01, 0x20, 0x81, 0x43, 0x19, 0x60, 0x19, 0x68, 0x04, 0x48, 0x82, 0xF7, 0x5F, 0xFA, 0xF2, 0xE7, 0xB4, 0xE5, 0x10, 0x00, +0x00, 0x60, 0x50, 0x40, 0x04, 0x30, 0x34, 0x40, 0x3C, 0xD0, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x4C, 0x4B, +0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4B, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, +0x13, 0x60, 0xA9, 0xF7, 0x71, 0xFD, 0x48, 0x4B, 0x18, 0x60, 0x5C, 0x60, 0x0C, 0x2D, 0x38, 0xD8, 0xAD, 0x00, 0x46, 0x4B, +0x5B, 0x59, 0x9F, 0x46, 0x80, 0x23, 0xDB, 0x01, 0x00, 0x21, 0x9C, 0x42, 0x1B, 0xD3, 0x43, 0x4A, 0x13, 0x68, 0x43, 0x49, +0x19, 0x40, 0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x11, 0x68, 0xE3, 0x08, 0xC0, 0x20, 0x40, 0x01, 0x03, 0x40, +0x76, 0x20, 0x03, 0x43, 0x09, 0x0C, 0x09, 0x04, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x3B, 0x49, 0x19, 0x40, 0x80, 0x23, +0x1B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x80, 0x21, 0xC9, 0x01, 0x35, 0x4B, 0x1A, 0x68, 0x35, 0x48, 0x02, 0x40, 0x1A, 0x60, +0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x0C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x30, 0x49, +0x11, 0x40, 0x80, 0x22, 0x12, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x70, 0xBD, 0x2D, 0x4B, 0x1B, 0x68, 0x9A, 0x6A, 0x5B, 0x6B, +0xD2, 0x1A, 0xD5, 0x00, 0x55, 0x19, 0x6D, 0x00, 0x55, 0x19, 0xAD, 0xB2, 0x2A, 0x00, 0x21, 0x00, 0x28, 0x48, 0x82, 0xF7, +0xF7, 0xF9, 0x23, 0x4B, 0x19, 0x68, 0x23, 0x4E, 0x31, 0x40, 0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, +0x12, 0x0C, 0x12, 0x04, 0x6D, 0x05, 0x6D, 0x0D, 0x2A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x1D, 0x48, 0x02, 0x40, 0x80, 0x21, +0x09, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x16, 0x40, 0x1E, 0x60, 0x1A, 0x68, 0xA4, 0x04, 0xA4, 0x0C, 0x80, 0x25, +0x2D, 0x02, 0x2C, 0x43, 0x12, 0x0C, 0x12, 0x04, 0x14, 0x43, 0x1C, 0x60, 0x1A, 0x68, 0x10, 0x40, 0x01, 0x43, 0x19, 0x60, +0xC7, 0xE7, 0x0F, 0x4A, 0x13, 0x68, 0x0F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x13, 0x68, 0x1B, 0x0C, 0x1B, 0x04, 0x10, 0x49, +0x0C, 0x43, 0xA4, 0xB2, 0x1C, 0x43, 0x14, 0x60, 0x13, 0x68, 0x0A, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x03, 0x0B, 0x43, +0x13, 0x60, 0xB2, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0x6C, 0xE6, 0x10, 0x00, +0x5C, 0xD0, 0x10, 0x00, 0xF8, 0x00, 0x60, 0x40, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xF8, 0xE6, 0x10, 0x00, +0x50, 0xD0, 0x10, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, +0x07, 0x00, 0xD4, 0xF7, 0x4B, 0xFD, 0x04, 0x00, 0x00, 0x23, 0x01, 0x93, 0x00, 0x93, 0x3B, 0x4A, 0x13, 0x70, 0x01, 0x21, +0x01, 0x20, 0xFF, 0xF7, 0xEF, 0xFC, 0x80, 0x46, 0x38, 0x4B, 0x1E, 0x78, 0x02, 0x3E, 0x73, 0x1E, 0x9E, 0x41, 0x76, 0x42, +0x19, 0x23, 0x1E, 0x40, 0x02, 0x36, 0x00, 0x2C, 0x21, 0xD0, 0x65, 0x68, 0xFB, 0x7D, 0x9A, 0x46, 0xA3, 0x68, 0x99, 0x46, +0x69, 0x46, 0x01, 0xA8, 0xA9, 0xF7, 0xB0, 0xFC, 0x01, 0x9B, 0x53, 0x44, 0xEB, 0x1A, 0x1B, 0x01, 0x1A, 0x09, 0x5B, 0x00, +0x9C, 0x1A, 0xA4, 0x00, 0xA4, 0x18, 0xA3, 0x00, 0xE4, 0x18, 0x4B, 0x46, 0x00, 0x9A, 0x9B, 0x1A, 0xE4, 0x18, 0xA4, 0x09, +0xA6, 0x42, 0x00, 0xD8, 0xA4, 0x1B, 0x80, 0x23, 0x5B, 0x02, 0x9C, 0x42, 0x02, 0xD9, 0x24, 0x4C, 0x00, 0xE0, 0x23, 0x4C, +0xFF, 0xF7, 0xFC, 0xFB, 0x05, 0x00, 0x43, 0x46, 0x00, 0x2B, 0x12, 0xD0, 0x20, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, +0x1F, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x0F, 0xD0, 0x0A, 0x2C, 0x16, 0xD8, 0x4F, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x02, 0xB0, +0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xA3, 0xFC, 0xE7, 0xE7, +0x16, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x13, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x00, 0x25, 0xE6, 0xE7, 0xFF, 0xF7, +0x0B, 0xFC, 0x00, 0x28, 0xE4, 0xD0, 0xB2, 0xF7, 0xC9, 0xFD, 0x06, 0x23, 0x00, 0x28, 0x05, 0xD1, 0x4A, 0x33, 0xFB, 0x5C, +0x01, 0x3B, 0x58, 0x42, 0x43, 0x41, 0x05, 0x33, 0x00, 0x2D, 0xD7, 0xD1, 0xCF, 0x2C, 0x01, 0xD8, 0x06, 0x2B, 0xD3, 0xD1, +0x21, 0x00, 0x18, 0x00, 0xFF, 0xF7, 0xCC, 0xFE, 0xCE, 0xE7, 0xC0, 0x46, 0xB2, 0xE6, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, +0xFF, 0xFF, 0x00, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x4E, 0x23, +0x01, 0x22, 0xC2, 0x54, 0x2A, 0x4B, 0x1D, 0x68, 0x2A, 0x4B, 0x1C, 0x68, 0x2A, 0x4B, 0x19, 0x68, 0x2A, 0x4B, 0x1A, 0x68, +0x2A, 0x4B, 0x00, 0x26, 0x1E, 0x70, 0x00, 0x23, 0x00, 0x2D, 0x05, 0xD0, 0x42, 0x33, 0xEB, 0x5C, 0x01, 0x3B, 0x5D, 0x42, +0x6B, 0x41, 0xDB, 0xB2, 0x00, 0x2C, 0x03, 0xD0, 0x3A, 0x25, 0x64, 0x5D, 0x01, 0x2C, 0x23, 0xD0, 0x00, 0x24, 0x00, 0x29, +0x04, 0xD0, 0x3E, 0x34, 0x0D, 0x5D, 0x00, 0x24, 0x01, 0x2D, 0x1D, 0xD0, 0x00, 0x2A, 0x03, 0xD0, 0x2F, 0x21, 0x51, 0x5C, +0x01, 0x29, 0x1A, 0xD0, 0x00, 0x2B, 0x1D, 0xD0, 0x1A, 0x49, 0x0B, 0x68, 0x1A, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, +0x13, 0x43, 0x0B, 0x60, 0x18, 0x4B, 0x19, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x9B, 0x5C, 0x00, 0x2B, 0x18, 0xD0, +0x4F, 0x23, 0x01, 0x22, 0xC2, 0x54, 0x70, 0xBD, 0x01, 0x23, 0xD9, 0xE7, 0x8C, 0x62, 0x01, 0x34, 0xDE, 0xE7, 0x00, 0x21, +0x91, 0x62, 0x00, 0x2B, 0xE2, 0xD1, 0x01, 0xE0, 0x00, 0x2C, 0xE7, 0xD0, 0x0A, 0x49, 0x0B, 0x68, 0x0D, 0x4A, 0x1A, 0x40, +0x80, 0x23, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0xDE, 0xE7, 0xFF, 0xF7, 0x17, 0xFF, 0xE6, 0xE7, 0x24, 0x27, 0x16, 0x00, +0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0xB1, 0xE6, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, +0xFF, 0xFF, 0xDF, 0xFF, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xFF, 0xFF, 0x7F, 0xFF, 0x02, 0x4B, 0x1B, 0x68, +0x04, 0x20, 0x18, 0x40, 0x70, 0x47, 0xC0, 0x46, 0x80, 0x40, 0x34, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x12, 0x48, +0x82, 0xF7, 0x98, 0xF8, 0x00, 0x2C, 0x1E, 0xD0, 0x10, 0x4B, 0x1A, 0x68, 0x10, 0x48, 0x02, 0x40, 0xD0, 0x21, 0x89, 0x03, +0x0A, 0x43, 0x1A, 0x60, 0x1C, 0x68, 0x04, 0x40, 0xA0, 0x22, 0x52, 0x03, 0x22, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x40, +0x11, 0x43, 0x19, 0x60, 0x09, 0x49, 0x04, 0x22, 0x0B, 0x68, 0x1A, 0x42, 0xFC, 0xD0, 0x05, 0x49, 0x0B, 0x68, 0x05, 0x4A, +0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x10, 0xBD, 0x90, 0xD0, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, +0xFF, 0xFF, 0xC1, 0xFF, 0x80, 0x40, 0x34, 0x40, 0xF8, 0xB5, 0x04, 0x00, 0x83, 0x7D, 0x02, 0x33, 0x83, 0x75, 0x03, 0x6C, +0x03, 0x61, 0xB2, 0xF7, 0xF9, 0xFC, 0x00, 0x28, 0x24, 0xD1, 0x20, 0x4E, 0x4C, 0x25, 0x20, 0x4F, 0x20, 0x00, 0xD4, 0xF7, +0x19, 0xFA, 0x00, 0x28, 0x33, 0xD0, 0x31, 0x00, 0x20, 0x69, 0xD6, 0xF7, 0xFD, 0xF9, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, +0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, +0xE3, 0x60, 0xA3, 0x7D, 0x14, 0x4A, 0x52, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, +0xDE, 0xD1, 0xF8, 0xBD, 0x63, 0x68, 0x18, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, +0x21, 0x69, 0x20, 0x00, 0xFF, 0xF7, 0x3C, 0xFA, 0x63, 0x68, 0xAB, 0x42, 0xCB, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, +0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEF, 0xD1, 0xC3, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0xC0, 0x46, +0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0xAB, 0xFF, 0x10, 0xBD, +0xF8, 0xB5, 0x04, 0x00, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x6E, 0xFB, +0xA9, 0xF7, 0x38, 0xFB, 0x23, 0x6C, 0x23, 0x61, 0x60, 0x60, 0x04, 0x26, 0x4C, 0x27, 0x10, 0x4D, 0x20, 0x00, 0xD4, 0xF7, +0xBF, 0xF9, 0x00, 0x28, 0x15, 0xD0, 0x63, 0x68, 0x04, 0x33, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0xE3, 0x5B, 0x5B, 0x00, +0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, 0xA3, 0x7D, 0x6A, 0x78, 0x9B, 0x18, 0xA3, 0x75, +0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xE5, 0xD1, 0xD8, 0xE7, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xD4, 0xE7, 0xC0, 0x46, +0x7C, 0x91, 0x0D, 0x00, 0x70, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x1C, 0xD1, +0x72, 0xB6, 0x10, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x07, 0xD0, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x05, 0xD0, 0x01, 0x2B, +0x0D, 0xD0, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x00, 0x21, 0xD4, 0xF7, 0x2A, 0xFB, 0x07, 0x4D, 0x28, 0x68, +0x80, 0xF7, 0x38, 0xF8, 0x00, 0x23, 0x2B, 0x60, 0xF1, 0xE7, 0x4E, 0x23, 0x02, 0x22, 0xC2, 0x54, 0xED, 0xE7, 0x02, 0x4B, +0x18, 0x68, 0x00, 0x28, 0xE3, 0xD1, 0xEB, 0xE7, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, 0x36, 0x4B, 0x1B, 0x68, +0x0C, 0x20, 0x00, 0x2B, 0x00, 0xD0, 0xF8, 0xBD, 0x00, 0x21, 0x48, 0x30, 0x7F, 0xF7, 0x7A, 0xFF, 0x31, 0x4B, 0x18, 0x60, +0x00, 0x28, 0x56, 0xD0, 0xA9, 0xF7, 0xD2, 0xFA, 0x06, 0x00, 0x00, 0x27, 0x2E, 0x4B, 0x1F, 0x60, 0x2E, 0x4B, 0x1F, 0x60, +0x2B, 0x4B, 0x1C, 0x68, 0x54, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7D, 0xF7, 0x19, 0xFF, 0x2B, 0x68, 0xA3, 0x62, 0x6A, 0x68, +0x22, 0x63, 0xEA, 0x68, 0xE2, 0x63, 0x2A, 0x68, 0xE2, 0x62, 0xAA, 0x68, 0xA2, 0x63, 0x62, 0x63, 0x1B, 0x01, 0x4C, 0x22, +0xA3, 0x52, 0x24, 0x4A, 0x22, 0x64, 0x24, 0x4B, 0x63, 0x62, 0x24, 0x4B, 0xE3, 0x61, 0x24, 0x4B, 0x23, 0x62, 0x03, 0x23, +0x23, 0x76, 0x23, 0x4B, 0x9B, 0x78, 0x02, 0x33, 0xA3, 0x75, 0x22, 0x61, 0xE7, 0x75, 0x05, 0x23, 0x63, 0x76, 0xEF, 0xF3, +0x10, 0x83, 0x01, 0x22, 0x15, 0x00, 0x1D, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x66, 0x60, 0x00, 0x23, 0xA3, 0x60, +0x1A, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE0, 0x5A, 0x40, 0x00, 0x80, 0x19, 0x00, 0x01, 0x00, 0x09, 0xE0, 0x60, 0x20, 0x00, +0xD4, 0xF7, 0x1E, 0xF9, 0x00, 0x28, 0x06, 0xD1, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x00, 0x2D, 0xA9, 0xD1, 0x62, 0xB6, +0xA7, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0xF3, 0xE7, 0x0D, 0x4B, +0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0C, 0x20, 0x97, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, +0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0xE8, 0xFD, 0x00, 0x00, 0xB9, 0x21, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, +0x05, 0x4B, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x00, 0xA0, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x06, 0x4B, +0x18, 0x68, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0xC3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0xFF, 0xF7, 0x84, 0xFD, +0xFB, 0xE7, 0xC0, 0x46, 0xF8, 0xE6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x85, 0xF7, 0x55, 0xFE, 0x4C, 0x4B, +0x1B, 0x68, 0x01, 0x2B, 0x02, 0xD0, 0x4A, 0x4B, 0x02, 0x22, 0x1A, 0x60, 0x49, 0x4A, 0x48, 0x4B, 0x19, 0x68, 0x49, 0x4B, +0xD1, 0x54, 0x00, 0x21, 0x42, 0x3B, 0xD1, 0x54, 0x0B, 0x23, 0x47, 0x48, 0x13, 0x54, 0x01, 0x30, 0x13, 0x54, 0x46, 0x4B, +0x1B, 0x68, 0x1C, 0x0A, 0x50, 0x38, 0x14, 0x54, 0x44, 0x48, 0x13, 0x54, 0x44, 0x4B, 0x20, 0x20, 0xD0, 0x54, 0x44, 0x4B, +0x10, 0x38, 0xD0, 0x54, 0x43, 0x4B, 0x19, 0x60, 0x00, 0x24, 0x00, 0x23, 0x98, 0x46, 0x00, 0x27, 0x01, 0x34, 0xE4, 0xB2, +0x01, 0x2C, 0x0B, 0xD0, 0x02, 0x2C, 0x3E, 0xD0, 0x03, 0x2C, 0x4C, 0xD0, 0x3D, 0x4A, 0x13, 0x78, 0x20, 0x21, 0x8B, 0x43, +0x13, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0C, 0x20, 0xFE, 0xF7, 0xA7, 0xF9, 0x06, 0x00, 0x0D, 0x20, 0xFE, 0xF7, +0xA3, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x35, 0x48, 0x81, 0xF7, 0xDA, 0xFE, 0x2B, 0x00, 0x33, 0x43, +0xDE, 0xD0, 0x43, 0x46, 0x00, 0x2B, 0x41, 0xD0, 0x27, 0x4B, 0x2A, 0x0A, 0x1A, 0x70, 0x5D, 0x70, 0x32, 0x0E, 0x9A, 0x70, +0x32, 0x0C, 0xDA, 0x70, 0x32, 0x0A, 0x1A, 0x71, 0x5E, 0x71, 0x00, 0x2F, 0x0A, 0xD0, 0x21, 0x4A, 0x11, 0x1D, 0x13, 0x78, +0x01, 0x33, 0xDB, 0xB2, 0x13, 0x70, 0x00, 0x2B, 0x02, 0xD1, 0x01, 0x32, 0x8A, 0x42, 0xF6, 0xD1, 0x1B, 0x4C, 0x20, 0x68, +0x61, 0x68, 0xA9, 0xF7, 0xD1, 0xFC, 0x20, 0x00, 0xB9, 0xF7, 0x0E, 0xFB, 0xC2, 0xE7, 0x07, 0x20, 0xFE, 0xF7, 0x72, 0xF9, +0x06, 0x00, 0x08, 0x20, 0xFE, 0xF7, 0x6E, 0xF9, 0x05, 0x04, 0x2D, 0x0C, 0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x81, 0xF7, +0xA5, 0xFE, 0x01, 0x27, 0xC8, 0xE7, 0x1A, 0x4B, 0x1E, 0x88, 0x58, 0x88, 0x00, 0x04, 0x06, 0x43, 0x18, 0x4B, 0x1D, 0x88, +0x5B, 0x88, 0x2A, 0x00, 0x31, 0x00, 0x17, 0x48, 0x81, 0xF7, 0x96, 0xFE, 0x01, 0x23, 0x98, 0x46, 0x00, 0x27, 0xB7, 0xE7, +0x06, 0x4B, 0x2A, 0x0A, 0x5A, 0x71, 0x1D, 0x71, 0x32, 0x0E, 0xDA, 0x70, 0x32, 0x0C, 0x9A, 0x70, 0x32, 0x0A, 0x5A, 0x70, +0x1E, 0x70, 0xBC, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x9A, 0x02, 0x00, 0x00, 0xA3, 0x02, 0x00, 0x00, +0xB0, 0xE5, 0x10, 0x00, 0x55, 0x02, 0x00, 0x00, 0x56, 0x02, 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, +0xEC, 0xE1, 0x10, 0x00, 0xA0, 0xD0, 0x10, 0x00, 0xB0, 0xD0, 0x10, 0x00, 0x12, 0xC0, 0x1F, 0x08, 0x16, 0xC0, 0x1F, 0x08, +0xC4, 0xD0, 0x10, 0x00, 0x30, 0xB5, 0x89, 0xB0, 0x05, 0x00, 0x14, 0x00, 0x00, 0x28, 0x14, 0xD1, 0x1F, 0x4B, 0x20, 0x48, +0x1A, 0x5C, 0x04, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x02, 0x30, 0x1A, 0x5C, 0x3E, 0x35, 0xAA, 0x43, 0x1A, 0x54, 0x22, 0x00, +0x00, 0x20, 0x8D, 0xF7, 0xF9, 0xFF, 0x1A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0E, 0xD0, 0x09, 0xB0, 0x30, 0xBD, 0x8D, 0xF7, +0xF1, 0xFF, 0x02, 0x2D, 0xF5, 0xD1, 0x23, 0x78, 0x0C, 0x22, 0x93, 0x43, 0x23, 0x70, 0x63, 0x78, 0x0B, 0x3A, 0x93, 0x43, +0x63, 0x70, 0xEC, 0xE7, 0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xEC, 0xD8, 0x00, 0x23, 0x07, 0x93, 0x0F, 0x4B, 0x1B, 0x68, +0x03, 0x93, 0x0F, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0x04, 0x93, 0x0E, 0x4B, 0x18, 0x68, 0x0E, 0x49, 0xD5, 0xF7, 0xD4, 0xFF, +0x05, 0x90, 0x0D, 0x4B, 0x18, 0x68, 0x0B, 0x49, 0xD5, 0xF7, 0xCE, 0xFF, 0x06, 0x90, 0x03, 0xA8, 0xFF, 0xF7, 0x6C, 0xFE, +0xD3, 0xE7, 0xC0, 0x46, 0x7C, 0x1E, 0x16, 0x00, 0x9E, 0x02, 0x00, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, +0x0C, 0xE2, 0x10, 0x00, 0x10, 0xE2, 0x10, 0x00, 0x04, 0xE2, 0x10, 0x00, 0x71, 0x02, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, +0x80, 0x00, 0x08, 0x4B, 0xC3, 0x58, 0x88, 0x22, 0xFF, 0x32, 0x9A, 0x5C, 0x00, 0x20, 0x01, 0x2A, 0x00, 0xD0, 0x70, 0x47, +0x8A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x01, 0x38, 0x43, 0x42, 0x58, 0x41, 0xF7, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, +0x00, 0x23, 0x00, 0x20, 0x06, 0x49, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x06, 0xD0, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, +0xF8, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0xF5, 0xE7, 0x70, 0x47, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, +0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x30, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x80, 0xF7, 0xB2, 0xF8, 0x03, 0x00, 0x02, 0x00, +0x01, 0x28, 0x12, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, 0x19, 0x2B, 0x05, 0xD8, 0x15, 0x23, 0x93, 0x42, 0x40, 0x41, +0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0xDB, 0xB2, 0x01, 0x20, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, 0x40, 0x00, +0xF5, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x3A, 0xD1, 0x4B, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, +0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD1, 0x36, 0x33, 0xF2, 0x5C, 0x35, 0x3B, 0x13, 0x40, +0x3E, 0x22, 0x13, 0x43, 0x6A, 0x46, 0x13, 0x71, 0x00, 0x23, 0x53, 0x71, 0xE8, 0xB2, 0x01, 0xA9, 0xA7, 0xF7, 0x98, 0xF9, +0x14, 0x48, 0x81, 0xF7, 0xA9, 0xFD, 0x59, 0x21, 0x20, 0x00, 0x80, 0xF7, 0x17, 0xF8, 0x00, 0x20, 0xCF, 0xE7, 0x01, 0xA9, +0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1E, 0x3B, 0x8B, 0x70, 0xE8, 0xB2, +0xA7, 0xF7, 0x82, 0xF9, 0x0A, 0x48, 0x81, 0xF7, 0x93, 0xFD, 0x20, 0x00, 0x97, 0xF7, 0x72, 0xFD, 0x58, 0x21, 0x20, 0x00, +0x7F, 0xF7, 0xFE, 0xFF, 0x00, 0x20, 0xB6, 0xE7, 0x05, 0x48, 0x81, 0xF7, 0x87, 0xFD, 0x00, 0x20, 0xB1, 0xE7, 0xC0, 0x46, +0x64, 0xA2, 0x16, 0x00, 0xDC, 0xD0, 0x10, 0x00, 0xEC, 0xD0, 0x10, 0x00, 0xFC, 0xD0, 0x10, 0x00, 0xF0, 0xB5, 0x05, 0xAC, +0x24, 0x78, 0x4E, 0x28, 0x3C, 0xD8, 0xFF, 0x2C, 0x08, 0xD0, 0x10, 0x2C, 0x0B, 0xD9, 0x18, 0x2C, 0x37, 0xD9, 0x20, 0x2C, +0x38, 0xD9, 0x03, 0x26, 0x00, 0x25, 0x06, 0xE0, 0x32, 0x4C, 0x24, 0x18, 0xED, 0x34, 0x24, 0x78, 0xF1, 0xE7, 0x00, 0x26, +0x03, 0x25, 0x00, 0x29, 0x36, 0xD0, 0x2E, 0x4F, 0x39, 0x18, 0x0E, 0x00, 0x4F, 0x36, 0x33, 0x70, 0x3E, 0x56, 0xF3, 0x18, +0x5B, 0x10, 0x3B, 0x54, 0x0B, 0x00, 0xED, 0x33, 0x1C, 0x70, 0x0E, 0x00, 0x9E, 0x36, 0x33, 0x78, 0x1C, 0x19, 0x64, 0x10, +0x34, 0x70, 0x8C, 0x31, 0xFF, 0x31, 0x00, 0x23, 0x0B, 0x70, 0x24, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1B, 0x78, +0xED, 0x18, 0x6D, 0xB2, 0x06, 0x2D, 0x10, 0xDC, 0x1F, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x1D, 0x70, 0x02, 0x30, +0x80, 0x00, 0x1C, 0x4B, 0x18, 0x18, 0x42, 0x60, 0xF0, 0xBD, 0x01, 0x26, 0x02, 0x25, 0xD0, 0xE7, 0x02, 0x26, 0x01, 0x25, +0xCD, 0xE7, 0x17, 0x4B, 0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0x06, 0x21, 0x19, 0x70, 0xEC, 0xE7, 0x12, 0x4B, 0x1B, 0x18, +0x8C, 0x33, 0xFF, 0x33, 0x1B, 0x78, 0x01, 0x2B, 0x14, 0xD0, 0x0F, 0x49, 0x09, 0x18, 0x8C, 0x31, 0xFF, 0x31, 0x01, 0x23, +0x0B, 0x70, 0x0D, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x78, 0x9B, 0x1B, 0x5B, 0xB2, 0x99, 0x1D, 0x08, 0xDB, +0x08, 0x49, 0x09, 0x18, 0x49, 0x31, 0xFF, 0x31, 0x0B, 0x70, 0xD0, 0xE7, 0x02, 0x36, 0xF6, 0xB2, 0xE7, 0xE7, 0x04, 0x4B, +0x1B, 0x18, 0x49, 0x33, 0xFF, 0x33, 0xFA, 0x21, 0x19, 0x70, 0xC6, 0xE7, 0x1C, 0xE7, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, +0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0x4C, 0x00, 0x25, 0x00, 0x22, 0x01, 0x26, +0xC1, 0x27, 0xFF, 0x00, 0x03, 0xE0, 0x01, 0x35, 0x09, 0x34, 0x07, 0x2D, 0x0E, 0xD0, 0x23, 0x78, 0x03, 0x2B, 0xF8, 0xD1, +0x63, 0x78, 0x00, 0x2B, 0xF5, 0xD1, 0x29, 0x02, 0x31, 0x43, 0x89, 0xB2, 0x00, 0x22, 0x38, 0x00, 0x7F, 0xF7, 0x20, 0xFC, +0x01, 0x22, 0xEC, 0xE7, 0x00, 0x2A, 0x0B, 0xD1, 0x7E, 0x4A, 0xD9, 0x23, 0x5B, 0x00, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x20, +0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xA8, 0xF7, 0xFE, 0xFF, 0x82, 0x46, 0x8E, 0xF7, +0x09, 0xF8, 0x80, 0x46, 0xA9, 0xF7, 0x18, 0xFB, 0x81, 0x46, 0x00, 0x24, 0x73, 0x4B, 0x9B, 0x46, 0x63, 0xE0, 0x8D, 0xF7, +0xF3, 0xFF, 0x00, 0x28, 0x19, 0xD0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, +0xC8, 0x22, 0x92, 0x01, 0x93, 0x42, 0x3D, 0xD2, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x1B, 0x57, 0x01, 0x33, 0x2D, 0xDB, +0xD4, 0x20, 0x40, 0x00, 0x66, 0x4B, 0x5B, 0x19, 0x01, 0x21, 0xB1, 0x40, 0x1A, 0x5C, 0x0A, 0x43, 0x1A, 0x54, 0x2A, 0x00, +0x63, 0x32, 0xFF, 0x32, 0x5A, 0x44, 0x00, 0x21, 0x06, 0x20, 0x38, 0x40, 0x03, 0x27, 0x13, 0x78, 0x03, 0x41, 0x3B, 0x40, +0x03, 0x2B, 0x27, 0xD0, 0x01, 0x31, 0x0A, 0x32, 0x07, 0x29, 0xF6, 0xD1, 0xB3, 0x1E, 0x01, 0x2B, 0x00, 0xD8, 0x98, 0xE0, +0x73, 0x1F, 0x01, 0x2B, 0x00, 0xD8, 0x94, 0xE0, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, +0x1B, 0x09, 0xFA, 0x22, 0x12, 0x02, 0x93, 0x42, 0x1E, 0xD9, 0x93, 0xE0, 0xD4, 0x21, 0x49, 0x00, 0x4F, 0x4B, 0x5D, 0x19, +0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0x13, 0xE0, 0x4B, 0x46, 0x3D, 0x33, 0xFF, 0x33, 0x00, 0x22, +0x1A, 0x55, 0xCA, 0xE7, 0xD4, 0x20, 0x40, 0x00, 0x47, 0x4B, 0x9C, 0x46, 0xAC, 0x44, 0x01, 0x22, 0xB2, 0x40, 0x63, 0x46, +0x1B, 0x5C, 0x93, 0x43, 0x62, 0x46, 0x13, 0x54, 0x07, 0x29, 0xCD, 0xD0, 0x01, 0x34, 0x4F, 0x2C, 0x13, 0xD0, 0xE7, 0xB2, +0x07, 0x26, 0x26, 0x40, 0x65, 0x05, 0x2D, 0x0E, 0x43, 0x46, 0x5B, 0x5D, 0x33, 0x41, 0xDB, 0x07, 0x91, 0xD4, 0xD4, 0x21, +0x49, 0x00, 0x3A, 0x4B, 0x5D, 0x19, 0x01, 0x22, 0xB2, 0x40, 0x6B, 0x5C, 0x93, 0x43, 0x6B, 0x54, 0xE8, 0xE7, 0x37, 0x48, +0x81, 0xF7, 0xB0, 0xFC, 0x13, 0x28, 0x41, 0xD8, 0x14, 0x23, 0x1B, 0x1A, 0xDB, 0xB2, 0x9B, 0x46, 0x14, 0x25, 0x2D, 0x1A, +0x00, 0x23, 0x99, 0x46, 0x00, 0x24, 0x2F, 0x4E, 0x0E, 0xE0, 0x48, 0x46, 0x13, 0x28, 0x09, 0xD9, 0x2C, 0x48, 0x84, 0x46, +0x62, 0x44, 0x01, 0x20, 0x98, 0x40, 0x01, 0x43, 0xD4, 0x23, 0x5B, 0x00, 0xD1, 0x54, 0x01, 0x34, 0xAC, 0x42, 0x27, 0xDA, +0xD6, 0xF7, 0xDA, 0xFA, 0x7F, 0x23, 0x18, 0x40, 0x4E, 0x28, 0x00, 0xD9, 0x4F, 0x38, 0xC2, 0x08, 0xB1, 0x18, 0xD4, 0x23, +0x5B, 0x00, 0xC9, 0x5C, 0xA2, 0x3B, 0xFF, 0x3B, 0x03, 0x40, 0x0F, 0x00, 0x1F, 0x41, 0xFF, 0x07, 0xEA, 0xD4, 0x47, 0x46, +0xBF, 0x5C, 0x1F, 0x41, 0xFF, 0x07, 0xE5, 0xD5, 0x4F, 0x46, 0x01, 0x37, 0xFF, 0xB2, 0xB9, 0x46, 0x1A, 0x4F, 0xBC, 0x46, +0x60, 0x44, 0x9E, 0x30, 0x00, 0x78, 0x18, 0x28, 0xD0, 0xD9, 0xCB, 0x45, 0xCB, 0xD8, 0x20, 0x28, 0xCC, 0xD9, 0xC8, 0xE7, +0x13, 0x48, 0x81, 0xF7, 0x69, 0xFC, 0x01, 0x00, 0x13, 0x48, 0x81, 0xF7, 0x01, 0xFC, 0xC8, 0x22, 0x00, 0x21, 0x12, 0x48, +0x7F, 0xF7, 0x38, 0xFA, 0x1F, 0xE7, 0xA3, 0x00, 0x4A, 0x46, 0xD3, 0x58, 0x52, 0x46, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, +0xFA, 0x22, 0xD2, 0x01, 0x93, 0x42, 0x89, 0xD9, 0xD4, 0x21, 0x49, 0x00, 0x05, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x01, 0x22, +0xB2, 0x40, 0x6B, 0x5C, 0x13, 0x43, 0x6B, 0x54, 0x7E, 0xE7, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, 0x68, 0x9E, 0x16, 0x00, +0x10, 0xA0, 0x16, 0x00, 0x1C, 0xE7, 0x10, 0x00, 0x0C, 0xD1, 0x10, 0x00, 0x0A, 0x05, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, +0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x07, 0x00, 0x08, 0x00, 0x00, 0x91, 0xBA, 0x00, 0xA4, 0x4B, +0xD5, 0x58, 0xA6, 0x23, 0xEB, 0x5C, 0x9B, 0x46, 0x2B, 0x6D, 0x98, 0x46, 0x62, 0x23, 0x7B, 0x43, 0xA0, 0x4A, 0x9A, 0x18, +0x16, 0x88, 0xA0, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x36, 0x04, 0x26, 0x43, 0x9E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0x05, +0x92, 0x0D, 0x91, 0x46, 0x9C, 0x4A, 0x9A, 0x18, 0x14, 0x88, 0x9C, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x24, 0x04, +0x1C, 0x19, 0x9A, 0x4B, 0x98, 0x45, 0x1A, 0xD8, 0x73, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, +0x4A, 0xD9, 0x83, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x49, 0xD0, 0x00, 0x2B, +0x09, 0xDB, 0x89, 0x08, 0x00, 0x29, 0x06, 0xDD, 0x89, 0x00, 0x00, 0x9B, 0x9C, 0x46, 0x61, 0x44, 0x09, 0x01, 0x0B, 0x09, +0x00, 0x93, 0xA4, 0x1B, 0x00, 0x9B, 0x9C, 0x46, 0x64, 0x44, 0x24, 0x01, 0x24, 0x09, 0xF4, 0x26, 0x76, 0x00, 0x4B, 0x46, +0xF6, 0x1A, 0x3B, 0xD4, 0xAC, 0x67, 0x82, 0x23, 0xEE, 0x52, 0x62, 0x42, 0x7F, 0x3B, 0x13, 0x40, 0xA6, 0x22, 0xAB, 0x54, +0x72, 0x3A, 0x2A, 0x65, 0x01, 0x96, 0xAE, 0x60, 0x42, 0x46, 0x34, 0x2A, 0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, +0xC8, 0x22, 0x52, 0x00, 0xB2, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, 0xEA, 0x75, 0x5B, 0x45, 0x00, 0xD1, 0x9F, 0xE0, +0xA1, 0x23, 0xEB, 0x5C, 0x03, 0x2B, 0x21, 0xD0, 0x3B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x02, 0x93, 0x01, 0x23, 0x98, 0x46, +0xFE, 0x33, 0x9A, 0x46, 0xA9, 0x46, 0x45, 0x46, 0xA0, 0x46, 0x4D, 0xE0, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, +0x00, 0x2A, 0xB8, 0xD0, 0xB5, 0xE7, 0x00, 0x2B, 0xB5, 0xDA, 0x6C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, +0x98, 0x47, 0xB8, 0xE7, 0x69, 0x4E, 0xF6, 0x1A, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0xBD, 0xE7, 0xC1, 0x33, 0x99, 0x46, +0xEB, 0x58, 0x6A, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4A, 0x46, 0xAB, 0x50, 0x3B, 0x02, +0x01, 0x21, 0x19, 0x43, 0x02, 0x23, 0x3B, 0x32, 0x5F, 0x48, 0x7F, 0xF7, 0x2B, 0xFA, 0x80, 0x46, 0x4B, 0x46, 0xEB, 0x58, +0x5B, 0x08, 0x99, 0x46, 0xCC, 0x23, 0xEB, 0x5A, 0x9A, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x57, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x51, 0x46, 0x48, 0x46, 0xD5, 0xF7, 0x47, 0xFD, 0x43, 0x46, 0x19, 0x80, 0x40, 0x46, +0x7F, 0xF7, 0x3C, 0xFA, 0xB0, 0xE7, 0x21, 0x00, 0x03, 0x98, 0xD5, 0xF7, 0x3D, 0xFD, 0x04, 0x9B, 0x59, 0x80, 0x18, 0x00, +0x7F, 0xF7, 0x32, 0xFA, 0x01, 0x3D, 0x3F, 0xD3, 0x53, 0x46, 0x2B, 0x40, 0x9B, 0x00, 0x4B, 0x4A, 0x9C, 0x58, 0x00, 0x2C, +0xF6, 0xD0, 0x46, 0x23, 0xE3, 0x5C, 0xBB, 0x42, 0xF2, 0xD1, 0x63, 0x6B, 0x42, 0x46, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, +0x63, 0x63, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x63, 0x63, 0x68, 0x42, 0x46, +0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x4A, 0x46, 0x52, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, +0x63, 0x60, 0x01, 0x9B, 0xA3, 0x60, 0x04, 0x23, 0x52, 0x46, 0x02, 0x99, 0x38, 0x48, 0x7F, 0xF7, 0xD9, 0xF9, 0x04, 0x90, +0x47, 0x23, 0xE3, 0x5C, 0x03, 0x70, 0x63, 0x6B, 0x5B, 0x08, 0x03, 0x93, 0x42, 0x23, 0xE4, 0x5C, 0x00, 0x2C, 0xBC, 0xD1, +0x2D, 0x4B, 0x9B, 0x6E, 0x05, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xB4, 0xE7, 0x44, 0x46, 0x4D, 0x46, +0x6C, 0x67, 0x84, 0x23, 0xEE, 0x52, 0x1D, 0x33, 0xEB, 0x5C, 0x04, 0x2B, 0x0D, 0xD0, 0xA6, 0x23, 0xE8, 0x5C, 0x5B, 0x46, +0xC0, 0x1A, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, +0xF0, 0xBD, 0x7C, 0x33, 0xEB, 0x5A, 0x9E, 0x1B, 0xF3, 0x17, 0xF6, 0x18, 0x5E, 0x40, 0x33, 0xB2, 0x9D, 0x22, 0x52, 0x00, +0x93, 0x42, 0x02, 0xDB, 0x1D, 0x4B, 0x9B, 0x1B, 0x1B, 0xB2, 0x03, 0x2B, 0xE1, 0xDD, 0xE8, 0x23, 0xEB, 0x58, 0x1A, 0x68, +0x00, 0x9B, 0xA8, 0x6F, 0x84, 0x46, 0x63, 0x44, 0x19, 0x00, 0xD3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, 0x00, 0x05, +0x83, 0x42, 0xD2, 0xD8, 0x09, 0x01, 0x09, 0x09, 0x51, 0x1A, 0x09, 0x01, 0x09, 0x09, 0x64, 0x29, 0xCB, 0xDD, 0x3F, 0x02, +0x01, 0x21, 0x39, 0x43, 0xFF, 0x22, 0x0F, 0x48, 0x7F, 0xF7, 0xC2, 0xF9, 0xC3, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, +0x4C, 0x65, 0x61, 0x40, 0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, +0xE1, 0x04, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0x33, 0x06, 0x00, 0x00, 0x54, 0x27, 0x16, 0x00, +0x34, 0x06, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x2E, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, +0x45, 0x46, 0xE0, 0xB5, 0x89, 0xB0, 0x03, 0x90, 0x89, 0x46, 0x81, 0x00, 0xC9, 0x4B, 0xCF, 0x58, 0x53, 0x1E, 0xDB, 0xB2, +0x9B, 0x46, 0x00, 0x2A, 0x00, 0xD1, 0x26, 0xE1, 0x03, 0x02, 0x01, 0x22, 0x13, 0x43, 0x07, 0x93, 0xC4, 0x4B, 0x98, 0x46, +0x9A, 0x46, 0x5C, 0x46, 0x83, 0xE0, 0x6B, 0x46, 0x10, 0x21, 0x5B, 0x5E, 0x00, 0x2B, 0x06, 0xDB, 0xA7, 0x21, 0x79, 0x5C, +0x77, 0x29, 0x02, 0xD8, 0x01, 0x31, 0xA7, 0x20, 0x39, 0x54, 0xE9, 0x06, 0x00, 0xD5, 0xD7, 0xE0, 0xA4, 0x21, 0x29, 0x42, +0x5B, 0xD1, 0x29, 0x07, 0x54, 0xD4, 0x00, 0x2B, 0x00, 0xDA, 0xCF, 0xE0, 0xA7, 0x23, 0xFB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, +0xA7, 0x23, 0x02, 0x21, 0xF9, 0x54, 0x0F, 0x23, 0x1A, 0x40, 0x03, 0x25, 0x05, 0x9B, 0x1D, 0x40, 0x03, 0x2A, 0x01, 0xD0, +0x08, 0x2A, 0x02, 0xD1, 0x03, 0x2D, 0x00, 0xD1, 0xCE, 0xE0, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0xB7, 0xE0, +0x6B, 0x1E, 0x01, 0x2B, 0x00, 0xD9, 0xB3, 0xE0, 0x05, 0x9B, 0xDE, 0x04, 0xB6, 0x0D, 0x00, 0xD1, 0xAE, 0xE0, 0x04, 0x23, +0xFF, 0x22, 0x07, 0x99, 0xA5, 0x48, 0x7F, 0xF7, 0x0B, 0xF9, 0xA5, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, +0x9B, 0x1A, 0x5B, 0x00, 0xA2, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x03, 0x80, 0x43, 0x88, 0x9B, 0x0A, 0x9B, 0x02, +0x33, 0x43, 0x9F, 0x4E, 0x33, 0x40, 0x2D, 0x03, 0x1D, 0x43, 0xAA, 0x04, 0x92, 0x0C, 0x06, 0x9B, 0x59, 0x42, 0x4B, 0x41, +0x9B, 0x03, 0x13, 0x43, 0x43, 0x80, 0x7F, 0xF7, 0x17, 0xF9, 0x96, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, +0x9B, 0x1A, 0x5B, 0x00, 0x93, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, 0x1A, 0x80, 0x7D, 0xE0, 0xFF, 0x22, 0x07, 0x99, +0x91, 0x48, 0x7F, 0xF7, 0x1B, 0xF9, 0xA8, 0xF7, 0x3F, 0xFA, 0x90, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x43, 0x46, 0xDB, 0x69, +0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x00, 0x21, 0x02, 0x98, 0xFF, 0xF7, 0x52, 0xFC, +0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x00, 0xD1, 0x99, 0xE0, 0x03, 0x98, 0xA8, 0xF7, 0x54, 0xFA, 0x00, 0x28, 0x00, 0xD1, +0x93, 0xE0, 0xD5, 0x23, 0x5B, 0x00, 0x7E, 0x4A, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x80, 0x4A, 0x9A, 0x18, +0x15, 0x88, 0xAD, 0xB2, 0x7F, 0x4A, 0x9A, 0x18, 0x16, 0x88, 0xB6, 0xB2, 0x7E, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x92, 0xB2, +0x05, 0x92, 0x7D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9A, 0xB2, 0x04, 0x92, 0xDA, 0xB2, 0x93, 0x46, 0x5B, 0x04, +0x5B, 0x0E, 0x02, 0x93, 0x4B, 0x46, 0xFA, 0x6E, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xC8, 0x2B, 0x0A, 0xD9, 0xA7, 0x23, +0xFB, 0x5C, 0x77, 0x2B, 0x06, 0xD8, 0xA1, 0x22, 0xBA, 0x5C, 0x00, 0x2A, 0x02, 0xD1, 0x01, 0x33, 0xA7, 0x32, 0xBB, 0x54, +0xEB, 0x07, 0xB0, 0xD4, 0x07, 0x23, 0x1A, 0x00, 0x32, 0x40, 0x06, 0x92, 0x4A, 0x46, 0xFA, 0x66, 0x33, 0x42, 0x0B, 0xD0, +0x5F, 0x4B, 0xDB, 0x69, 0x58, 0x46, 0x98, 0x47, 0x98, 0x22, 0xBB, 0x5A, 0x1B, 0x18, 0xBB, 0x52, 0x02, 0x32, 0xBB, 0x5C, +0x01, 0x33, 0xBB, 0x54, 0xAB, 0x07, 0x9A, 0xD4, 0x4B, 0x46, 0x3B, 0x67, 0x6B, 0x06, 0x02, 0xD5, 0x06, 0x9B, 0x00, 0x2B, +0x0C, 0xD1, 0xF6, 0x10, 0xF2, 0xB2, 0x0E, 0x23, 0x1E, 0x42, 0x00, 0xD0, 0x1F, 0xE7, 0x99, 0x33, 0xFB, 0x5C, 0x00, 0x2B, +0x02, 0xD0, 0x01, 0x3B, 0xA7, 0x22, 0xBB, 0x54, 0xA8, 0xF7, 0xC6, 0xF9, 0x53, 0x4B, 0x1D, 0x68, 0x58, 0x46, 0x53, 0x46, +0xDB, 0x69, 0x98, 0x47, 0x03, 0x00, 0x2D, 0x0A, 0xED, 0xB2, 0x00, 0x95, 0x4A, 0x46, 0x01, 0x21, 0x02, 0x98, 0xFF, 0xF7, +0xD9, 0xFB, 0x85, 0xE7, 0x47, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4D, 0x4A, +0x94, 0x46, 0x63, 0x44, 0x19, 0x88, 0x8B, 0xB2, 0x04, 0x93, 0x05, 0x9A, 0xD5, 0x04, 0xAD, 0x0D, 0x6B, 0x1C, 0xFF, 0x22, +0x07, 0x99, 0x48, 0x48, 0x7F, 0xF7, 0x3A, 0xF8, 0x06, 0x00, 0x05, 0x70, 0x04, 0x9B, 0x46, 0x4A, 0x94, 0x46, 0x63, 0x44, +0x19, 0x00, 0x01, 0x30, 0x2A, 0x00, 0xD5, 0xF7, 0x27, 0xFF, 0x30, 0x00, 0x7F, 0xF7, 0x56, 0xF8, 0xC8, 0xE7, 0x62, 0x24, +0x03, 0x9B, 0x5C, 0x43, 0x3F, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x23, 0x80, 0x89, 0xF7, +0x59, 0xF9, 0x00, 0x28, 0x18, 0xD0, 0x2F, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x13, 0xD1, 0x38, 0x4B, 0x1B, 0x88, +0x9B, 0xB2, 0x00, 0x2B, 0x0E, 0xD1, 0x37, 0x4B, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x09, 0xD1, 0x35, 0x4B, 0x1B, 0x88, +0x9B, 0xB2, 0x00, 0x2B, 0x04, 0xD1, 0x23, 0x88, 0x80, 0x22, 0x93, 0x43, 0x13, 0x43, 0x23, 0x80, 0x9A, 0x23, 0xFB, 0x5C, +0x96, 0x2B, 0x03, 0xD9, 0xEC, 0x23, 0xFB, 0x58, 0x00, 0x2B, 0x06, 0xD0, 0x09, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAC, 0x33, 0xFB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x9B, 0x23, 0x00, 0x22, 0xFA, 0x54, +0x26, 0x4A, 0x27, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0x03, 0xD5, 0x26, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD1, 0x00, 0x23, +0x9A, 0x22, 0xBB, 0x54, 0x02, 0x3A, 0xBB, 0x52, 0xE2, 0xE7, 0x03, 0x9B, 0x19, 0x02, 0x01, 0x23, 0x19, 0x43, 0xFF, 0x22, +0x1F, 0x48, 0x7F, 0xF7, 0x17, 0xF8, 0x98, 0x23, 0xF8, 0x5E, 0x9A, 0x23, 0xF9, 0x5C, 0xD5, 0xF7, 0x05, 0xFB, 0x06, 0x4A, +0x2F, 0x23, 0xD3, 0x5C, 0xC0, 0x1A, 0x9B, 0x23, 0xF8, 0x54, 0x17, 0x4A, 0x13, 0x78, 0x01, 0x3B, 0x13, 0x70, 0xE0, 0xE7, +0x38, 0x27, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, 0x29, 0x06, 0x00, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, +0xFF, 0xCF, 0xFF, 0xFF, 0x2A, 0x06, 0x00, 0x00, 0x0C, 0x01, 0x60, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, +0x96, 0x69, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x27, 0x06, 0x00, 0x00, 0x00, 0x00, 0x61, 0x40, +0x0E, 0x65, 0x61, 0x40, 0xA8, 0x69, 0x61, 0x40, 0xB6, 0x69, 0x61, 0x40, 0xC4, 0x69, 0x61, 0x40, 0x7C, 0x1E, 0x16, 0x00, +0x9D, 0x02, 0x00, 0x00, 0x24, 0xE6, 0x10, 0x00, 0x2F, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x04, 0x00, +0x88, 0x46, 0x16, 0x00, 0xFF, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0x3F, 0xD1, 0x22, 0x4D, 0x23, 0x4F, 0xEB, 0x5D, 0x04, 0x22, +0x93, 0x43, 0xEB, 0x55, 0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0x1F, 0xFE, 0xEB, 0x5D, 0x04, 0x22, 0x13, 0x43, +0xEB, 0x55, 0xA4, 0x00, 0x1C, 0x4B, 0xE4, 0x58, 0xA7, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x02, 0xD9, 0xA7, 0x23, 0x04, 0x22, +0xE2, 0x54, 0xFE, 0xF7, 0x49, 0xFB, 0x00, 0x28, 0x02, 0xD1, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xB1, 0xF7, 0x04, 0xFD, +0x00, 0x28, 0xF8, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0xA7, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD1, +0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xA8, 0x23, 0xE3, 0x5C, 0x00, 0x2B, +0x03, 0xD1, 0x62, 0x68, 0x09, 0x4B, 0x1A, 0x60, 0xE1, 0xE7, 0xA8, 0xF7, 0x81, 0xFB, 0x08, 0x4B, 0x18, 0x60, 0xF6, 0xE7, +0x32, 0x00, 0x41, 0x46, 0x20, 0x00, 0xFF, 0xF7, 0xE5, 0xFD, 0xC8, 0xE7, 0x7C, 0x1E, 0x16, 0x00, 0x9D, 0x02, 0x00, 0x00, +0x38, 0x27, 0x16, 0x00, 0x28, 0xE6, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0x04, 0x4B, +0x04, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x04, 0x30, 0x34, 0x40, 0xC1, 0x00, 0xA0, 0x00, 0x0C, 0x00, 0x58, 0x40, +0x14, 0x00, 0x7F, 0x30, 0x01, 0x4B, 0x02, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, +0x10, 0xB5, 0x30, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, 0x01, 0x28, 0x08, 0xD0, 0x02, 0x28, 0x47, 0xD0, 0x2D, 0x4B, +0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xBD, 0xA8, 0xF7, 0x44, 0xFB, 0x27, 0x4B, 0x5B, 0x78, +0x00, 0x2B, 0x11, 0xD1, 0x25, 0x4B, 0x01, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x9B, 0x78, 0x01, 0x2B, 0xF1, 0xD0, 0xFE, 0xF7, +0xA7, 0xFA, 0x00, 0x28, 0xED, 0xD1, 0xFE, 0xF7, 0xC1, 0xFA, 0x00, 0x28, 0xE9, 0xD1, 0xFF, 0xF7, 0xC1, 0xFF, 0xE6, 0xE7, +0x1C, 0x4A, 0x53, 0x68, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x92, 0x78, 0x00, 0x2A, 0x0B, 0xD1, 0x23, 0x2B, 0xDC, 0xD9, +0x17, 0x4B, 0x01, 0x32, 0x9A, 0x70, 0x00, 0x22, 0x5A, 0x70, 0x58, 0x60, 0x16, 0x4B, 0x17, 0x4A, 0x1A, 0x60, 0xD2, 0xE7, +0x01, 0x2A, 0xD0, 0xD1, 0x3B, 0x2B, 0xCE, 0xD9, 0x10, 0x4B, 0x00, 0x22, 0x9A, 0x70, 0x01, 0x32, 0x5A, 0x70, 0x58, 0x60, +0xFE, 0xF7, 0x7E, 0xFA, 0x00, 0x28, 0xC4, 0xD1, 0xFE, 0xF7, 0x98, 0xFA, 0x00, 0x28, 0xC0, 0xD1, 0xFF, 0xF7, 0x98, 0xFF, +0xBD, 0xE7, 0x08, 0x4B, 0x5B, 0x78, 0x01, 0x2B, 0x01, 0xD0, 0x00, 0x29, 0xB7, 0xD0, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x70, +0x9A, 0x70, 0x01, 0x3A, 0x5A, 0x60, 0x04, 0x4B, 0x04, 0x4A, 0x1A, 0x60, 0xAD, 0xE7, 0xC0, 0x46, 0xDC, 0xE6, 0x10, 0x00, +0x28, 0x19, 0x16, 0x00, 0x04, 0x30, 0x34, 0x40, 0xC0, 0x00, 0xA0, 0x00, 0xF0, 0xB5, 0x80, 0x00, 0x26, 0x4B, 0xC3, 0x58, +0xAB, 0x20, 0x18, 0x5C, 0x00, 0x28, 0x27, 0xD0, 0x0D, 0x1C, 0xAA, 0x20, 0x80, 0x00, 0x81, 0x42, 0x01, 0xD3, 0x22, 0x49, +0x0D, 0x1C, 0xAD, 0xB2, 0x9D, 0x21, 0x5F, 0x5C, 0x00, 0x23, 0x00, 0x24, 0x01, 0x26, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, +0x0C, 0xD0, 0xD8, 0xB2, 0x39, 0x00, 0x19, 0x41, 0x0E, 0x42, 0xF7, 0xD0, 0x59, 0x00, 0x1A, 0x4C, 0x61, 0x5A, 0xA9, 0x42, +0x01, 0xD2, 0x04, 0x00, 0xF0, 0xE7, 0x04, 0x00, 0x17, 0x4B, 0x18, 0x5D, 0x64, 0x00, 0x15, 0x4B, 0xE3, 0x5A, 0xAB, 0x42, +0x00, 0xD9, 0x2B, 0x00, 0x13, 0x80, 0xF0, 0xBD, 0x9C, 0x20, 0x1F, 0x5C, 0x00, 0x23, 0x00, 0x25, 0x01, 0x26, 0x02, 0xE0, +0x01, 0x33, 0x06, 0x2B, 0x0C, 0xD0, 0xDC, 0xB2, 0x38, 0x00, 0x18, 0x41, 0x06, 0x42, 0xF7, 0xD0, 0x58, 0x00, 0x0C, 0x4D, +0x28, 0x5A, 0x88, 0x42, 0x01, 0xD2, 0x25, 0x00, 0xF0, 0xE7, 0x25, 0x00, 0x09, 0x4B, 0x58, 0x5D, 0x6D, 0x00, 0x07, 0x4B, +0xEB, 0x5A, 0x8B, 0x42, 0x00, 0xD9, 0x0B, 0x00, 0x13, 0x80, 0xDE, 0xE7, 0x38, 0x27, 0x16, 0x00, 0xA7, 0x02, 0x00, 0x00, +0x40, 0xC9, 0x0D, 0x00, 0x50, 0xC9, 0x0D, 0x00, 0x2C, 0xC9, 0x0D, 0x00, 0x38, 0xC9, 0x0D, 0x00, 0xF0, 0xB5, 0xDE, 0x46, +0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x00, 0x90, 0x88, 0x46, 0x82, 0x00, 0x95, 0x4B, 0xD4, 0x58, +0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0x0D, 0xE1, 0x03, 0x02, 0x01, 0x27, 0x1F, 0x43, 0x88, 0x23, 0x99, 0x46, +0xBB, 0x46, 0x2A, 0xE0, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x8E, 0x4B, 0xEA, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, +0x60, 0x39, 0x0B, 0x43, 0x13, 0x80, 0x8B, 0x4B, 0xEA, 0x18, 0x83, 0x79, 0xDB, 0x00, 0x11, 0x39, 0x0B, 0x43, 0x13, 0x80, +0x82, 0x88, 0x88, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x87, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, +0x2B, 0x80, 0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, +0xAF, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD9, 0xDB, 0xE0, 0x9E, 0x23, 0xE5, 0x5C, 0x6D, 0x00, 0x10, 0x33, 0xE3, 0x5C, +0xED, 0x18, 0xED, 0xB2, 0x20, 0x00, 0x40, 0x30, 0x81, 0xF7, 0x84, 0xFA, 0x00, 0x28, 0xC7, 0xD1, 0xEC, 0x23, 0xE3, 0x58, +0x00, 0x2B, 0x39, 0xD0, 0x9A, 0x7A, 0x00, 0x2A, 0x36, 0xD1, 0xAC, 0x32, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD1, 0xC2, 0xE0, +0x9A, 0x78, 0x05, 0x3A, 0x03, 0x2A, 0x00, 0xD8, 0xBD, 0xE0, 0x1A, 0x88, 0xA9, 0x00, 0x4D, 0x19, 0x6D, 0x00, 0x69, 0x49, +0x68, 0x18, 0x01, 0x88, 0xDE, 0x79, 0x0F, 0x23, 0x33, 0x40, 0xDB, 0x00, 0x78, 0x26, 0xB1, 0x43, 0x0B, 0x43, 0x03, 0x80, +0x64, 0x4B, 0xE9, 0x18, 0xD3, 0x00, 0x05, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x0B, 0x80, 0xEC, 0x23, 0xE3, 0x58, 0x1A, 0x89, +0x62, 0x4B, 0xEB, 0x18, 0x1A, 0x80, 0x60, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, +0xAE, 0x22, 0xA3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0xAF, 0xE7, +0xAC, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8B, 0xE0, 0x96, 0x23, 0xE1, 0x5A, 0x01, 0x27, 0x00, 0x29, 0x39, 0xD0, +0x02, 0xAB, 0x9A, 0x1D, 0x00, 0x98, 0xFF, 0xF7, 0x07, 0xFF, 0xAB, 0x00, 0x5D, 0x19, 0x6D, 0x00, 0x4B, 0x4B, 0xEA, 0x18, +0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0xC0, 0x00, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x48, 0x4B, 0xEA, 0x18, 0x02, 0xAB, +0xDB, 0x88, 0xDB, 0x00, 0x1F, 0x43, 0x04, 0x23, 0x1F, 0x43, 0xBF, 0xB2, 0x17, 0x80, 0x94, 0x22, 0xA1, 0x5A, 0x45, 0x4B, +0xEB, 0x18, 0x19, 0x80, 0x42, 0x4B, 0x9C, 0x46, 0x65, 0x44, 0x2B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x2B, 0x80, 0x02, 0xAB, +0xDB, 0x88, 0x96, 0x20, 0x21, 0x5A, 0xC9, 0x1A, 0x21, 0x52, 0xA1, 0x5A, 0x5B, 0x18, 0xA3, 0x52, 0x1A, 0x32, 0xA3, 0x5C, +0x59, 0x42, 0x4B, 0x41, 0xA3, 0x54, 0x01, 0x32, 0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x6B, 0xE7, 0x27, 0x00, 0x48, 0x37, +0x80, 0x23, 0x1B, 0x05, 0x9A, 0x46, 0x0F, 0xE0, 0x52, 0x00, 0x8A, 0x42, 0x1E, 0xDA, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, +0x31, 0x48, 0x7E, 0xF7, 0x7F, 0xFD, 0x01, 0x23, 0x03, 0x70, 0x7E, 0xF7, 0xA5, 0xFD, 0x30, 0x89, 0x88, 0xF7, 0x98, 0xFE, +0x38, 0x00, 0x81, 0xF7, 0xE7, 0xF9, 0x06, 0x1E, 0x46, 0xD0, 0x4B, 0x46, 0xE2, 0x5A, 0x00, 0x2A, 0x08, 0xD0, 0x43, 0x68, +0x59, 0x1C, 0x05, 0xD0, 0x41, 0x46, 0xCB, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x51, 0x45, 0xDD, 0xD9, 0x73, 0x89, 0x9F, 0x04, +0xBF, 0x0F, 0x9B, 0x05, 0x9B, 0x0D, 0x9A, 0x46, 0x90, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x2C, 0xD0, 0x8C, 0x23, 0xE3, 0x58, +0x00, 0x2B, 0x06, 0xD0, 0x1D, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x8C, 0x23, +0xE6, 0x50, 0x96, 0x23, 0x52, 0x46, 0xE2, 0x52, 0x32, 0x89, 0x02, 0x3B, 0xE2, 0x52, 0x01, 0x2F, 0x00, 0xD0, 0x02, 0x27, +0x96, 0x23, 0xE1, 0x5A, 0x00, 0x29, 0x00, 0xD0, 0x78, 0xE7, 0xAF, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0xA8, 0x23, +0xE3, 0x5C, 0x00, 0x2B, 0x02, 0xD1, 0xA8, 0x33, 0x01, 0x22, 0xE2, 0x54, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x90, 0x33, 0xE6, 0x50, 0xDC, 0xE7, 0x01, 0x27, 0xE3, 0xE7, 0x38, 0x27, 0x16, 0x00, +0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xCE, 0x69, 0x61, 0x40, +0x2B, 0x06, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, +0x83, 0xB0, 0x82, 0x00, 0x4B, 0x4B, 0xD4, 0x58, 0x90, 0x23, 0xE2, 0x58, 0x00, 0x2A, 0x00, 0xD1, 0x84, 0xE0, 0x49, 0x4B, +0x59, 0x88, 0x49, 0x4B, 0x1B, 0x78, 0x99, 0x42, 0x73, 0xD9, 0x9E, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0xAD, 0x21, 0x61, 0x5C, +0x5B, 0x18, 0xDB, 0xB2, 0x56, 0x89, 0xB6, 0x05, 0xB2, 0x0D, 0x90, 0x46, 0x02, 0x22, 0x90, 0x26, 0x41, 0x49, 0x01, 0x91, +0xAF, 0x21, 0x8A, 0x46, 0x01, 0x39, 0x89, 0x46, 0x10, 0x39, 0x8C, 0x46, 0x00, 0x90, 0x0C, 0xE0, 0x63, 0x46, 0xE5, 0x5C, +0x6D, 0x00, 0xAD, 0x23, 0xE1, 0x5C, 0x4B, 0x42, 0x4B, 0x41, 0x5B, 0x19, 0xDB, 0xB2, 0x01, 0x3A, 0xD2, 0xB2, 0x00, 0x2A, +0x31, 0xD0, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x35, 0x49, 0x5F, 0x18, 0x39, 0x88, 0x89, 0xB2, 0xA5, 0x59, 0x2D, 0x89, +0x8D, 0x42, 0xE7, 0xD8, 0x45, 0x44, 0xA9, 0x42, 0xE4, 0xDA, 0x31, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x01, 0x98, 0x01, 0x40, +0x29, 0x80, 0x2F, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x2D, 0x48, 0x01, 0x43, 0x89, 0xB2, 0x29, 0x80, +0x2C, 0x49, 0x8B, 0x46, 0x5B, 0x44, 0x19, 0x88, 0x78, 0x20, 0x81, 0x43, 0x19, 0x80, 0x00, 0x23, 0x3B, 0x80, 0x53, 0x46, +0xE3, 0x5C, 0x01, 0x3B, 0x51, 0x46, 0x63, 0x54, 0x4B, 0x46, 0xE3, 0x5C, 0x59, 0x42, 0x4B, 0x41, 0x49, 0x46, 0x63, 0x54, +0xC0, 0xE7, 0x00, 0x98, 0x00, 0x02, 0x01, 0x25, 0x28, 0x43, 0x81, 0xB2, 0x01, 0x23, 0xFF, 0x32, 0x1F, 0x48, 0x7E, 0xF7, +0xA5, 0xFC, 0x05, 0x70, 0x7E, 0xF7, 0xCC, 0xFC, 0x1D, 0x48, 0x80, 0xF7, 0xA3, 0xFD, 0x90, 0x23, 0xE3, 0x58, 0x18, 0x89, +0x88, 0xF7, 0xBA, 0xFD, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0x0B, 0xD0, 0x90, 0x22, 0xA3, 0x50, 0x8C, 0x23, 0x00, 0x22, +0xE2, 0x50, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x96, 0x22, 0x00, 0x21, +0xA1, 0x52, 0xEF, 0xE7, 0x8C, 0x23, 0xE3, 0x58, 0x00, 0x2B, 0xF0, 0xD0, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0x98, 0x47, 0xE9, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x9C, 0xE5, 0x10, 0x00, 0xF8, 0xE1, 0x10, 0x00, +0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, +0xCA, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x18, 0xD1, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x03, 0x00, 0x00, 0x20, +0x9A, 0x6C, 0x00, 0x2A, 0x00, 0xD0, 0x70, 0x47, 0xA7, 0x32, 0x9A, 0x5C, 0x00, 0x2A, 0xFA, 0xD1, 0xA8, 0x32, 0x98, 0x5C, +0x43, 0x42, 0x58, 0x41, 0xC0, 0xB2, 0xF4, 0xE7, 0x04, 0x4B, 0x18, 0x68, 0x04, 0x4B, 0x1B, 0x68, 0x18, 0x43, 0x43, 0x1E, +0x98, 0x41, 0xC0, 0xB2, 0x70, 0x47, 0xC0, 0x46, 0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x70, 0xB5, 0x84, 0xB0, +0x82, 0x00, 0x12, 0x4B, 0xD5, 0x58, 0x01, 0xA9, 0x11, 0x4C, 0x02, 0x01, 0x13, 0x1A, 0x9B, 0x00, 0xE3, 0x18, 0xDE, 0x88, +0x4E, 0x80, 0x1E, 0x7B, 0x4E, 0x70, 0x1E, 0x89, 0xCE, 0x80, 0x5E, 0x89, 0x0E, 0x81, 0x9B, 0x88, 0x8B, 0x80, 0x12, 0x1A, +0x92, 0x00, 0xA2, 0x18, 0x53, 0x7B, 0x01, 0x22, 0x53, 0x40, 0x36, 0x22, 0xAA, 0x5C, 0x5A, 0x40, 0x01, 0x23, 0x13, 0x40, +0x2E, 0x22, 0x13, 0x43, 0x0B, 0x70, 0xA6, 0xF7, 0x0F, 0xF9, 0x04, 0xB0, 0x70, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, +0xC0, 0xA0, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x0C, 0x00, 0x05, 0x0A, 0xAA, 0x00, 0x18, 0x4B, 0xD7, 0x58, 0x36, 0x23, +0xFB, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x2B, 0x01, 0x5B, 0x1B, 0x9B, 0x00, 0x14, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x00, 0x2B, +0x08, 0xD1, 0x01, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0x77, 0xFF, 0xF8, 0xBD, 0xE8, 0xB2, 0xB2, 0xF7, 0x73, 0xF9, 0xEE, 0xE7, +0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x0D, 0x48, 0x7E, 0xF7, 0xF6, 0xFB, 0x04, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, +0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xD0, 0xF7, 0x4B, 0xFA, 0x2B, 0x01, 0x5D, 0x1B, 0xAD, 0x00, +0x03, 0x4B, 0x5D, 0x19, 0x00, 0x23, 0x6B, 0x73, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xC0, 0xA0, 0x16, 0x00, +0x03, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x93, 0xB0, 0x05, 0x00, +0x03, 0x91, 0x93, 0x46, 0x1E, 0x00, 0x1C, 0xAB, 0x1B, 0x88, 0x99, 0x46, 0x1D, 0xAB, 0x1B, 0x88, 0x9A, 0x46, 0x04, 0x0A, +0xA2, 0x00, 0xCB, 0x4B, 0xD7, 0x58, 0x01, 0x00, 0xCA, 0x48, 0x7E, 0xF7, 0x7B, 0xFB, 0xB3, 0x1F, 0xC9, 0x4A, 0x9B, 0xB2, +0x93, 0x42, 0x03, 0xD8, 0x5B, 0x46, 0x33, 0x43, 0xDB, 0x07, 0x0D, 0xD5, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x12, 0x22, +0x17, 0x21, 0xA6, 0xF7, 0xF6, 0xF8, 0x13, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, +0x5E, 0x45, 0xEF, 0xD9, 0x4B, 0x46, 0x00, 0x2B, 0xEC, 0xD0, 0x73, 0x08, 0x4B, 0x45, 0xE9, 0xD3, 0x53, 0x46, 0x28, 0x2B, +0xE6, 0xD8, 0x4B, 0x44, 0x5B, 0x00, 0xB3, 0x42, 0xE2, 0xD2, 0x28, 0x00, 0x7E, 0xF7, 0x70, 0xFF, 0x01, 0x28, 0x00, 0xD1, +0x85, 0xE0, 0xB5, 0x4B, 0x22, 0x01, 0x11, 0x1B, 0x89, 0x00, 0xCE, 0x52, 0x5B, 0x18, 0x5E, 0x80, 0x4A, 0x46, 0x1A, 0x81, +0x9E, 0x80, 0x5A, 0x46, 0xDA, 0x80, 0x52, 0x46, 0x5A, 0x81, 0x03, 0x9A, 0x1A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x22, +0x04, 0x92, 0x01, 0x2B, 0x77, 0xD0, 0x0A, 0x96, 0x0B, 0x96, 0x36, 0x23, 0xF8, 0x5C, 0x4A, 0x46, 0x02, 0x2A, 0x00, 0xD9, +0x02, 0x22, 0x90, 0x46, 0x80, 0x44, 0x0A, 0xAB, 0x42, 0x46, 0x0C, 0x92, 0x49, 0x46, 0x49, 0x00, 0x0D, 0x91, 0x00, 0x21, +0x99, 0x74, 0x80, 0x31, 0x8C, 0x46, 0xA4, 0x44, 0x61, 0x46, 0x19, 0x82, 0x01, 0x21, 0x04, 0x9A, 0x11, 0x40, 0xD9, 0x74, +0x06, 0xAB, 0x06, 0x96, 0x42, 0x46, 0x07, 0x92, 0x62, 0x46, 0x9A, 0x81, 0x00, 0x28, 0x5A, 0xD1, 0x58, 0x46, 0x08, 0x90, +0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x5A, 0xD0, 0x08, 0x9B, 0x10, 0x93, 0x11, 0x93, 0x06, 0x9B, 0x0F, 0x93, 0x06, 0xA8, +0xD4, 0xF7, 0x5A, 0xFA, 0x80, 0x46, 0x00, 0x28, 0x72, 0xD1, 0x0A, 0xAA, 0x10, 0x98, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, +0x8D, 0x49, 0xCB, 0x18, 0x98, 0x62, 0x0F, 0x99, 0x8C, 0x46, 0x59, 0x62, 0x0C, 0x99, 0xD9, 0x62, 0x0D, 0x99, 0x19, 0x63, +0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x6B, 0xD1, +0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x81, 0x4A, 0xD3, 0x18, 0xD8, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, +0x67, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7D, 0x4B, 0x9A, 0x42, 0x79, 0xD1, 0x43, 0x46, 0x01, 0x2B, +0x00, 0xD1, 0xDF, 0xE0, 0x02, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0x2B, 0x00, 0xD1, 0xAE, 0xE0, 0x77, 0x4B, 0x9B, 0x6E, +0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x5D, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x70, 0x4A, 0xD3, 0x18, +0x00, 0x22, 0x5A, 0x73, 0x71, 0xE7, 0xE0, 0xB2, 0xAF, 0xF7, 0xAE, 0xFE, 0x43, 0x08, 0x04, 0x93, 0x81, 0xE7, 0x04, 0x9A, +0x31, 0x00, 0x58, 0x46, 0xA5, 0xF7, 0x2E, 0xFD, 0x9F, 0xE7, 0x06, 0x9B, 0x9B, 0x46, 0x01, 0x3B, 0x98, 0x46, 0x80, 0x44, +0x5B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x66, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x59, 0x46, +0x40, 0x46, 0xD4, 0xF7, 0x1B, 0xFE, 0x08, 0x91, 0x0A, 0xAB, 0xDA, 0x7C, 0x01, 0x21, 0x4A, 0x40, 0xDA, 0x74, 0x0C, 0x9A, +0x03, 0x32, 0x0C, 0x92, 0x0D, 0x9A, 0x03, 0x32, 0x0D, 0x92, 0x07, 0x9B, 0x05, 0x93, 0x03, 0x33, 0x07, 0x93, 0x81, 0xE7, +0x28, 0x00, 0x7E, 0xF7, 0xAD, 0xFE, 0x80, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x01, 0x23, 0x98, 0x46, 0x83, 0xE7, 0x0A, 0xA8, +0xD4, 0xF7, 0x6A, 0xF9, 0x00, 0x28, 0x00, 0xD0, 0x7D, 0xE7, 0x02, 0x23, 0x98, 0x46, 0x7A, 0xE7, 0x63, 0x46, 0x99, 0xB2, +0x80, 0xB2, 0x04, 0x9A, 0xA5, 0xF7, 0x0A, 0xFD, 0x8D, 0xE7, 0x43, 0x1C, 0x04, 0x93, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, +0x05, 0xD1, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, +0x42, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0xDB, 0xFD, 0x05, 0x9B, 0xD9, 0x80, 0x7E, 0xE7, +0xE3, 0xB2, 0x9B, 0x46, 0x18, 0x00, 0x95, 0xF7, 0x71, 0xFF, 0x05, 0x90, 0x0F, 0x9B, 0x04, 0x93, 0x00, 0x28, 0x05, 0xD1, +0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x05, 0x99, 0x04, 0x98, 0xD4, 0xF7, 0xC4, 0xFD, +0x00, 0x29, 0x00, 0xD0, 0x6E, 0xE7, 0x3C, 0x22, 0x62, 0x43, 0x31, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0x11, 0x9B, 0x04, 0x93, +0x10, 0x9B, 0x05, 0x93, 0x04, 0x9B, 0x05, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x58, 0x46, 0x95, 0xF7, 0x9C, 0xFF, +0x04, 0x90, 0x0F, 0x9B, 0x9B, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x29, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, +0x98, 0x47, 0x3C, 0x23, 0x63, 0x43, 0x23, 0x4A, 0xD3, 0x18, 0x05, 0x93, 0x59, 0x46, 0x04, 0x98, 0xD4, 0xF7, 0x9C, 0xFD, +0x05, 0x9B, 0xD9, 0x80, 0x46, 0xE7, 0x39, 0x33, 0xFA, 0x5C, 0xE0, 0xB2, 0x17, 0x21, 0xA5, 0xF7, 0x87, 0xFF, 0x2F, 0x21, +0x28, 0x00, 0x7E, 0xF7, 0xD5, 0xFD, 0xAA, 0xE6, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x0A, 0xD0, 0xE0, 0xB2, 0xFF, 0xF7, +0x13, 0xFE, 0x28, 0x00, 0x96, 0xF7, 0x3A, 0xFB, 0x2E, 0x21, 0x28, 0x00, 0x7E, 0xF7, 0xC6, 0xFD, 0x9B, 0xE6, 0x3C, 0x22, +0x62, 0x43, 0x10, 0x4B, 0x9B, 0x18, 0xD9, 0x88, 0xE0, 0xB2, 0x03, 0x9B, 0x9F, 0x07, 0xFF, 0x0F, 0x01, 0x97, 0x53, 0x46, +0x00, 0x93, 0x4B, 0x46, 0x32, 0x00, 0xAF, 0xF7, 0x5F, 0xFC, 0xE3, 0xE7, 0x39, 0x23, 0xFB, 0x5C, 0xE0, 0xB2, 0x20, 0x22, +0x17, 0x21, 0xA5, 0xF7, 0x7A, 0xFF, 0x20, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFE, 0x7E, 0xE6, 0x64, 0xA2, 0x16, 0x00, +0x05, 0x06, 0x00, 0x00, 0x3A, 0x05, 0x00, 0x00, 0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, +0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x8A, 0xB0, 0x06, 0x00, 0x88, 0x46, 0x91, 0x46, 0x1D, 0x00, +0x12, 0xAB, 0x1B, 0x88, 0x9C, 0x46, 0x04, 0x0A, 0xA2, 0x00, 0x9C, 0x4B, 0xD7, 0x58, 0x9C, 0x4B, 0x22, 0x01, 0x11, 0x1B, +0x89, 0x00, 0x40, 0x46, 0xC8, 0x52, 0x5B, 0x18, 0x4A, 0x46, 0x5A, 0x80, 0x1D, 0x81, 0x62, 0x46, 0x5A, 0x81, 0x36, 0x23, +0xFB, 0x5C, 0x00, 0x22, 0x92, 0x46, 0x01, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x91, 0x4A, +0xD3, 0x18, 0x00, 0x22, 0x1A, 0x73, 0xA7, 0xF7, 0x29, 0xFE, 0x50, 0x44, 0x03, 0x01, 0x06, 0xD5, 0x23, 0x01, 0x1B, 0x1B, +0x9B, 0x00, 0x8B, 0x4A, 0xD3, 0x18, 0x02, 0x22, 0x1A, 0x73, 0x02, 0xAB, 0x4A, 0x46, 0x02, 0x92, 0x42, 0x46, 0x5A, 0x60, +0x2A, 0x00, 0x02, 0x2D, 0x00, 0xD9, 0x02, 0x22, 0x9A, 0x60, 0x6D, 0x00, 0x05, 0x95, 0x00, 0x23, 0x02, 0xAA, 0x93, 0x74, +0x25, 0x00, 0x80, 0x35, 0x15, 0x82, 0x53, 0x46, 0x5B, 0x08, 0x9A, 0x46, 0x01, 0x23, 0x52, 0x46, 0x13, 0x40, 0x02, 0xAA, +0xD3, 0x74, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, 0x7B, 0x4B, 0x9A, 0x42, 0x58, 0xD1, 0x36, 0x23, 0xFB, 0x5C, +0x01, 0x2B, 0x6A, 0xD0, 0x02, 0xA8, 0xD4, 0xF7, 0x63, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x72, 0xE0, 0x08, 0x98, 0x22, 0x01, +0x12, 0x1B, 0x92, 0x00, 0x71, 0x4B, 0x9B, 0x18, 0x98, 0x62, 0x07, 0x99, 0x59, 0x62, 0x04, 0x9A, 0xDA, 0x62, 0x05, 0x9A, +0x00, 0x92, 0x1A, 0x63, 0x02, 0xAA, 0x12, 0x8A, 0x9A, 0x86, 0x00, 0x22, 0x9A, 0x63, 0x36, 0x33, 0x1A, 0x70, 0x36, 0x23, +0xFB, 0x5C, 0x00, 0x2B, 0x6A, 0xD1, 0x80, 0xB2, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x65, 0x4A, 0xD3, 0x18, 0xD8, 0x80, +0x07, 0x9D, 0x9D, 0x80, 0x36, 0x23, 0xFB, 0x5C, 0x01, 0x2B, 0x63, 0xD0, 0xD9, 0x23, 0x9B, 0x00, 0xFB, 0x18, 0x1A, 0x88, +0x5F, 0x4B, 0x9A, 0x42, 0x00, 0xD0, 0x72, 0xE0, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x5B, 0x4A, 0xD3, 0x18, 0x01, 0x22, +0x5A, 0x73, 0x36, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xA4, 0xE0, 0xE0, 0xB2, 0xFF, 0xF7, 0x43, 0xFD, 0x30, 0x00, +0x96, 0xF7, 0x6A, 0xFA, 0x2E, 0x21, 0x30, 0x00, 0x7E, 0xF7, 0xF6, 0xFC, 0x0A, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xA2, 0x46, 0xF0, 0xBD, 0xE0, 0xB2, 0xAF, 0xF7, 0x1F, 0xFD, 0x82, 0x46, 0x72, 0xE7, 0xE0, 0xB2, 0x95, 0xF7, 0x40, 0xFE, +0x02, 0x00, 0x03, 0x00, 0x02, 0x98, 0x82, 0x42, 0x07, 0xD2, 0x00, 0x92, 0x11, 0x00, 0xD4, 0xF7, 0x13, 0xFC, 0x43, 0x1C, +0x00, 0x9A, 0x5A, 0x43, 0x93, 0xB2, 0x03, 0x9A, 0x93, 0x42, 0x93, 0xD8, 0x02, 0x93, 0x03, 0x93, 0x90, 0xE7, 0x02, 0xAB, +0xDB, 0x7C, 0x01, 0x22, 0x53, 0x40, 0x02, 0xAA, 0xD3, 0x74, 0x04, 0x9B, 0x03, 0x33, 0x04, 0x93, 0x05, 0x9B, 0x00, 0x93, +0x03, 0x33, 0x05, 0x93, 0x86, 0xE7, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, 0x3A, 0x48, 0x7E, 0xF7, 0x4B, 0xF9, 0x20, 0x23, +0x03, 0x70, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, 0xFB, 0x5C, 0x03, 0x71, 0xCF, 0xF7, 0xA1, 0xFF, 0xBF, 0xE7, +0x89, 0xB2, 0x80, 0xB2, 0x52, 0x46, 0xA5, 0xF7, 0x83, 0xFB, 0x8F, 0xE7, 0x43, 0x1C, 0x98, 0x46, 0x00, 0x2D, 0x05, 0xD1, +0x2F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x28, 0x4A, +0x91, 0x46, 0x99, 0x44, 0x29, 0x00, 0x40, 0x46, 0xD4, 0xF7, 0x56, 0xFC, 0x4B, 0x46, 0xD9, 0x80, 0x84, 0xE7, 0xE3, 0xB2, +0x98, 0x46, 0x18, 0x00, 0x95, 0xF7, 0xEC, 0xFD, 0x05, 0x1E, 0x07, 0x9B, 0x99, 0x46, 0x05, 0xD1, 0x21, 0x4B, 0x9B, 0x6E, +0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x29, 0x00, 0x48, 0x46, 0xD4, 0xF7, 0x40, 0xFC, 0x00, 0x29, 0x00, 0xD0, +0x76, 0xE7, 0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x16, 0x4A, 0xD3, 0x18, 0xD9, 0x88, 0x09, 0x9B, 0x00, 0x93, 0x08, 0x9B, +0x01, 0x93, 0x00, 0x9B, 0x01, 0x9A, 0x9A, 0x1A, 0x8A, 0x18, 0x92, 0xB2, 0x40, 0x46, 0x95, 0xF7, 0x17, 0xFE, 0x81, 0x46, +0x07, 0x9B, 0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x0F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x23, 0x01, 0x1B, 0x1B, 0x9B, 0x00, 0x08, 0x4D, 0xED, 0x18, 0x41, 0x46, 0x48, 0x46, 0xD4, 0xF7, 0x17, 0xFC, 0xE9, 0x80, +0x4E, 0xE7, 0xE0, 0xB2, 0x01, 0x33, 0x00, 0x22, 0x17, 0x21, 0x95, 0xF7, 0x89, 0xFC, 0x53, 0xE7, 0x64, 0xA2, 0x16, 0x00, +0xC0, 0xA0, 0x16, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, +0x00, 0xB5, 0x00, 0x24, 0x00, 0x20, 0x0E, 0x4E, 0xA1, 0x27, 0xAF, 0x23, 0x98, 0x46, 0x0C, 0xE0, 0x42, 0x46, 0x9D, 0x5C, +0x45, 0x19, 0xED, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x18, 0xFE, 0x28, 0x18, 0xC0, 0xB2, 0x01, 0x34, 0x07, 0x2C, +0x07, 0xD0, 0xA3, 0x00, 0x9B, 0x59, 0x00, 0x2B, 0xF8, 0xD0, 0xDA, 0x5D, 0x00, 0x2A, 0xF5, 0xD1, 0xEA, 0xE7, 0x04, 0xBC, +0x90, 0x46, 0xF0, 0xBD, 0x38, 0x27, 0x16, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x40, 0x4B, 0x1A, 0x78, 0x01, 0x2A, 0x01, 0xD0, +0x05, 0xB0, 0xF0, 0xBD, 0x3E, 0x4B, 0x1D, 0x78, 0x3E, 0x4B, 0x1B, 0x68, 0x00, 0x24, 0x5B, 0x05, 0x08, 0xD5, 0x3C, 0x48, +0x03, 0x68, 0x3C, 0x49, 0x19, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x0B, 0x43, 0x03, 0x60, 0x80, 0x34, 0x39, 0x4B, 0x1B, 0x68, +0x9B, 0x05, 0x09, 0xD4, 0x37, 0x48, 0x03, 0x68, 0x37, 0x49, 0x19, 0x40, 0x80, 0x23, 0x9B, 0x00, 0x0B, 0x43, 0x03, 0x60, +0x40, 0x23, 0x1C, 0x43, 0x34, 0x4B, 0x18, 0x68, 0x34, 0x4B, 0x19, 0x68, 0x34, 0x4B, 0x1E, 0x68, 0x8B, 0x07, 0x31, 0xD4, +0xF0, 0x23, 0x03, 0x40, 0x30, 0x2B, 0x0E, 0xD0, 0x20, 0x2B, 0x1F, 0xD0, 0x10, 0x2B, 0x29, 0xD1, 0x2F, 0x4B, 0xDB, 0x69, +0xB3, 0x42, 0x25, 0xD0, 0xF0, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x3B, 0x00, 0x20, 0x27, 0x3B, 0x43, 0x0A, 0xE0, 0x2A, 0x4B, +0xDB, 0x6B, 0xB3, 0x42, 0x1A, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x20, 0x22, 0x13, 0x43, 0x1D, 0x3A, +0x22, 0x4F, 0x3F, 0x68, 0xBF, 0x07, 0x1F, 0xD4, 0x1F, 0x4F, 0x3B, 0x60, 0x14, 0x43, 0x1D, 0xE0, 0x20, 0x4B, 0xDB, 0x6A, +0xB3, 0x42, 0x07, 0xD0, 0xF0, 0x23, 0x02, 0x00, 0x9A, 0x43, 0x13, 0x00, 0x10, 0x22, 0x13, 0x43, 0x0E, 0x3A, 0xEB, 0xE7, +0x01, 0x2D, 0xA3, 0xD1, 0x17, 0x4B, 0x1B, 0x68, 0x02, 0x93, 0x00, 0x23, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x00, 0x22, +0x16, 0x48, 0x80, 0xF7, 0x47, 0xF9, 0x00, 0x2C, 0x96, 0xD0, 0x0D, 0xE0, 0x04, 0x27, 0x3C, 0x43, 0x01, 0x2D, 0x00, 0xD0, +0x90, 0xE7, 0x0E, 0x4D, 0x2D, 0x68, 0x02, 0x95, 0x01, 0x93, 0x00, 0x90, 0x33, 0x00, 0x0E, 0x48, 0x80, 0xF7, 0x36, 0xF9, +0x32, 0x00, 0x21, 0x00, 0x0C, 0x48, 0x80, 0xF7, 0x31, 0xF9, 0x81, 0xE7, 0xB4, 0xE5, 0x10, 0x00, 0xBC, 0xE6, 0x10, 0x00, +0x4C, 0x20, 0x62, 0x40, 0xFF, 0xF3, 0xFF, 0xFF, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, 0x08, 0x05, 0x62, 0x40, +0x74, 0x20, 0x62, 0x40, 0x78, 0x20, 0x62, 0x40, 0xD8, 0x97, 0x16, 0x00, 0x24, 0xD1, 0x10, 0x00, 0x3C, 0xD1, 0x10, 0x00, +0x70, 0x47, 0x00, 0x00, 0x03, 0x4B, 0x04, 0x4A, 0x13, 0x60, 0x81, 0x22, 0x52, 0x00, 0x98, 0x5C, 0x70, 0x47, 0xC0, 0x46, +0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x17, 0x4B, 0x17, 0x4A, 0x1A, 0x60, +0x17, 0x48, 0x80, 0xF7, 0x53, 0xFD, 0x45, 0x1E, 0x6D, 0xB2, 0x40, 0xB2, 0x00, 0x28, 0x1F, 0xDD, 0x11, 0x4F, 0x14, 0x4B, +0x98, 0x46, 0x14, 0x4E, 0x0A, 0xE0, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x43, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x09, 0xE0, +0x01, 0x3D, 0x6D, 0xB2, 0x6B, 0x1C, 0x0F, 0xD0, 0x38, 0x68, 0x0C, 0x30, 0x80, 0xF7, 0x56, 0xFC, 0x04, 0x1E, 0xEE, 0xD0, +0x61, 0x6A, 0x30, 0x00, 0x80, 0xF7, 0xE2, 0xF8, 0x63, 0x6A, 0x00, 0x2B, 0xEE, 0xD0, 0x20, 0x00, 0x98, 0x47, 0xEB, 0xE7, +0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x70, 0x2A, 0x16, 0x00, +0x28, 0x19, 0x16, 0x00, 0xC0, 0xD3, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x78, 0x21, 0x88, 0xF7, 0xAB, 0xF9, 0x05, 0x00, +0x08, 0x4B, 0xC0, 0x18, 0x78, 0x22, 0x55, 0x21, 0x7C, 0xF7, 0x42, 0xF8, 0x29, 0x00, 0x20, 0x00, 0x88, 0xF7, 0xBA, 0xF9, +0x01, 0x00, 0x20, 0x00, 0xB0, 0xF7, 0x1E, 0xFD, 0x02, 0x48, 0x80, 0xF7, 0xB7, 0xF8, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, +0x4C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x04, 0x00, +0x83, 0x00, 0x76, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1D, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xDE, 0xE0, 0x4B, 0x23, 0xEB, 0x5C, +0x00, 0x2B, 0x05, 0xD0, 0x71, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x28, 0x00, 0x50, 0x30, +0x80, 0xF7, 0x02, 0xFC, 0x07, 0x00, 0x00, 0x21, 0x20, 0x00, 0x88, 0xF7, 0xDF, 0xF9, 0x63, 0x01, 0x6A, 0x4A, 0x9A, 0x18, +0x12, 0x68, 0xD2, 0x0F, 0x49, 0x21, 0x69, 0x5C, 0x01, 0x26, 0x71, 0x40, 0x91, 0x42, 0x4F, 0xD0, 0x66, 0x49, 0x8A, 0x46, +0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x89, 0xB2, 0x8B, 0x46, 0x64, 0x4E, 0xB1, 0x46, 0x99, 0x44, 0x4E, 0x46, 0x36, 0x68, +0xB6, 0xB2, 0xB0, 0x46, 0x61, 0x4E, 0x9E, 0x19, 0x36, 0x68, 0xB6, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x56, 0x46, 0x36, 0x68, +0x36, 0x0C, 0x36, 0x04, 0xB4, 0x46, 0x56, 0x46, 0x61, 0x46, 0x31, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x09, 0x04, +0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x00, 0x2F, 0x67, 0xD0, 0x00, 0x2A, 0x4C, 0xD1, 0x52, 0x4A, 0x94, 0x46, +0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, 0x91, 0x46, 0xBA, 0x88, 0x12, 0x04, 0x49, 0x46, 0x0F, 0x04, 0x3F, 0x0C, 0x3A, 0x43, +0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0x0A, 0xD0, 0x4B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, +0x12, 0x04, 0x38, 0x04, 0x00, 0x0C, 0x02, 0x43, 0x1A, 0x60, 0x5B, 0x46, 0x00, 0x2B, 0x4C, 0xD1, 0x43, 0x46, 0x00, 0x2B, +0x4E, 0xD1, 0x03, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x3E, 0x49, 0x8A, 0x46, +0x9A, 0x44, 0x51, 0x46, 0x09, 0x68, 0x09, 0x0C, 0x8B, 0x46, 0x3C, 0x49, 0x89, 0x46, 0x99, 0x44, 0x49, 0x46, 0x0E, 0x68, +0x31, 0x0C, 0x88, 0x46, 0x39, 0x49, 0x5E, 0x18, 0x36, 0x68, 0x36, 0x03, 0xB1, 0x0F, 0x01, 0x91, 0x51, 0x46, 0x09, 0x68, +0x09, 0x04, 0x09, 0x0C, 0x8C, 0x46, 0x51, 0x46, 0x66, 0x46, 0x0E, 0x60, 0x49, 0x46, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0C, +0x8C, 0x46, 0x49, 0x46, 0x66, 0x46, 0x0E, 0x60, 0xAE, 0xE7, 0x2C, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, 0x12, 0x68, +0x12, 0x0C, 0x12, 0x04, 0xBF, 0x88, 0x3A, 0x43, 0x61, 0x46, 0x0A, 0x60, 0x00, 0x28, 0xC0, 0xD0, 0x26, 0x4A, 0x94, 0x46, +0x63, 0x44, 0x1F, 0x68, 0x82, 0x88, 0x04, 0x32, 0x92, 0xB2, 0x38, 0x0C, 0x00, 0x04, 0x02, 0x43, 0x1A, 0x60, 0xB4, 0xE7, +0x00, 0x28, 0xB2, 0xD0, 0x00, 0x2A, 0xEF, 0xD1, 0xA4, 0xE7, 0x59, 0x46, 0x20, 0x00, 0x88, 0xF7, 0x17, 0xF9, 0xAD, 0xE7, +0x46, 0x23, 0xE9, 0x5C, 0x09, 0x02, 0x45, 0x3B, 0x19, 0x43, 0x05, 0x33, 0xFF, 0x22, 0x1A, 0x48, 0x7D, 0xF7, 0xDE, 0xFE, +0x07, 0x00, 0x43, 0x46, 0x03, 0x80, 0x58, 0x23, 0xEA, 0x5C, 0x01, 0x32, 0x2B, 0x8F, 0x53, 0x43, 0x83, 0x70, 0x01, 0x99, +0xC1, 0x70, 0x14, 0x4B, 0x1A, 0x68, 0x01, 0x32, 0x1A, 0x60, 0x00, 0x29, 0x04, 0xD1, 0x3C, 0x71, 0x38, 0x00, 0x7D, 0xF7, +0xF3, 0xFE, 0x90, 0xE7, 0x0F, 0x49, 0x0B, 0x68, 0x01, 0x33, 0x0B, 0x60, 0x01, 0x99, 0x0E, 0x48, 0x7F, 0xF7, 0xC4, 0xFF, +0xF1, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x80, 0xE7, 0x54, 0x27, 0x16, 0x00, +0x28, 0x19, 0x16, 0x00, 0xD0, 0x05, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, 0xD4, 0x05, 0x60, 0x40, +0x35, 0x06, 0x00, 0x00, 0xC4, 0xE6, 0x10, 0x00, 0xC0, 0xE6, 0x10, 0x00, 0x54, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, +0x15, 0x00, 0x10, 0x00, 0x7E, 0xF7, 0x74, 0xFA, 0x00, 0x28, 0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x07, 0xD8, +0x21, 0x88, 0x04, 0x39, 0x89, 0xB2, 0x20, 0x79, 0x88, 0xF7, 0xFA, 0xF8, 0x00, 0x20, 0x70, 0xBD, 0x2E, 0x0A, 0x06, 0x23, +0x2A, 0x00, 0x31, 0x00, 0x1B, 0x48, 0x7D, 0xF7, 0x89, 0xFE, 0x05, 0x00, 0x23, 0x88, 0x83, 0x80, 0xA3, 0x78, 0x83, 0x70, +0x21, 0x79, 0x01, 0x31, 0x09, 0x02, 0x80, 0x36, 0x89, 0x19, 0x01, 0x80, 0xE1, 0x78, 0x0A, 0x03, 0x14, 0x4B, 0x1A, 0x42, +0x06, 0xD0, 0xC0, 0x20, 0x13, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x80, 0x01, 0xB0, 0x47, 0x2B, 0x88, 0x0F, 0x4A, +0x13, 0x40, 0xE2, 0x78, 0x12, 0x03, 0x13, 0x43, 0x2B, 0x80, 0xE3, 0x78, 0x00, 0x2B, 0x03, 0xD1, 0x28, 0x00, 0xCF, 0xF7, +0xC5, 0xFC, 0xD1, 0xE7, 0xA2, 0x78, 0x20, 0x88, 0x09, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x7B, 0xF7, 0xE0, 0xFE, +0xE1, 0x78, 0x00, 0x29, 0xF0, 0xD0, 0x06, 0x48, 0x7F, 0xF7, 0x5A, 0xFF, 0xEC, 0xE7, 0xC0, 0x46, 0x07, 0x11, 0x00, 0x00, +0xFF, 0xCF, 0xFF, 0xFF, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0x6C, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0x89, 0xB0, +0x04, 0x1E, 0x00, 0xD1, 0xAB, 0xE0, 0x46, 0x23, 0xC6, 0x5C, 0xB2, 0x00, 0x5A, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, +0xA9, 0xE0, 0x43, 0x68, 0x02, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0xC3, 0x62, 0x28, 0x30, 0xD2, 0xF7, 0xE9, 0xFD, 0x62, 0x68, +0x61, 0x6B, 0x8A, 0x42, 0x13, 0xD0, 0x45, 0x23, 0xE3, 0x5C, 0x5B, 0x00, 0x5B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, +0x0B, 0xD0, 0x4F, 0x4B, 0x9B, 0x7A, 0xA3, 0x75, 0x4A, 0x23, 0xE3, 0x5C, 0x03, 0x2B, 0x00, 0xD0, 0x8D, 0xE0, 0x47, 0x33, +0x00, 0x22, 0xE2, 0x54, 0x89, 0xE0, 0x4A, 0x4B, 0x00, 0x93, 0x01, 0x92, 0xA3, 0x68, 0x02, 0x93, 0x6B, 0x46, 0x1E, 0x76, +0x47, 0x23, 0xE0, 0x5C, 0x03, 0x01, 0x33, 0x43, 0x04, 0x93, 0x00, 0x23, 0x9C, 0x46, 0x03, 0x93, 0xA7, 0x7D, 0x6B, 0x46, +0x1F, 0x75, 0x67, 0x46, 0x5F, 0x75, 0x9F, 0x75, 0x8A, 0x42, 0x00, 0xD1, 0x73, 0xE0, 0x10, 0x23, 0x6A, 0x46, 0xD3, 0x75, +0x0C, 0x3B, 0x6A, 0x46, 0x93, 0x76, 0xD0, 0x76, 0x01, 0x23, 0x53, 0x76, 0x68, 0x46, 0xD3, 0xF7, 0x9B, 0xF8, 0x48, 0x22, +0xA3, 0x5C, 0x01, 0x33, 0xA3, 0x54, 0x01, 0x21, 0x63, 0x68, 0x62, 0x6B, 0x93, 0x42, 0x35, 0xD0, 0x47, 0x23, 0xE3, 0x5C, +0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x01, 0x1A, 0x68, 0x32, 0x48, 0x02, 0x40, 0x09, 0x04, 0x0A, 0x43, 0x1A, 0x60, +0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0xB6, 0xD1, 0x2B, 0x6D, 0x5F, 0x1C, 0x7F, 0x08, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x22, +0x56, 0x43, 0x2B, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x29, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x80, 0x23, +0x9B, 0x01, 0x9F, 0x42, 0x2B, 0xD3, 0x27, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0xF9, 0xF8, 0x00, 0x29, 0x19, 0xD0, 0x25, 0x4B, +0x9C, 0x46, 0x66, 0x44, 0x22, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x6A, 0xF8, 0x01, 0x30, 0x22, 0x4B, 0x03, 0x43, 0x9B, 0xB2, +0x33, 0x80, 0x90, 0xE7, 0x20, 0x4B, 0x2A, 0x6D, 0x9A, 0x42, 0xC5, 0xD8, 0x4A, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xC1, 0xD1, +0x44, 0x33, 0xE1, 0x5C, 0x01, 0x31, 0xC9, 0xB2, 0xBC, 0xE7, 0x18, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x15, 0x49, 0x38, 0x00, +0xD4, 0xF7, 0x50, 0xF8, 0x15, 0x4B, 0x03, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x77, 0xE7, 0x01, 0x37, 0x7F, 0x08, 0xBF, 0xB2, +0x10, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0x37, 0x80, 0x6F, 0xE7, 0x11, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, +0x98, 0x47, 0x09, 0xB0, 0xF0, 0xBD, 0x0F, 0x23, 0x6A, 0x46, 0xD3, 0x75, 0x0D, 0x3B, 0x8A, 0xE7, 0x38, 0x27, 0x16, 0x00, +0x7C, 0x91, 0x0D, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x2F, 0x00, 0x03, 0x02, 0xFF, 0xFF, 0x00, 0xFF, 0xFA, 0x64, 0x61, 0x40, +0xFC, 0x64, 0x61, 0x40, 0x71, 0x02, 0x00, 0x00, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0xE1, 0x04, 0x00, 0x00, +0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x06, 0x00, 0x14, 0x4B, 0x1D, 0x68, 0x00, 0x2D, 0x05, 0xD1, 0x5D, 0x68, 0x00, 0x2D, +0x02, 0xD1, 0x00, 0x24, 0x20, 0x00, 0xF8, 0xBD, 0xAB, 0x68, 0x2A, 0x69, 0x94, 0x46, 0x63, 0x44, 0x1F, 0x00, 0x0E, 0x49, +0x18, 0x00, 0xD4, 0xF7, 0x09, 0xF8, 0x6C, 0x6B, 0x04, 0x19, 0x0B, 0x49, 0x38, 0x00, 0xD4, 0xF7, 0x89, 0xF8, 0xB3, 0x68, +0x9C, 0x46, 0x8C, 0x45, 0x89, 0x41, 0x49, 0x42, 0x64, 0x18, 0xB1, 0x8A, 0x89, 0x04, 0x49, 0x0F, 0x04, 0x29, 0xE3, 0xD0, +0x20, 0x00, 0xFC, 0xF7, 0x63, 0xFF, 0x04, 0x00, 0xDE, 0xE7, 0xC0, 0x46, 0x54, 0x27, 0x16, 0x00, 0x71, 0x02, 0x00, 0x00, +0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0xBD, 0x4B, 0x1C, 0x68, 0xA1, 0x46, +0xBC, 0x4B, 0xA3, 0x82, 0x4C, 0x23, 0xE3, 0x5A, 0x5B, 0x00, 0x62, 0x6C, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, +0xE3, 0x60, 0xA7, 0xF7, 0x5D, 0xF9, 0x04, 0x90, 0xB6, 0x4B, 0x1B, 0x68, 0x01, 0x93, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x93, +0xB5, 0x4B, 0x1B, 0x68, 0x07, 0x93, 0xB5, 0x4B, 0x1B, 0x68, 0x06, 0x93, 0x00, 0x25, 0x00, 0x20, 0x00, 0x27, 0x00, 0x23, +0x03, 0x93, 0x00, 0x26, 0xB1, 0x4B, 0x98, 0x46, 0xA1, 0x23, 0x9A, 0x46, 0x02, 0x3B, 0x9B, 0x46, 0x0F, 0xE0, 0x01, 0x37, +0xFF, 0xB2, 0xAF, 0x22, 0x9E, 0x5C, 0x86, 0x19, 0xF6, 0xB2, 0x48, 0x33, 0x18, 0x00, 0x80, 0xF7, 0x5F, 0xFA, 0x30, 0x18, +0xC0, 0xB2, 0x01, 0x26, 0x01, 0x35, 0x07, 0x2D, 0x0E, 0xD0, 0xAB, 0x00, 0x42, 0x46, 0x9B, 0x58, 0x00, 0x2B, 0xF7, 0xD0, +0x52, 0x46, 0x9A, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x5A, 0x46, 0x9A, 0x5C, 0x01, 0x2A, 0xE2, 0xD1, 0x03, 0x92, 0xE0, 0xE7, +0x9F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x00, 0x23, 0x01, 0x32, 0xBA, 0x42, 0x5B, 0x41, 0x02, 0x33, 0x9C, 0x4A, 0x13, 0x70, +0x83, 0x42, 0x08, 0xD8, 0x00, 0x22, 0x03, 0x28, 0x01, 0xD9, 0xC2, 0x1E, 0xD2, 0xB2, 0xC0, 0x1A, 0x10, 0x18, 0x96, 0x4B, +0x18, 0x70, 0x50, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x95, 0x4B, 0x19, 0x00, 0x41, 0x31, 0xFF, 0x31, 0x00, 0x25, 0x04, 0xE0, +0x01, 0x35, 0xED, 0xB2, 0x40, 0x33, 0x8B, 0x42, 0x07, 0xD0, 0x1A, 0x78, 0x09, 0x2A, 0xF9, 0xD1, 0x00, 0x2F, 0xF5, 0xD0, +0x01, 0x37, 0xFF, 0xB2, 0xF2, 0xE7, 0xB0, 0xF7, 0x5F, 0xFA, 0x05, 0x90, 0x80, 0x46, 0x02, 0x9B, 0x01, 0x9A, 0x13, 0x43, +0x5A, 0x1E, 0x93, 0x41, 0xDB, 0xB2, 0x9B, 0x46, 0x87, 0x4B, 0x1B, 0x78, 0x9A, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x79, 0xE0, +0x85, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x28, 0xD9, 0x02, 0x2B, 0x64, 0xD0, 0x8C, 0xF7, 0xDC, 0xF8, 0x82, 0x46, 0x00, 0x28, +0x00, 0xD1, 0x1B, 0xE2, 0x00, 0x23, 0x9A, 0x46, 0x7F, 0x4B, 0x23, 0x64, 0x02, 0x22, 0x62, 0x63, 0xFA, 0x22, 0x92, 0x01, +0xA2, 0x62, 0x19, 0x00, 0x23, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x77, 0xE0, 0xA3, 0x6A, 0x62, 0x6B, 0x98, 0x1A, +0x40, 0x00, 0x04, 0x9B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x01, 0x2D, 0x00, 0xD1, 0x84, 0xE1, +0x00, 0x22, 0x20, 0x00, 0xFC, 0xF7, 0x9A, 0xFF, 0x11, 0xE0, 0x71, 0x4B, 0x23, 0x64, 0x80, 0x22, 0x62, 0x63, 0xA2, 0x62, +0x6C, 0x4A, 0x01, 0x21, 0x11, 0x70, 0x16, 0x22, 0xA2, 0x75, 0x23, 0x61, 0x04, 0x98, 0x2C, 0x30, 0x00, 0x01, 0x00, 0x09, +0x60, 0x60, 0x00, 0x23, 0x9A, 0x46, 0x69, 0x4E, 0x4C, 0x25, 0x69, 0x4F, 0x48, 0x46, 0xD1, 0xF7, 0x33, 0xFF, 0x00, 0x28, +0x00, 0xD1, 0xB0, 0xE1, 0x31, 0x00, 0x20, 0x69, 0xD3, 0xF7, 0x16, 0xFF, 0x63, 0x68, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x01, +0x00, 0x09, 0x60, 0x60, 0x63, 0x5B, 0x5B, 0x00, 0xE2, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x60, +0xA3, 0x7D, 0x5D, 0x4A, 0xD2, 0x78, 0x9B, 0x18, 0xA3, 0x75, 0x59, 0x4B, 0x9C, 0x46, 0x66, 0x44, 0xBE, 0x42, 0xDD, 0xD1, +0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x56, 0x4B, 0x1B, 0x68, 0x5B, 0x00, +0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x4E, 0x33, 0xA3, 0x62, 0x4C, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0x49, 0x4B, 0x00, 0x22, +0x1A, 0x70, 0x8B, 0xE7, 0xFD, 0xF7, 0x12, 0xF8, 0x00, 0x28, 0x04, 0xD1, 0x4D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x00, 0xD1, +0x11, 0xE1, 0x43, 0x46, 0x00, 0x2B, 0x2C, 0xD0, 0x4A, 0x4B, 0x23, 0x64, 0x04, 0x23, 0x63, 0x63, 0x08, 0x33, 0xA3, 0x62, +0x8C, 0xF7, 0x56, 0xF8, 0x00, 0x28, 0x00, 0xD0, 0x7C, 0xE7, 0x23, 0x6C, 0x23, 0x61, 0x20, 0x00, 0xFF, 0xF7, 0xAE, 0xFE, +0x53, 0x46, 0x00, 0x2B, 0x00, 0xD1, 0x95, 0xE1, 0xC0, 0x30, 0x00, 0x01, 0x00, 0x09, 0x60, 0x60, 0x18, 0x26, 0x4F, 0x46, +0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0x20, 0xFF, 0x63, 0x68, 0xAB, 0x42, 0x00, 0xD1, 0x4A, 0xE1, +0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x90, 0x2E, 0xEE, 0xD1, 0xB9, 0x46, 0x8B, 0xE7, 0x5B, 0x46, +0x00, 0x2B, 0x21, 0xD0, 0x33, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x23, 0x64, 0xE3, 0x6B, 0x63, 0x63, 0x23, 0x6B, 0xA3, 0x62, +0x03, 0x9B, 0x00, 0x2B, 0x05, 0xD0, 0x2F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0x46, 0x33, 0xA3, 0x62, 0xB2, 0x46, +0x00, 0x2E, 0x00, 0xD1, 0xD4, 0xE0, 0x05, 0x9A, 0x92, 0x46, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xCE, 0xE0, 0x28, 0x4B, +0x1B, 0x68, 0xA1, 0x6A, 0x8C, 0x46, 0x63, 0x44, 0xA3, 0x62, 0xC7, 0xE0, 0x15, 0x4B, 0x1B, 0x78, 0x5A, 0x00, 0x9B, 0x18, +0x5B, 0x00, 0xDB, 0xB2, 0x01, 0x2F, 0x49, 0xD9, 0x21, 0x4A, 0x22, 0x64, 0x1A, 0x22, 0x62, 0x63, 0x2C, 0x32, 0xA2, 0x62, +0x00, 0x2B, 0x03, 0xD0, 0x1E, 0x4B, 0x23, 0x64, 0x14, 0x23, 0x63, 0x63, 0x00, 0x2D, 0x03, 0xD0, 0x1C, 0x4B, 0x23, 0x64, +0x10, 0x23, 0x63, 0x63, 0x63, 0x6B, 0xA3, 0x62, 0xDA, 0x46, 0xA9, 0xE0, 0xF8, 0xE6, 0x10, 0x00, 0x00, 0xA0, 0xFF, 0xFF, +0x24, 0x27, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0x28, 0x27, 0x16, 0x00, 0x20, 0x27, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, +0xB1, 0xE6, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, +0xC4, 0x09, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x6A, 0x18, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, +0x04, 0xE2, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, 0xF9, 0x15, 0x00, 0x00, 0x08, 0xE2, 0x10, 0x00, 0xDC, 0x82, 0x00, 0x00, +0x14, 0xE2, 0x10, 0x00, 0xE8, 0x80, 0x00, 0x00, 0xF6, 0x54, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x85, 0x4A, 0x5A, 0x43, +0x03, 0x99, 0x00, 0x29, 0x33, 0xD0, 0x84, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x29, 0xD8, 0x8A, 0x1A, 0x22, 0x64, +0x28, 0x22, 0xD3, 0x1A, 0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x7F, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x4B, 0xD9, 0xDA, 0x46, +0x00, 0x2F, 0x5D, 0xD0, 0x07, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0xC4, 0xE0, 0x59, 0x68, 0x06, 0x9A, 0x00, 0x2A, 0x00, 0xD1, +0xC4, 0xE0, 0x78, 0x4B, 0x99, 0x42, 0x00, 0xD1, 0xBE, 0xE0, 0x52, 0x68, 0x53, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x20, +0x00, 0x05, 0x83, 0x42, 0x00, 0xD8, 0xBA, 0xE0, 0x8B, 0x1A, 0x1B, 0x01, 0x00, 0xD1, 0xB6, 0xE0, 0x11, 0x00, 0xB1, 0xE0, +0x6F, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xD5, 0xE7, 0x00, 0x2D, 0x0D, 0xD0, 0x6D, 0x4B, 0x23, 0x64, 0x10, 0x23, +0x63, 0x63, 0xA3, 0x62, 0x01, 0x2D, 0x02, 0xD0, 0x01, 0x23, 0x9A, 0x46, 0xD0, 0xE7, 0x40, 0x33, 0x01, 0x22, 0xE2, 0x54, +0xF8, 0xE7, 0x67, 0x49, 0x09, 0x68, 0x49, 0x00, 0x8A, 0x42, 0x0D, 0xD8, 0x8A, 0x1A, 0x22, 0x64, 0xA2, 0x6B, 0xD3, 0x1A, +0x63, 0x63, 0xE3, 0x6A, 0xA3, 0x62, 0x5D, 0x4B, 0x22, 0x6C, 0x9A, 0x42, 0x09, 0xD9, 0x03, 0x9B, 0x9A, 0x46, 0xB9, 0xE7, +0x5B, 0x4B, 0x23, 0x64, 0x1A, 0x23, 0x63, 0x63, 0xF1, 0xE7, 0x00, 0x2D, 0x05, 0xD1, 0x58, 0x4B, 0x23, 0x64, 0x1A, 0x23, +0x63, 0x63, 0xDA, 0x46, 0xAC, 0xE7, 0xDA, 0x46, 0xAA, 0xE7, 0x50, 0x4B, 0x23, 0x64, 0x02, 0x23, 0x63, 0x63, 0x43, 0x46, +0x00, 0x2B, 0x0B, 0xD1, 0x30, 0x33, 0xA3, 0x62, 0x2F, 0x3B, 0x9A, 0x46, 0x8B, 0xF7, 0x42, 0xFF, 0x00, 0x28, 0x00, 0xD0, +0x68, 0xE6, 0x21, 0x6C, 0x21, 0x61, 0x72, 0xE6, 0xC0, 0x23, 0xA3, 0x62, 0x05, 0x9B, 0x9A, 0x46, 0xDE, 0xE6, 0x00, 0x23, +0x08, 0x93, 0x09, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x08, 0xAA, 0x09, 0xA9, 0xFC, 0xF7, 0x72, 0xFD, 0x09, 0x9B, 0x00, 0x2B, +0x04, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x00, 0x2F, 0x07, 0xD0, 0x08, 0x9B, 0x5B, 0x00, +0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x63, 0x6B, 0x02, 0x2B, 0x1E, 0xD0, 0x53, 0x46, +0x00, 0x2B, 0x04, 0xD1, 0x3A, 0x4B, 0x08, 0x9A, 0x53, 0x43, 0x23, 0x61, 0x23, 0x64, 0x03, 0x26, 0x4F, 0x46, 0x65, 0x68, +0x00, 0x22, 0x21, 0x69, 0x38, 0x00, 0xFC, 0xF7, 0xEB, 0xFD, 0x63, 0x68, 0xAB, 0x42, 0x18, 0xD0, 0x08, 0x9B, 0x9C, 0x46, +0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0xB9, 0x46, 0x54, 0xE6, +0x08, 0x9A, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, +0xD5, 0xE7, 0xB9, 0x46, 0x47, 0xE6, 0xB9, 0x46, 0x45, 0xE6, 0x4E, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, +0x00, 0xD9, 0x63, 0xE6, 0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5F, 0xE6, 0x53, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x5B, 0xE6, +0x11, 0x33, 0xA3, 0x75, 0x58, 0xE6, 0x06, 0x9B, 0x00, 0x2B, 0x91, 0xD0, 0x06, 0x9B, 0x59, 0x68, 0x15, 0x4B, 0x99, 0x42, +0x8C, 0xD0, 0x63, 0x6B, 0x1A, 0x00, 0x28, 0x32, 0x52, 0x00, 0xA0, 0x6A, 0xC3, 0x1A, 0x5B, 0x00, 0x04, 0x98, 0x84, 0x46, +0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x9A, 0x42, 0x00, 0xD2, 0x7A, 0xE7, 0x0C, 0x4B, +0x23, 0x64, 0x77, 0xE7, 0x21, 0x6C, 0x21, 0x61, 0x43, 0x46, 0x00, 0x2B, 0x04, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x14, 0xFD, +0x60, 0x60, 0x6B, 0xE6, 0x05, 0x9B, 0x9A, 0x46, 0xE5, 0xE5, 0xC0, 0x46, 0xE2, 0x04, 0x00, 0x00, 0x00, 0xE2, 0x10, 0x00, +0xE7, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xE8, 0x80, 0x00, 0x00, 0xF2, 0x2B, 0x00, 0x00, 0x04, 0xE2, 0x10, 0x00, +0xA9, 0x03, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x1A, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x19, 0x4B, +0x9B, 0x78, 0x83, 0x75, 0xFC, 0xF7, 0x06, 0xFE, 0x05, 0x00, 0x02, 0x21, 0x01, 0x20, 0xFC, 0xF7, 0xC3, 0xFE, 0x06, 0x00, +0x00, 0x2D, 0x04, 0xD0, 0x11, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x4E, 0x23, 0xE3, 0x5C, 0x02, 0x2B, +0x0E, 0xD0, 0xA6, 0xF7, 0x83, 0xFE, 0x60, 0x64, 0xFF, 0xF7, 0x0C, 0xFD, 0x00, 0x2E, 0x0E, 0xD0, 0x00, 0x2D, 0x04, 0xD0, +0x08, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x70, 0xBD, 0x07, 0x4C, 0x20, 0x68, 0x7D, 0xF7, 0xB8, 0xFB, +0x00, 0x23, 0x23, 0x60, 0xEE, 0xE7, 0x02, 0x21, 0x00, 0x20, 0xFC, 0xF7, 0x9D, 0xFE, 0xEB, 0xE7, 0xFC, 0x00, 0x60, 0x40, +0x7C, 0x91, 0x0D, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x4E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x10, 0xBD, +0x00, 0x21, 0xD1, 0xF7, 0x8F, 0xFE, 0xFF, 0xF7, 0xE5, 0xFC, 0xF8, 0xE7, 0x10, 0xB5, 0xA6, 0xF7, 0x55, 0xFE, 0x22, 0x4B, +0x5A, 0x68, 0x92, 0x01, 0x1B, 0x68, 0xC0, 0x1A, 0x00, 0x01, 0x01, 0x09, 0x40, 0x00, 0x43, 0x1A, 0x9B, 0x00, 0x5B, 0x18, +0x99, 0x00, 0x5B, 0x18, 0x9A, 0x42, 0x20, 0xD3, 0xD3, 0x1A, 0x1B, 0x4C, 0x9C, 0x42, 0xA4, 0x41, 0x64, 0x42, 0x1A, 0x4B, +0x1A, 0x4A, 0x1A, 0x60, 0xD1, 0xF7, 0xC0, 0xFE, 0x00, 0x28, 0x0A, 0xD0, 0x00, 0x2C, 0x19, 0xD0, 0x17, 0x4B, 0x80, 0x22, +0x12, 0x05, 0x1A, 0x60, 0x16, 0x48, 0x7F, 0xF7, 0x05, 0xFB, 0x10, 0xBD, 0x00, 0x24, 0x11, 0x4B, 0x1B, 0x68, 0x9B, 0x68, +0x00, 0x2B, 0xF1, 0xD0, 0x12, 0x4A, 0xDB, 0x69, 0x93, 0x42, 0xEB, 0xD1, 0xEC, 0xE7, 0x0C, 0x4B, 0x0C, 0x4A, 0x1A, 0x60, +0xD1, 0xF7, 0xA4, 0xFE, 0x00, 0x28, 0xED, 0xD0, 0x0D, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x0D, 0x4B, 0x00, 0x22, 0x1A, 0x70, +0x0C, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xE2, 0xD0, 0xFF, 0xF7, 0xAE, 0xFF, 0xDF, 0xE7, 0xC0, 0x46, 0x6C, 0xE6, 0x10, 0x00, +0xFF, 0x70, 0x02, 0x00, 0x10, 0xE7, 0x10, 0x00, 0x64, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x74, 0xD1, 0x10, 0x00, +0xC9, 0x1F, 0x10, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0xF8, 0xB5, 0xDE, 0x46, +0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x49, 0x4B, 0x1C, 0x68, 0xA4, 0x04, +0xA4, 0x0E, 0x20, 0x00, 0x50, 0x43, 0x43, 0x01, 0x1B, 0x1A, 0x9B, 0x00, 0x1B, 0x18, 0x98, 0x00, 0x18, 0x18, 0x00, 0x02, +0xD3, 0xF7, 0x5E, 0xFC, 0x81, 0x46, 0x03, 0x0A, 0x9B, 0x46, 0x29, 0x00, 0x80, 0x20, 0xC0, 0x00, 0xD3, 0xF7, 0x56, 0xFC, +0x03, 0x00, 0x6B, 0x43, 0x9A, 0x46, 0xFF, 0x21, 0x4B, 0x46, 0x19, 0x40, 0x69, 0x43, 0x09, 0x0A, 0x48, 0x43, 0x53, 0x46, +0x1B, 0x1A, 0x98, 0x46, 0x23, 0x01, 0x1B, 0x19, 0x9B, 0x00, 0x99, 0x46, 0xA1, 0x44, 0x53, 0x46, 0x00, 0x2B, 0x05, 0xD1, +0x34, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x78, 0x01, 0xC0, 0x1B, 0x80, 0x00, 0xC7, 0x19, +0xB8, 0x00, 0x38, 0x18, 0x29, 0x00, 0xD3, 0xF7, 0x33, 0xFC, 0x44, 0x43, 0x27, 0x00, 0x65, 0x09, 0x73, 0x01, 0x2C, 0x4A, +0x9A, 0x18, 0x11, 0x68, 0x2B, 0x4A, 0x11, 0x60, 0x2B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, +0x2A, 0x4B, 0x5A, 0x46, 0x1A, 0x60, 0x51, 0x46, 0x48, 0x46, 0xD3, 0xF7, 0xA3, 0xFC, 0x09, 0x05, 0x43, 0x46, 0x19, 0x43, +0x26, 0x4B, 0x19, 0x60, 0x26, 0x4B, 0x52, 0x46, 0x1A, 0x60, 0x26, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x25, 0x4B, 0x9E, 0x22, +0xFF, 0x32, 0x99, 0x5C, 0x09, 0x02, 0x01, 0x3A, 0x9A, 0x5C, 0x0A, 0x43, 0x12, 0x04, 0x9C, 0x21, 0xFF, 0x31, 0x58, 0x5C, +0x00, 0x02, 0x01, 0x39, 0x59, 0x5C, 0x01, 0x43, 0x0A, 0x43, 0x1E, 0x49, 0x0A, 0x60, 0xA0, 0x22, 0xFF, 0x32, 0x98, 0x5C, +0x00, 0x02, 0x01, 0x3A, 0x9C, 0x5C, 0x04, 0x43, 0x24, 0x04, 0x20, 0x00, 0x28, 0x43, 0x01, 0x35, 0x6D, 0x01, 0xEC, 0x1B, +0x24, 0x04, 0x04, 0x43, 0x16, 0x4A, 0x14, 0x60, 0x9A, 0x22, 0xFF, 0x32, 0x98, 0x5C, 0x00, 0x02, 0x01, 0x3A, 0x9B, 0x5C, +0x03, 0x43, 0x36, 0x02, 0x1E, 0x43, 0x01, 0x20, 0x06, 0x43, 0x11, 0x4B, 0x1E, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, 0xC0, 0x46, 0x08, 0x04, 0x60, 0x40, 0x28, 0x19, 0x16, 0x00, 0xDC, 0x05, 0x60, 0x40, +0x5C, 0x06, 0x60, 0x40, 0xD8, 0x05, 0x60, 0x40, 0x60, 0x06, 0x60, 0x40, 0x50, 0x06, 0x60, 0x40, 0x54, 0x06, 0x60, 0x40, +0x58, 0x06, 0x60, 0x40, 0x4C, 0x06, 0x60, 0x40, 0x20, 0xA3, 0x16, 0x00, 0x44, 0x06, 0x60, 0x40, 0x48, 0x06, 0x60, 0x40, +0x40, 0x06, 0x60, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8F, 0xB0, 0x80, 0x46, +0x0E, 0x00, 0x15, 0x00, 0x03, 0x93, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x17, 0x00, 0x1F, 0x40, 0x1A, 0x42, 0x00, 0xD0, +0xF6, 0xE2, 0x72, 0xB6, 0x00, 0x21, 0x5C, 0x20, 0x7D, 0xF7, 0xCE, 0xF9, 0x04, 0x1E, 0x00, 0xD1, 0x25, 0xE3, 0x00, 0x20, +0x00, 0x2F, 0x00, 0xD0, 0xF1, 0xE2, 0x62, 0xB6, 0x00, 0x28, 0x00, 0xD1, 0xED, 0xE2, 0x0F, 0xB0, 0x3C, 0xBC, 0x90, 0x46, +0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xDE, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x0C, 0x20, 0x00, 0x2F, 0xEF, 0xD1, 0xEA, 0xE7, 0x00, 0x23, 0x06, 0x93, 0xEC, 0xE2, 0x01, 0x23, 0x06, 0x93, 0xE9, 0xE2, +0x00, 0x23, 0x5B, 0x00, 0xD6, 0x4A, 0xD3, 0x18, 0x5F, 0x78, 0xBA, 0x46, 0xBF, 0xE0, 0x2F, 0x7B, 0xD4, 0x4B, 0x19, 0x00, +0x00, 0x22, 0x08, 0x78, 0xB8, 0x42, 0x00, 0xD1, 0xAD, 0xE0, 0x01, 0x32, 0x02, 0x31, 0x08, 0x2A, 0xF7, 0xD1, 0x02, 0x27, +0x68, 0x7B, 0x00, 0x22, 0x19, 0x78, 0x81, 0x42, 0x00, 0xD1, 0xA7, 0xE0, 0x01, 0x32, 0x02, 0x33, 0x08, 0x2A, 0xF7, 0xD1, +0x02, 0x23, 0x9A, 0x46, 0x09, 0x2F, 0x05, 0xD9, 0xC5, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x07, 0x97, 0xD3, 0x46, 0xC4, 0x4A, 0x7B, 0x00, 0xDF, 0x19, 0xD7, 0x19, 0x53, 0x46, 0x5B, 0x00, 0x53, 0x44, 0xD2, 0x18, +0xBF, 0x78, 0x93, 0x78, 0xFF, 0x18, 0xFB, 0xB2, 0x1F, 0x00, 0x05, 0x93, 0x28, 0x7C, 0x19, 0x00, 0xD3, 0xF7, 0x48, 0xFB, +0xC0, 0xB2, 0xBC, 0x4B, 0x63, 0x62, 0xBC, 0x4B, 0xE3, 0x61, 0xBC, 0x4B, 0x23, 0x62, 0x03, 0x23, 0x23, 0x76, 0xBB, 0x4B, +0x9B, 0x7A, 0xA3, 0x75, 0xBA, 0x4A, 0x9F, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x00, 0x23, 0x00, 0x2A, 0x02, 0xD1, 0x7B, 0x00, +0x03, 0x33, 0xDB, 0xB2, 0xE3, 0x75, 0x00, 0x23, 0xA3, 0x82, 0x06, 0x33, 0x63, 0x76, 0x40, 0x33, 0x42, 0x46, 0xE2, 0x54, +0x01, 0x33, 0xE6, 0x54, 0xEB, 0x88, 0x23, 0x87, 0x2B, 0x89, 0x63, 0x87, 0xAA, 0x7A, 0x3D, 0x23, 0xE2, 0x54, 0xEA, 0x7A, +0x01, 0x33, 0xE2, 0x54, 0x2A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0xAA, 0x7B, 0x01, 0x33, +0xE2, 0x54, 0xEA, 0x7B, 0x01, 0x33, 0xE2, 0x54, 0x6A, 0x7C, 0x01, 0x33, 0xE2, 0x54, 0x01, 0x33, 0xE0, 0x54, 0x9B, 0x4A, +0xB0, 0x33, 0xD3, 0x58, 0x23, 0x63, 0xAA, 0x78, 0x4B, 0x23, 0xE2, 0x54, 0x2B, 0x7C, 0x05, 0x99, 0x8C, 0x46, 0x63, 0x44, +0xEA, 0x7B, 0x9B, 0x1A, 0x5A, 0x42, 0x53, 0x41, 0x49, 0x22, 0xA3, 0x54, 0x45, 0x23, 0xE1, 0x54, 0x13, 0x33, 0x08, 0x9A, +0xE2, 0x54, 0x01, 0x22, 0x31, 0x00, 0x01, 0x20, 0xA6, 0xF7, 0xF8, 0xF9, 0x03, 0x9B, 0x00, 0x2B, 0x00, 0xD0, 0x98, 0xE1, +0x06, 0x99, 0x01, 0x31, 0x2A, 0x89, 0x4A, 0x43, 0xD3, 0xB2, 0x0C, 0x93, 0xEB, 0x88, 0x4B, 0x43, 0xDB, 0xB2, 0x0D, 0x93, +0x2B, 0x79, 0x00, 0x22, 0x92, 0x46, 0x00, 0x2B, 0x02, 0xD0, 0xEA, 0x78, 0x04, 0x2A, 0x26, 0xD0, 0x68, 0x78, 0x03, 0x28, +0x33, 0xD8, 0x2B, 0x78, 0x04, 0x2B, 0x30, 0xD8, 0x9B, 0x00, 0x88, 0x4A, 0xD3, 0x18, 0x1A, 0x5C, 0x0F, 0x23, 0x13, 0x40, +0x0A, 0x93, 0x53, 0x11, 0x01, 0x21, 0x0B, 0x40, 0x03, 0x93, 0x12, 0x11, 0x11, 0x40, 0x0B, 0x91, 0x2C, 0xE0, 0x52, 0x00, +0x79, 0x49, 0x8A, 0x18, 0x57, 0x78, 0x51, 0xE7, 0x52, 0x00, 0x77, 0x4B, 0x9A, 0x18, 0x53, 0x78, 0x9A, 0x46, 0x09, 0x2F, +0x00, 0xD9, 0x57, 0xE7, 0x53, 0x46, 0x09, 0x2B, 0x00, 0xD9, 0x53, 0xE7, 0x58, 0xE7, 0x01, 0x2B, 0x0A, 0xD0, 0x02, 0x3B, +0x5A, 0x42, 0x53, 0x41, 0x5B, 0x42, 0x76, 0x4A, 0x13, 0x40, 0x9A, 0x46, 0x75, 0x4B, 0x9C, 0x46, 0xE2, 0x44, 0xCB, 0xE7, +0x74, 0x4B, 0x9A, 0x46, 0xC8, 0xE7, 0x29, 0x78, 0x66, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0xC0, 0x47, +0x03, 0x9B, 0x0B, 0x93, 0x00, 0x23, 0x0A, 0x93, 0x2B, 0x79, 0x0E, 0x2B, 0x00, 0xD1, 0xBC, 0xE0, 0x00, 0xD9, 0xAC, 0xE0, +0x00, 0x22, 0x06, 0x92, 0x08, 0x2B, 0x04, 0xD0, 0x01, 0x32, 0x06, 0x92, 0x0D, 0x2B, 0x00, 0xD0, 0xA8, 0xE0, 0xEB, 0x78, +0x5A, 0x1E, 0x03, 0x2A, 0x00, 0xD9, 0xE3, 0xE0, 0xD3, 0xB2, 0x08, 0x93, 0x63, 0x4A, 0x13, 0x68, 0x63, 0x49, 0x19, 0x40, +0x80, 0x23, 0x9B, 0x02, 0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0x61, 0x49, 0x0B, 0x40, 0x80, 0x21, 0x49, 0x02, 0x8C, 0x46, +0x0B, 0x43, 0x13, 0x60, 0x73, 0x01, 0x98, 0x46, 0x5D, 0x4A, 0x42, 0x44, 0x85, 0x23, 0x1B, 0x04, 0x51, 0x46, 0x0B, 0x43, +0x13, 0x60, 0x5B, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x4B, 0x4A, 0x5B, 0x46, 0x59, 0x00, 0x59, 0x44, 0x53, 0x18, 0x5B, 0x78, +0x1B, 0x01, 0xA8, 0x7A, 0x03, 0x43, 0xE8, 0x7A, 0x02, 0x38, 0x07, 0x00, 0x78, 0x42, 0x78, 0x41, 0xC0, 0x00, 0x03, 0x43, +0x07, 0x9F, 0x78, 0x00, 0xBB, 0x46, 0x58, 0x44, 0x17, 0x18, 0x7F, 0x78, 0x7F, 0x01, 0x3B, 0x43, 0x67, 0x46, 0x3B, 0x43, +0x57, 0x46, 0x3B, 0x60, 0x4C, 0x4B, 0x43, 0x44, 0x9A, 0x46, 0x2B, 0x89, 0x1B, 0x05, 0x9C, 0x46, 0xEB, 0x88, 0x1B, 0x01, +0x67, 0x46, 0x3B, 0x43, 0x80, 0x5C, 0x03, 0x43, 0x88, 0x5C, 0x00, 0x04, 0x03, 0x43, 0x52, 0x46, 0x13, 0x60, 0x03, 0x9B, +0xDB, 0x03, 0x0A, 0x9A, 0x12, 0x02, 0x13, 0x43, 0x0B, 0x9A, 0xD2, 0x01, 0x13, 0x43, 0x06, 0x9A, 0x12, 0x05, 0x13, 0x43, +0x08, 0x9A, 0x12, 0x04, 0x13, 0x43, 0x3E, 0x4A, 0xB2, 0x18, 0x92, 0x00, 0x13, 0x60, 0xB3, 0x00, 0x3C, 0x4A, 0x9C, 0x50, +0x4B, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x87, 0xE0, 0x32, 0x01, 0xB2, 0x18, 0xD3, 0x01, 0x9B, 0x1A, 0xF3, 0x18, +0x37, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x9B, 0xB2, 0x36, 0x49, 0x41, 0x44, 0x0C, 0x98, 0xC2, 0x18, 0x12, 0x04, 0x13, 0x43, +0x0B, 0x60, 0x87, 0x23, 0xDB, 0x00, 0x73, 0x43, 0x84, 0x46, 0x63, 0x44, 0x31, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x5B, 0x00, +0x9B, 0xB2, 0x30, 0x49, 0x41, 0x44, 0x0D, 0x9A, 0x9A, 0x18, 0x92, 0xB2, 0x1B, 0x04, 0x13, 0x43, 0x0B, 0x60, 0x2D, 0x4B, +0x43, 0x44, 0xE9, 0x7B, 0x80, 0x22, 0xD2, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x29, 0x89, 0x00, 0x29, 0x04, 0xD1, 0xEB, 0x88, +0x01, 0x31, 0x00, 0x2B, 0x00, 0xD0, 0x19, 0x00, 0x00, 0x2E, 0x00, 0xD0, 0xDA, 0xE0, 0xEA, 0x7B, 0x89, 0xB2, 0x00, 0x20, +0xFF, 0xF7, 0x72, 0xFD, 0xD4, 0xE0, 0x03, 0x22, 0x06, 0x92, 0x10, 0x2B, 0x00, 0xD1, 0x56, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, +0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x06, 0x93, 0x4D, 0xE7, 0x02, 0x23, 0x06, 0x93, 0x4A, 0xE7, +0x28, 0x19, 0x16, 0x00, 0xE4, 0xDF, 0x10, 0x00, 0xD4, 0xDF, 0x10, 0x00, 0xE8, 0xDF, 0x10, 0x00, 0x69, 0xF5, 0x0A, 0x00, +0x21, 0x61, 0x10, 0x00, 0x4D, 0xF3, 0x0A, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0x08, 0xE0, 0x10, 0x00, +0x00, 0xA0, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0xFD, 0xFF, +0xFF, 0xFF, 0xFE, 0xFF, 0xD4, 0x05, 0x60, 0x40, 0xE0, 0x05, 0x60, 0x40, 0xE4, 0x05, 0x60, 0x40, 0x8C, 0x01, 0x18, 0x10, +0x54, 0x27, 0x16, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, 0xD8, 0x05, 0x60, 0x40, 0xAE, 0x55, 0x00, 0x00, 0xDC, 0x05, 0x60, 0x40, +0xD0, 0x05, 0x60, 0x40, 0x96, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, 0x08, 0x93, +0x14, 0xE7, 0x42, 0x33, 0xE3, 0x5C, 0x5F, 0x1E, 0x20, 0x00, 0x50, 0x30, 0x7F, 0xF7, 0xF0, 0xFA, 0x49, 0x23, 0xE1, 0x5C, +0xCB, 0x1C, 0xDB, 0xB2, 0x04, 0x31, 0xC9, 0xB2, 0x8B, 0x4A, 0x92, 0x46, 0x0D, 0x9A, 0x04, 0x32, 0xD2, 0xB2, 0x00, 0x92, +0x84, 0x22, 0x50, 0x46, 0x82, 0x58, 0x93, 0x46, 0x0C, 0x9A, 0x30, 0x00, 0xD8, 0x47, 0x86, 0x4A, 0x42, 0x44, 0x00, 0x23, +0x13, 0x60, 0x85, 0x4A, 0x42, 0x44, 0x13, 0x60, 0x19, 0x33, 0xFF, 0x33, 0x52, 0x46, 0xD0, 0x58, 0x31, 0x00, 0xD2, 0xF7, +0x47, 0xFB, 0x81, 0x4A, 0x11, 0x68, 0x80, 0x23, 0x9B, 0x01, 0xB3, 0x40, 0x0B, 0x43, 0x13, 0x60, 0x7E, 0x4A, 0x42, 0x44, +0xFF, 0x23, 0x3B, 0x40, 0x1F, 0x2B, 0x00, 0xD9, 0x1F, 0x23, 0x1B, 0x02, 0xE9, 0x7B, 0x0B, 0x43, 0x09, 0x99, 0x03, 0x39, +0x48, 0x42, 0x41, 0x41, 0xC9, 0x03, 0x0B, 0x43, 0xC0, 0x21, 0xC9, 0x01, 0x0B, 0x43, 0x13, 0x60, 0x42, 0xE0, 0x75, 0x4B, +0xF2, 0x18, 0x52, 0x01, 0x74, 0x49, 0x5B, 0x46, 0x58, 0x00, 0x58, 0x44, 0x0B, 0x18, 0x5B, 0x78, 0x1B, 0x01, 0xAF, 0x7A, +0x1F, 0x43, 0xBC, 0x46, 0xEB, 0x7A, 0x02, 0x3B, 0x1F, 0x00, 0x7B, 0x42, 0x7B, 0x41, 0xDB, 0x00, 0x67, 0x46, 0x3B, 0x43, +0x9A, 0x46, 0x07, 0x9F, 0x7B, 0x00, 0x98, 0x46, 0xBC, 0x46, 0xE0, 0x44, 0x8C, 0x46, 0xC4, 0x44, 0x63, 0x46, 0x5B, 0x78, +0x5B, 0x01, 0x1F, 0x00, 0x53, 0x46, 0x1F, 0x43, 0x80, 0x23, 0x5B, 0x02, 0x3B, 0x43, 0x13, 0x60, 0x2B, 0x89, 0x1B, 0x05, +0xED, 0x88, 0x2D, 0x01, 0x2B, 0x43, 0x45, 0x46, 0x6D, 0x5C, 0x2B, 0x43, 0x41, 0x5C, 0x09, 0x04, 0x0B, 0x43, 0x53, 0x60, +0x31, 0x01, 0x71, 0x18, 0xCB, 0x01, 0x5B, 0x1A, 0xF3, 0x18, 0x5B, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x98, 0xB2, 0x11, 0x00, +0x08, 0x39, 0x1B, 0x04, 0x03, 0x43, 0x0B, 0x60, 0x04, 0x3A, 0x13, 0x60, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, +0x19, 0x40, 0x88, 0x46, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x52, 0x4B, 0x05, 0x9A, 0x53, 0x43, 0x9B, 0xB2, 0x42, 0x22, +0xA2, 0x5C, 0x52, 0x00, 0x44, 0x21, 0x61, 0x5C, 0x48, 0x1E, 0x81, 0x41, 0x00, 0x91, 0x31, 0x00, 0x0B, 0x20, 0xD3, 0xF7, +0x41, 0xF8, 0x4B, 0x46, 0xDB, 0x07, 0x33, 0xD4, 0x4B, 0x46, 0x1F, 0x01, 0x3F, 0x09, 0x41, 0x23, 0xE5, 0x5C, 0x02, 0x33, +0xE3, 0x5C, 0x9B, 0x06, 0x7F, 0x08, 0x5F, 0x40, 0x42, 0x23, 0xE3, 0x5C, 0x99, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x39, 0x4B, +0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x49, 0x46, 0x38, 0x00, 0xD3, 0xF7, 0x63, 0xF9, 0x69, 0x1A, +0x00, 0x29, 0x21, 0xDD, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x1A, 0x49, 0x00, 0x58, 0x00, 0x04, 0x9A, 0x94, 0x46, 0x60, 0x44, +0x09, 0x18, 0x09, 0x01, 0x09, 0x09, 0x61, 0x63, 0x02, 0x2B, 0x02, 0xD9, 0x30, 0x00, 0x34, 0x4B, 0x98, 0x47, 0x00, 0x20, +0x43, 0x46, 0x00, 0x2B, 0x00, 0xD0, 0x28, 0xE5, 0x62, 0xB6, 0x26, 0xE5, 0x30, 0x4F, 0x4B, 0x46, 0x3B, 0x40, 0x1F, 0x00, +0x04, 0x98, 0x01, 0x38, 0x00, 0x01, 0x03, 0x09, 0x04, 0x93, 0xC4, 0xE7, 0x42, 0x23, 0xE3, 0x5C, 0xC9, 0x18, 0xD9, 0xE7, +0x00, 0x21, 0x5C, 0x20, 0x7C, 0xF7, 0xD8, 0xFE, 0x04, 0x1E, 0x00, 0xD1, 0x18, 0xE5, 0x43, 0x46, 0x9B, 0x00, 0x26, 0x4A, +0x9F, 0x58, 0x6B, 0x78, 0x09, 0x93, 0x03, 0x2B, 0x00, 0xD1, 0x19, 0xE5, 0xAB, 0x78, 0x01, 0x2B, 0x00, 0xD1, 0x18, 0xE5, +0x2A, 0x79, 0x08, 0x23, 0x93, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x93, 0x06, 0x9B, 0x08, 0x93, 0xA6, 0xF7, 0x1C, 0xFA, +0x04, 0x90, 0xBB, 0x6F, 0x81, 0x46, 0x99, 0x44, 0x5C, 0x22, 0x00, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0x67, 0xFE, 0xEB, 0x7A, +0x00, 0x2B, 0x00, 0xD0, 0x0B, 0xE5, 0x2B, 0x7B, 0x00, 0x2B, 0x00, 0xD1, 0x00, 0xE5, 0x02, 0x22, 0x92, 0x46, 0x02, 0x27, +0x02, 0x2B, 0x00, 0xD0, 0x22, 0xE5, 0x01, 0x3B, 0xF9, 0xE4, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, +0x98, 0x47, 0x0C, 0x20, 0xD5, 0xE4, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xD8, 0x05, 0x60, 0x40, 0xDC, 0x05, 0x60, 0x40, +0x0C, 0x04, 0x60, 0x40, 0xD0, 0x05, 0x60, 0x40, 0x2F, 0x00, 0x03, 0x02, 0xE8, 0xDF, 0x10, 0x00, 0x5C, 0xAB, 0xFF, 0xFF, +0xE2, 0x04, 0x00, 0x00, 0x3D, 0xF4, 0x0A, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0x38, 0x27, 0x16, 0x00, 0x00, 0x20, 0x70, 0x47, +0x10, 0xB5, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x5A, 0x4B, +0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x58, 0x49, 0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, +0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xDB, 0x53, 0x4B, 0x1B, 0x68, 0xDB, 0x05, 0x0B, 0xD5, 0x51, 0x49, +0x0B, 0x68, 0x5B, 0x00, 0x5B, 0x08, 0x80, 0x22, 0x12, 0x06, 0x13, 0x43, 0x0B, 0x60, 0x0A, 0x00, 0x13, 0x68, 0x00, 0x2B, +0xFC, 0xDB, 0x7A, 0xF7, 0x4F, 0xFF, 0x4B, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0x7C, 0xF7, 0xF5, 0xFE, 0x48, 0x4B, +0x00, 0x22, 0x1A, 0x60, 0x47, 0x4A, 0x13, 0x68, 0x04, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x46, 0x4B, 0x11, 0x22, 0x44, 0x21, +0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x10, 0x3A, +0x40, 0x49, 0x5A, 0x54, 0x40, 0x49, 0x5A, 0x54, 0x40, 0x4A, 0x00, 0x21, 0x99, 0x54, 0x40, 0x4B, 0x1B, 0x68, 0x01, 0x2B, +0x47, 0xD9, 0x39, 0x4B, 0x1A, 0x68, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x20, 0x82, 0x43, 0x1A, 0x60, +0x1A, 0x68, 0x06, 0x39, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x38, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, +0x12, 0x0C, 0xB0, 0x21, 0x49, 0x03, 0x0A, 0x43, 0x1A, 0x60, 0x34, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD0, 0x54, 0x29, 0x4A, +0x13, 0x68, 0x0F, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x30, 0x4A, 0x13, 0x68, 0x30, 0x49, 0x19, 0x40, 0xA0, 0x23, 0xDB, 0x03, +0x0B, 0x43, 0x13, 0x60, 0x13, 0x68, 0xFF, 0x21, 0x8B, 0x43, 0xAF, 0x39, 0x0B, 0x43, 0x13, 0x60, 0x2B, 0x4B, 0x2C, 0x4A, +0x9A, 0x60, 0x2C, 0x4A, 0xDA, 0x60, 0x2C, 0x4A, 0x5A, 0x61, 0x2C, 0x4A, 0x9A, 0x61, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, +0x00, 0x23, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x2A, 0x4A, 0x13, 0x60, 0x0A, 0x22, 0x29, 0x49, 0x2A, 0x48, +0xD3, 0xF7, 0x10, 0xFC, 0x10, 0xBD, 0x15, 0x4B, 0x1A, 0x68, 0x08, 0x31, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x07, 0x39, +0x8A, 0x43, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x02, 0x20, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x13, 0x48, 0x10, 0x40, +0x80, 0x22, 0x92, 0x01, 0x02, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x12, 0x04, 0x12, 0x0C, 0xB0, 0x20, 0x40, 0x03, 0x02, 0x43, +0x1A, 0x60, 0x0E, 0x4A, 0xA0, 0x23, 0x9B, 0x00, 0xD1, 0x54, 0x19, 0x4B, 0x19, 0x4A, 0x1A, 0x60, 0xAF, 0xE7, 0xC0, 0x46, +0x00, 0x04, 0x60, 0x40, 0x00, 0x08, 0x60, 0x40, 0xF8, 0xE6, 0x10, 0x00, 0xFC, 0x00, 0x60, 0x40, 0xEC, 0xA4, 0x16, 0x00, +0x1E, 0x03, 0x00, 0x00, 0x6F, 0x04, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xFF, 0xDF, 0xFF, 0xFF, +0x7C, 0x1E, 0x16, 0x00, 0x8C, 0x04, 0x60, 0x40, 0xFF, 0xFF, 0x00, 0xFF, 0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, +0x81, 0x01, 0x10, 0x00, 0x8D, 0x05, 0x10, 0x00, 0xB9, 0x00, 0x10, 0x00, 0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, +0x54, 0xE6, 0x10, 0x00, 0xD8, 0xE1, 0x10, 0x00, 0xC0, 0x9F, 0x16, 0x00, 0x30, 0x10, 0x62, 0x40, 0x15, 0x1C, 0x20, 0x00, +0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x70, 0x4B, 0x1B, 0x68, 0x1B, 0x07, 0x0B, 0xD5, +0x6F, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x6C, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0x6B, 0x4B, +0x01, 0x22, 0x1A, 0x60, 0x6A, 0x4C, 0x23, 0x68, 0x6A, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6A, 0x4D, 0x2B, 0x68, 0x6A, 0x4F, +0x3B, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xEE, 0xFA, 0x23, 0x68, 0x68, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x33, 0x40, +0x2B, 0x60, 0x23, 0x68, 0x1F, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x3B, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, +0x9B, 0x00, 0x33, 0x43, 0x23, 0x60, 0x60, 0x4B, 0x99, 0x46, 0xFF, 0x23, 0x9B, 0x46, 0x22, 0x00, 0xC0, 0x3B, 0x98, 0x46, +0x5D, 0x4B, 0x9C, 0x46, 0x40, 0x25, 0x80, 0x21, 0x09, 0x01, 0x5F, 0x46, 0x5E, 0x46, 0x04, 0x36, 0xF3, 0xB2, 0x9B, 0x46, +0x4C, 0x46, 0x18, 0x00, 0x13, 0x68, 0x46, 0x46, 0xB3, 0x43, 0x03, 0x43, 0x13, 0x60, 0x63, 0x46, 0x26, 0x68, 0x1E, 0x60, +0x13, 0x68, 0xAB, 0x43, 0x2B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, +0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0xB8, 0x42, 0xE7, 0xD1, 0x10, 0x23, 0x9A, 0x46, 0xD1, 0x44, 0x5B, 0x46, +0x0F, 0x2B, 0xDA, 0xD1, 0x42, 0x4C, 0x23, 0x68, 0x44, 0x4D, 0x2B, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xAA, 0xFA, 0x23, 0x68, +0x3F, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x3F, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x15, 0x40, +0x80, 0x22, 0x52, 0x00, 0x2A, 0x43, 0x1A, 0x60, 0x3E, 0x4B, 0x9A, 0x46, 0xFF, 0x24, 0x38, 0x4A, 0x1F, 0x23, 0x99, 0x46, +0x3C, 0x4B, 0x98, 0x46, 0x20, 0x26, 0x80, 0x21, 0xC9, 0x00, 0x04, 0xE0, 0x08, 0x23, 0x9C, 0x46, 0xE2, 0x44, 0x1F, 0x2C, +0x1D, 0xD0, 0xA4, 0x46, 0x02, 0x34, 0xE4, 0xB2, 0x55, 0x46, 0x20, 0x00, 0x13, 0x68, 0x4F, 0x46, 0xBB, 0x43, 0x03, 0x43, +0x13, 0x60, 0x43, 0x46, 0x2F, 0x68, 0x1F, 0x60, 0x13, 0x68, 0xB3, 0x43, 0x33, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, +0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x38, 0xC0, 0xB2, 0x04, 0x35, 0x60, 0x45, 0xE7, 0xD1, +0xDC, 0xE7, 0x22, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x65, 0xFA, 0x23, 0x68, 0x1F, 0x4D, +0x2B, 0x40, 0x23, 0x60, 0x23, 0x49, 0x0B, 0x68, 0x23, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x5B, 0x02, 0x13, 0x43, 0x0B, 0x60, +0x83, 0xF7, 0x50, 0xFA, 0x15, 0x49, 0x0B, 0x68, 0x18, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, +0x0B, 0x68, 0x12, 0x48, 0x03, 0x40, 0x80, 0x22, 0x92, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x23, 0x68, 0x03, 0x40, 0x1A, 0x43, +0x22, 0x60, 0x23, 0x68, 0x1D, 0x40, 0x80, 0x23, 0x5B, 0x00, 0x2B, 0x43, 0x23, 0x60, 0x14, 0x49, 0x0B, 0x68, 0x14, 0x4A, +0x1A, 0x40, 0x80, 0x23, 0x5B, 0x03, 0x13, 0x43, 0x0B, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, +0xF8, 0xBD, 0xC0, 0x46, 0x18, 0x00, 0x58, 0x40, 0x40, 0x42, 0x04, 0x40, 0x58, 0x20, 0x62, 0x40, 0xFF, 0xFD, 0xFF, 0xFF, +0x64, 0x20, 0x62, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x97, 0x16, 0x00, 0x5C, 0x20, 0x62, 0x40, +0xD8, 0x98, 0x16, 0x00, 0x68, 0x20, 0x62, 0x40, 0x4C, 0x20, 0x62, 0x40, 0xFF, 0xFF, 0xFE, 0xFF, 0x30, 0x20, 0x62, 0x40, +0xFF, 0xFF, 0xEF, 0xFF, 0xF8, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x6E, 0x4C, 0x23, 0x68, +0x6E, 0x4E, 0x33, 0x40, 0x23, 0x60, 0x6E, 0x4D, 0x2B, 0x68, 0x6E, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x83, 0xF7, 0xF8, 0xF9, +0x23, 0x68, 0x6C, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x2B, 0x68, 0x6B, 0x4A, 0x13, 0x40, 0x2B, 0x60, 0x23, 0x68, 0x6A, 0x4A, +0x1A, 0x40, 0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x23, 0x60, 0x23, 0x68, 0x1E, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x33, 0x43, +0x23, 0x60, 0x65, 0x4B, 0x9A, 0x46, 0x7F, 0x25, 0x22, 0x00, 0xFF, 0x23, 0x99, 0x46, 0x63, 0x4B, 0x98, 0x46, 0x5D, 0x4B, +0x9C, 0x46, 0x80, 0x21, 0x89, 0x01, 0x2E, 0x00, 0x04, 0x35, 0xED, 0xB2, 0x54, 0x46, 0x28, 0x00, 0x13, 0x68, 0x4F, 0x46, +0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x43, 0x46, 0x27, 0x68, 0x1F, 0x60, 0x13, 0x68, 0x67, 0x46, 0x3B, 0x40, 0x80, 0x27, +0x7F, 0x00, 0x3B, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, +0x01, 0x38, 0xC0, 0xB2, 0x04, 0x34, 0x86, 0x42, 0xE4, 0xD1, 0x10, 0x23, 0x9B, 0x46, 0xDA, 0x44, 0x8F, 0x2D, 0xDA, 0xD1, +0x45, 0x4C, 0x23, 0x68, 0x4A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x83, 0xF7, 0xB2, 0xF9, 0x23, 0x68, 0x42, 0x4A, 0x13, 0x40, +0x23, 0x60, 0x42, 0x4B, 0x1A, 0x68, 0x80, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x40, 0x49, 0x11, 0x40, 0x80, 0x22, +0x52, 0x00, 0x0A, 0x43, 0x1A, 0x60, 0x10, 0x20, 0x1A, 0x00, 0x1F, 0x27, 0x41, 0x4E, 0x42, 0x4D, 0x20, 0x24, 0x80, 0x21, +0xC9, 0x00, 0x13, 0x68, 0xBB, 0x43, 0x03, 0x43, 0x13, 0x60, 0x83, 0x00, 0xF3, 0x58, 0x2B, 0x60, 0x13, 0x68, 0xA3, 0x43, +0x23, 0x43, 0x13, 0x60, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0xC0, 0x46, 0x13, 0x68, 0x0B, 0x42, 0xFC, 0xD0, 0x01, 0x30, +0x20, 0x28, 0xEA, 0xD1, 0x2D, 0x4C, 0x23, 0x68, 0x80, 0x22, 0x93, 0x43, 0x23, 0x60, 0x83, 0xF7, 0x7E, 0xF9, 0x23, 0x68, +0x2A, 0x4A, 0x13, 0x40, 0x23, 0x60, 0x31, 0x4A, 0x13, 0x68, 0x00, 0x2B, 0xFC, 0xD0, 0x30, 0x4A, 0x13, 0x68, 0x02, 0x21, +0x8B, 0x43, 0x13, 0x60, 0x2C, 0x4B, 0x01, 0x22, 0x1A, 0x60, 0x2D, 0x4A, 0x13, 0x68, 0x2D, 0x49, 0x0B, 0x40, 0x13, 0x60, +0x2C, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x83, 0xF7, 0x5D, 0xF9, 0x1B, 0x49, 0x0B, 0x68, 0x1E, 0x4A, 0x13, 0x40, 0x80, 0x22, +0x52, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x0B, 0x68, 0x17, 0x48, 0x18, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x03, 0x43, 0x0B, 0x60, +0x15, 0x4B, 0x19, 0x68, 0x17, 0x48, 0x08, 0x40, 0x80, 0x21, 0x89, 0x00, 0x01, 0x43, 0x19, 0x60, 0x19, 0x68, 0x12, 0x48, +0x08, 0x40, 0x80, 0x21, 0x49, 0x00, 0x01, 0x43, 0x19, 0x60, 0x1C, 0x4B, 0x19, 0x68, 0x0A, 0x43, 0x1A, 0x60, 0x1B, 0x4A, +0x13, 0x68, 0x1B, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x1A, 0x4B, 0x1A, 0x68, 0x1A, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x19, 0x68, +0x80, 0x22, 0xD2, 0x05, 0x0A, 0x43, 0x1A, 0x60, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF8, 0xBD, +0x60, 0x40, 0x34, 0x40, 0xFF, 0xF7, 0xFF, 0xFF, 0x6C, 0x40, 0x34, 0x40, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, +0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xD8, 0x9B, 0x16, 0x00, 0x64, 0x40, 0x34, 0x40, 0x58, 0x99, 0x16, 0x00, +0x70, 0x40, 0x34, 0x40, 0x40, 0x42, 0x04, 0x40, 0x18, 0x00, 0x58, 0x40, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xFF, 0xFB, +0x08, 0x40, 0x34, 0x40, 0x14, 0x20, 0x34, 0x40, 0x18, 0x20, 0x34, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x1C, 0x20, 0x34, 0x40, +0xFF, 0xFF, 0xFF, 0xDF, 0x10, 0xB5, 0x07, 0x49, 0x0A, 0x69, 0x0F, 0x24, 0xA2, 0x43, 0x03, 0x20, 0x02, 0x43, 0x0A, 0x61, +0xCB, 0x69, 0xA3, 0x43, 0x03, 0x43, 0xCB, 0x61, 0x02, 0x48, 0x7E, 0xF7, 0xA1, 0xFB, 0x10, 0xBD, 0x00, 0x30, 0x50, 0x40, +0x94, 0xD1, 0x10, 0x00, 0x70, 0xB5, 0x1B, 0x4B, 0x9B, 0x69, 0xDB, 0x05, 0x1F, 0xD4, 0x0C, 0x38, 0xEF, 0xF3, 0x10, 0x83, +0x01, 0x22, 0x14, 0x00, 0x1C, 0x40, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x15, 0x4B, 0x1B, 0x7F, 0x01, 0x2B, 0x1C, 0xD0, +0xCF, 0xF7, 0x62, 0xF8, 0x12, 0x4B, 0x1B, 0x7F, 0xFF, 0x2B, 0x1A, 0xD0, 0x02, 0x20, 0x7B, 0xF7, 0xCB, 0xF9, 0xFF, 0xF7, +0xCF, 0xFF, 0x0F, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, 0x00, 0x2C, 0x00, 0xD1, 0x62, 0xB6, 0x70, 0xBD, 0x0C, 0x4D, +0xC4, 0x24, 0x64, 0x00, 0x00, 0x23, 0x2B, 0x51, 0xCE, 0xF7, 0xCC, 0xF8, 0x09, 0x4B, 0x2B, 0x51, 0xF4, 0xE7, 0x05, 0x4B, +0xFF, 0x22, 0x1A, 0x77, 0xDE, 0xE7, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x77, 0xE0, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, +0x24, 0x2A, 0x16, 0x00, 0x00, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0xB9, 0x5A, 0x10, 0x00, 0x01, 0x28, 0x02, 0xD0, +0x02, 0x28, 0x05, 0xD0, 0x70, 0x47, 0x05, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xF9, 0xE7, 0x02, 0x4B, 0x80, 0x22, +0x52, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x15, 0x4B, 0x16, 0x4A, 0x13, 0x60, 0x16, 0x4A, +0x13, 0x60, 0x16, 0x4B, 0x1A, 0x68, 0x30, 0x21, 0x8A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x90, 0x31, 0x8A, 0x43, 0x1A, 0x60, +0x1A, 0x68, 0x12, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x11, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x10, 0x49, +0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x0F, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x0E, 0x4A, 0xC4, 0x20, 0x80, 0x00, 0x13, 0x58, +0x1B, 0x02, 0x1B, 0x0A, 0xC0, 0x21, 0x09, 0x06, 0x0B, 0x43, 0x13, 0x50, 0x80, 0x23, 0x1B, 0x03, 0x13, 0x60, 0x70, 0x47, +0x00, 0x00, 0x7C, 0x07, 0x08, 0x41, 0x04, 0x40, 0x0C, 0x41, 0x04, 0x40, 0x18, 0x41, 0x04, 0x40, 0xFF, 0xFC, 0xFF, 0xFF, +0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x00, 0xE1, 0x00, 0xE0, 0x70, 0xB5, 0x82, 0xB0, +0x04, 0x00, 0x64, 0x4B, 0x18, 0x68, 0x04, 0x28, 0x04, 0xD8, 0x49, 0xD8, 0x80, 0x00, 0x62, 0x4B, 0x1B, 0x58, 0x9F, 0x46, +0xFF, 0x28, 0x43, 0xD1, 0x60, 0x4B, 0x80, 0x22, 0xD2, 0x00, 0x1A, 0x60, 0x5F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x5F, 0x4B, +0x1B, 0x68, 0x00, 0x2B, 0x40, 0xD1, 0x5E, 0x4B, 0x19, 0x68, 0x41, 0x29, 0x57, 0xD0, 0x43, 0xD8, 0x01, 0x29, 0x49, 0xD0, +0x21, 0x29, 0x00, 0xD0, 0x81, 0xE0, 0x5A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x52, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0x58, 0x4B, +0x1B, 0x68, 0x01, 0x2B, 0x54, 0xD1, 0x50, 0xE0, 0x54, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x4F, 0x4B, 0x80, 0x22, 0xD2, 0x00, +0x1A, 0x60, 0x4E, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x50, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x00, 0xD1, 0x7D, 0xE0, 0x47, 0x4B, +0x1B, 0x68, 0x02, 0x2B, 0x40, 0xD1, 0x00, 0x25, 0x4C, 0x4B, 0x1D, 0x70, 0x01, 0x20, 0xFB, 0xF7, 0xCB, 0xFD, 0x4B, 0x4B, +0x1D, 0x70, 0x3D, 0xE0, 0x46, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0xE2, 0xE7, 0x44, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xDE, 0xE7, +0x42, 0x4B, 0x19, 0x78, 0x45, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA8, 0x47, 0xD6, 0xE7, 0x0F, 0x20, 0xFA, 0xF7, +0x6F, 0xFD, 0xFF, 0x23, 0x03, 0x40, 0x3B, 0x4A, 0x13, 0x60, 0xB6, 0xE7, 0x61, 0x29, 0x10, 0xD0, 0xFF, 0x29, 0x3E, 0xD1, +0x3D, 0x48, 0x7E, 0xF7, 0xA1, 0xFA, 0xCD, 0xE7, 0x36, 0x4B, 0x02, 0x22, 0x1A, 0x70, 0x2F, 0x4B, 0x01, 0x3A, 0x1A, 0x60, +0x34, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x0D, 0xD1, 0x4C, 0xE0, 0x31, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x29, 0x4B, 0x01, 0x32, +0x1A, 0x60, 0x2F, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0xC1, 0xD1, 0x26, 0x4B, 0x03, 0x22, 0x1A, 0x60, 0x2D, 0x4B, 0x01, 0x22, +0x1A, 0x70, 0x00, 0x20, 0xFB, 0xF7, 0x8A, 0xFD, 0x2D, 0x4B, 0x03, 0x22, 0x1A, 0x70, 0xFF, 0xF7, 0x35, 0xFF, 0x2C, 0x4B, +0x1B, 0x68, 0x24, 0x4A, 0x12, 0x78, 0x1D, 0x49, 0x09, 0x68, 0x2A, 0x48, 0x00, 0x68, 0x01, 0x90, 0x1E, 0x48, 0x00, 0x68, +0x00, 0x90, 0x28, 0x48, 0x7E, 0xF7, 0x6E, 0xFA, 0x00, 0x2C, 0x27, 0xD0, 0x26, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x0B, 0x43, +0x13, 0x60, 0x02, 0xB0, 0x70, 0xBD, 0x24, 0x48, 0x7E, 0xF7, 0x62, 0xFA, 0x17, 0x4E, 0x31, 0x78, 0x10, 0x4D, 0x00, 0x23, +0x00, 0x22, 0x28, 0x68, 0x81, 0xF7, 0xFE, 0xFF, 0x02, 0x23, 0x33, 0x70, 0x01, 0x3B, 0x2B, 0x60, 0x12, 0x4B, 0x1B, 0x68, +0x01, 0x2B, 0xC9, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x03, 0xE0, 0x0E, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0xBF, 0xD0, 0x02, 0x2B, +0x00, 0xD0, 0x7A, 0xE7, 0x04, 0x4B, 0x04, 0x22, 0x1A, 0x60, 0xBB, 0xE7, 0x12, 0x4A, 0x13, 0x68, 0x20, 0x21, 0x8B, 0x43, +0x13, 0x60, 0xD6, 0xE7, 0x50, 0xE0, 0x10, 0x00, 0xE0, 0xD1, 0x10, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xB2, 0xE6, 0x10, 0x00, +0xA4, 0xE5, 0x10, 0x00, 0xC0, 0xE5, 0x10, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x54, 0xE0, 0x10, 0x00, 0x60, 0xE6, 0x10, 0x00, +0xDC, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x9C, 0xD1, 0x10, 0x00, 0xD1, 0xE6, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, +0xBC, 0xE5, 0x10, 0x00, 0xC8, 0xD1, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, 0xB0, 0xD1, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, +0x00, 0xB5, 0x38, 0x4B, 0x38, 0x4A, 0x1A, 0x60, 0x38, 0x4B, 0x39, 0x4A, 0x1A, 0x60, 0x40, 0x23, 0x38, 0x4A, 0x13, 0x60, +0x28, 0x22, 0x38, 0x49, 0x0A, 0x80, 0xC8, 0x21, 0x49, 0x00, 0x37, 0x48, 0x01, 0x80, 0x37, 0x48, 0x01, 0x80, 0x03, 0x20, +0x36, 0x49, 0x08, 0x80, 0x02, 0x21, 0x36, 0x4C, 0x21, 0x80, 0x36, 0x4C, 0x20, 0x80, 0x36, 0x48, 0x01, 0x80, 0x36, 0x49, +0x0A, 0x80, 0x80, 0x25, 0xAD, 0x00, 0x35, 0x49, 0x0D, 0x80, 0x14, 0x21, 0x34, 0x48, 0x01, 0x80, 0x34, 0x48, 0x15, 0x24, +0x04, 0x80, 0x34, 0x48, 0x01, 0x80, 0x20, 0x26, 0x33, 0x49, 0x0E, 0x60, 0x0D, 0x3C, 0x33, 0x49, 0x0C, 0x60, 0x33, 0x49, +0x01, 0x20, 0x40, 0x42, 0x08, 0x60, 0x00, 0x20, 0x31, 0x49, 0x08, 0x60, 0x31, 0x49, 0x88, 0x46, 0x31, 0x4F, 0x39, 0x60, +0x31, 0x4F, 0x14, 0x21, 0xFF, 0x31, 0x39, 0x60, 0x30, 0x4F, 0x31, 0x49, 0x39, 0x60, 0x31, 0x4F, 0x07, 0x21, 0x39, 0x80, +0x30, 0x4F, 0x3B, 0x80, 0x30, 0x4F, 0x41, 0x31, 0x39, 0x80, 0x30, 0x4F, 0x01, 0x39, 0x39, 0x80, 0x2F, 0x4F, 0x3E, 0x80, +0x2F, 0x4E, 0x35, 0x80, 0x2F, 0x4D, 0xD2, 0x26, 0x76, 0x00, 0x2E, 0x80, 0x64, 0x25, 0x2E, 0x4E, 0x35, 0x80, 0x2E, 0x4E, +0x35, 0x80, 0x2E, 0x4D, 0x2C, 0x80, 0x2E, 0x4C, 0x18, 0x25, 0x25, 0x80, 0x2D, 0x4C, 0x22, 0x80, 0x2D, 0x4A, 0x8C, 0x24, +0x14, 0x80, 0x2D, 0x4A, 0x10, 0x80, 0x2D, 0x4A, 0x13, 0x60, 0x2D, 0x4B, 0x42, 0x46, 0x1A, 0x60, 0x2C, 0x4B, 0x32, 0x22, +0x1A, 0x80, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xA0, 0x06, 0x16, 0x00, 0x00, 0xD7, 0x18, 0x00, 0x9C, 0x06, 0x16, 0x00, +0x00, 0xF7, 0x18, 0x00, 0x78, 0x06, 0x16, 0x00, 0x5C, 0x06, 0x16, 0x00, 0x8E, 0x06, 0x16, 0x00, 0x8C, 0x06, 0x16, 0x00, +0x5A, 0x06, 0x16, 0x00, 0x4A, 0x06, 0x16, 0x00, 0x56, 0x06, 0x16, 0x00, 0x54, 0x06, 0x16, 0x00, 0x5E, 0x06, 0x16, 0x00, +0x58, 0x06, 0x16, 0x00, 0x64, 0x06, 0x16, 0x00, 0x66, 0x06, 0x16, 0x00, 0x62, 0x06, 0x16, 0x00, 0x68, 0x06, 0x16, 0x00, +0x6C, 0x06, 0x16, 0x00, 0x44, 0x1E, 0x16, 0x00, 0x40, 0x1E, 0x16, 0x00, 0x20, 0x4E, 0x00, 0x00, 0x7C, 0x06, 0x16, 0x00, +0x38, 0x1E, 0x16, 0x00, 0x3C, 0x1E, 0x16, 0x00, 0x02, 0x73, 0x06, 0x20, 0x4C, 0x06, 0x16, 0x00, 0x4E, 0x06, 0x16, 0x00, +0x50, 0x06, 0x16, 0x00, 0x52, 0x06, 0x16, 0x00, 0x90, 0x06, 0x16, 0x00, 0x94, 0x06, 0x16, 0x00, 0x92, 0x06, 0x16, 0x00, +0x8A, 0x06, 0x16, 0x00, 0x88, 0x06, 0x16, 0x00, 0x82, 0x06, 0x16, 0x00, 0x80, 0x06, 0x16, 0x00, 0x86, 0x06, 0x16, 0x00, +0x84, 0x06, 0x16, 0x00, 0x48, 0x1E, 0x16, 0x00, 0x70, 0x06, 0x16, 0x00, 0x74, 0x06, 0x16, 0x00, 0x60, 0x06, 0x16, 0x00, +0x0F, 0x4B, 0x02, 0x22, 0x9A, 0x77, 0x0F, 0x4A, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x01, 0x0B, 0x43, 0x13, 0x65, 0x0D, 0x4B, +0x1B, 0x78, 0x02, 0x2B, 0x0B, 0xD0, 0x0A, 0x4B, 0x19, 0x6D, 0x80, 0x22, 0x12, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x19, 0x6D, +0x80, 0x22, 0x92, 0x02, 0x0A, 0x43, 0x1A, 0x65, 0x70, 0x47, 0x11, 0x6D, 0x80, 0x23, 0xDB, 0x02, 0x0B, 0x43, 0x13, 0x65, +0xED, 0xE7, 0xC0, 0x46, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0xB4, 0xE5, 0x10, 0x00, 0x01, 0x4B, 0x01, 0x22, +0xDA, 0x77, 0x70, 0x47, 0x3C, 0x95, 0x16, 0x00, 0x10, 0xB5, 0x01, 0x20, 0x7F, 0xF7, 0x48, 0xF9, 0x10, 0xBD, 0x10, 0xB5, +0x80, 0x20, 0x40, 0x00, 0x7B, 0xF7, 0x3A, 0xFC, 0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x20, 0x4B, 0x1B, 0x68, +0x01, 0x2B, 0x03, 0xD0, 0x1F, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x22, 0xD1, 0x00, 0x2C, 0x2C, 0xD0, 0x1D, 0x4A, 0x13, 0x68, +0x08, 0x21, 0x0B, 0x43, 0x13, 0x60, 0x00, 0x23, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, 0x1B, 0x4A, 0x13, 0x60, +0x1B, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x22, 0xD9, 0x1A, 0x4A, 0x0F, 0x21, 0x11, 0x70, 0x03, 0x3B, 0x01, 0x2B, 0x05, 0xD8, +0x18, 0x4A, 0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0x16, 0x49, 0x17, 0x48, 0x7E, 0xF7, 0xEC, 0xF8, +0x10, 0xBD, 0xFF, 0xF7, 0xCF, 0xFE, 0xFF, 0xF7, 0x97, 0xFF, 0x11, 0x4B, 0x01, 0x22, 0xDA, 0x77, 0xFF, 0xF7, 0xBE, 0xFF, +0xFF, 0xF7, 0xC1, 0xFF, 0xD0, 0xE7, 0x07, 0x4A, 0x13, 0x68, 0x08, 0x21, 0x8B, 0x43, 0x13, 0x60, 0xD1, 0xE7, 0x09, 0x4B, +0x0B, 0x22, 0x1A, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0xA8, 0xE5, 0x10, 0x00, 0xAC, 0xE5, 0x10, 0x00, 0x84, 0x40, 0x04, 0x40, +0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x54, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xE2, 0xE1, 0x10, 0x00, +0x3C, 0x95, 0x16, 0x00, 0xF8, 0xE8, 0x10, 0x00, 0xF4, 0xD1, 0x10, 0x00, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x04, 0x1A, 0x60, +0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0x12, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, +0x00, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, +0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x52, 0x05, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, +0xD0, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x04, 0x00, 0x13, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x07, 0xD0, +0x11, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x16, 0xD9, 0x20, 0x00, 0x10, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xAD, 0x33, 0xC3, 0x5C, +0x00, 0x2B, 0xF7, 0xD0, 0x0D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x54, 0xF8, +0xEA, 0xE7, 0xFF, 0xF7, 0xD5, 0xFF, 0x08, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xAE, 0xF7, 0x09, 0xFD, 0x00, 0x28, +0xE4, 0xD1, 0xA7, 0x23, 0x04, 0x22, 0xE2, 0x54, 0xE0, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, 0xD5, 0x0D, 0x0B, 0x00, +0xD8, 0xE6, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x0B, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFE, 0xF7, +0x11, 0xF9, 0x10, 0xBD, 0x08, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, 0xFD, 0xF7, 0x2C, 0xF8, +0xF2, 0xE7, 0xFF, 0xF7, 0xAD, 0xFF, 0x03, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xC0, 0x46, 0x50, 0xE0, 0x10, 0x00, +0xD8, 0xE6, 0x10, 0x00, 0x04, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x03, 0xD0, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x05, 0x1A, 0x60, +0x70, 0x47, 0xC0, 0x46, 0xD2, 0xE6, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, +0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x00, 0x91, 0x82, 0x00, 0x93, 0x4B, 0xD5, 0x58, 0x9E, 0x23, 0xEC, 0x5C, +0x64, 0x00, 0x0F, 0x33, 0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0xAF, 0xE0, +0xA8, 0x23, 0xEB, 0x5C, 0x77, 0x2B, 0x02, 0xD8, 0x01, 0x33, 0xA8, 0x22, 0xAB, 0x54, 0x43, 0x46, 0x1B, 0x02, 0x01, 0x27, +0x3B, 0x43, 0x9B, 0x46, 0x87, 0x4B, 0x99, 0x46, 0x47, 0xE0, 0xC5, 0x20, 0x02, 0x23, 0xFF, 0x22, 0x59, 0x46, 0xC0, 0x00, +0x7B, 0xF7, 0x0A, 0xFF, 0x06, 0x00, 0x3B, 0x88, 0x03, 0x80, 0x7B, 0xF7, 0x2F, 0xFF, 0x30, 0x88, 0x43, 0x1C, 0x9B, 0xB2, +0x7F, 0x49, 0x5A, 0x5C, 0x41, 0x5C, 0x49, 0x10, 0x7E, 0x48, 0x7D, 0xF7, 0xFF, 0xFF, 0x00, 0x23, 0x3B, 0x80, 0x7D, 0x4B, +0xE2, 0x18, 0x13, 0x88, 0x78, 0x21, 0x8B, 0x43, 0x13, 0x80, 0x7B, 0x4B, 0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x7A, 0x4A, +0x13, 0x40, 0x23, 0x80, 0xAF, 0x22, 0xAB, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xAB, 0x54, 0x35, 0x31, 0x6A, 0x5C, 0x50, 0x42, +0x42, 0x41, 0x6A, 0x54, 0x5A, 0x1E, 0x93, 0x41, 0xA8, 0x22, 0xAB, 0x54, 0x8C, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x05, 0xD0, +0x6A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x9E, 0x23, 0xEC, 0x5C, 0x64, 0x00, 0x0F, 0x33, +0xEB, 0x5C, 0xE4, 0x18, 0xE4, 0xB2, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x58, 0xD0, 0xA3, 0x00, 0x1C, 0x19, 0x64, 0x00, +0x66, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x0B, 0x50, 0xD0, 0x65, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, +0xA9, 0xD1, 0x63, 0x4B, 0xE7, 0x18, 0x3B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x38, 0xD0, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, +0xB7, 0xD1, 0x5A, 0x4B, 0xE3, 0x18, 0x1B, 0x88, 0xDB, 0x04, 0x9B, 0x0D, 0x0A, 0xD0, 0x3A, 0x88, 0x90, 0x21, 0x69, 0x58, +0xD3, 0x18, 0x4A, 0x89, 0x92, 0x05, 0x92, 0x0D, 0x09, 0x89, 0x52, 0x18, 0x93, 0x42, 0x0D, 0xDA, 0x8C, 0x23, 0xEB, 0x58, +0x00, 0x2B, 0x06, 0xD0, 0x4B, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x23, +0x3B, 0x80, 0x98, 0xE7, 0x01, 0x23, 0xFF, 0x22, 0x59, 0x46, 0x4E, 0x48, 0x7B, 0xF7, 0x8C, 0xFE, 0x00, 0x23, 0x9A, 0x46, +0x03, 0x70, 0x7B, 0xF7, 0xB1, 0xFE, 0x90, 0x26, 0xAB, 0x59, 0x18, 0x89, 0x85, 0xF7, 0xA2, 0xFF, 0x8C, 0x23, 0xEA, 0x58, +0xAA, 0x51, 0x52, 0x46, 0xEA, 0x50, 0xE6, 0xE7, 0xEC, 0x23, 0xEB, 0x58, 0x00, 0x2B, 0x00, 0xD0, 0x7D, 0xE7, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x4B, 0x46, 0x9B, 0x6E, 0x98, 0x47, 0x76, 0xE7, 0x00, 0x99, 0x40, 0x46, 0xFD, 0xF7, 0x0C, 0xF8, +0x3D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0A, 0xD0, 0xFC, 0xF7, 0x6E, 0xF9, 0x01, 0x28, 0x28, 0xD0, 0x03, 0xB0, 0x3C, 0xBC, +0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xAD, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x35, 0x4B, +0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0x2B, 0xFF, 0xE7, 0xE7, 0xFF, 0xF7, 0x08, 0xFF, +0x2F, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0x2D, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x21, 0x01, 0x20, +0xFC, 0xF7, 0x1C, 0xFF, 0xD8, 0xE7, 0xFF, 0xF7, 0x9D, 0xFE, 0x28, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xFB, 0xF7, +0x0F, 0xFA, 0x00, 0x28, 0xD2, 0xD0, 0xAE, 0xF7, 0xCD, 0xFB, 0x00, 0x28, 0xCE, 0xD1, 0x8A, 0xF7, 0x5D, 0xFA, 0x00, 0x28, +0xCA, 0xD1, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0xC6, 0xD1, 0xA7, 0x33, 0xEB, 0x5C, 0x01, 0x2B, 0xC2, 0xD8, 0xD0, 0xF7, +0xD9, 0xFA, 0x04, 0x1E, 0xBE, 0xD0, 0x1B, 0x4B, 0xC2, 0x69, 0x9A, 0x42, 0xBA, 0xD1, 0xA5, 0xF7, 0x4D, 0xFA, 0x63, 0x68, +0x05, 0x3B, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAA, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xAF, 0xD0, 0x0B, 0x2B, 0xAD, 0xD9, +0x13, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x9E, 0x23, 0xE8, 0x5C, 0xD1, 0xF7, 0x35, 0xFA, 0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, +0xA2, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xFC, 0xD1, 0x10, 0x00, +0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0x07, 0xE0, 0xFF, 0xFF, 0xC8, 0x69, 0x61, 0x40, 0xD0, 0x69, 0x61, 0x40, +0xCE, 0x69, 0x61, 0x40, 0x2B, 0x06, 0x00, 0x00, 0x50, 0xE0, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xC9, 0x1F, 0x10, 0x00, +0x98, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x81, 0x46, +0x82, 0x00, 0xBA, 0x4B, 0xD4, 0x58, 0x01, 0x94, 0xB0, 0x23, 0x15, 0x22, 0xE2, 0x54, 0x2A, 0x3B, 0xFA, 0x22, 0x52, 0x01, +0xE2, 0x52, 0xB6, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x15, 0xD0, 0xB4, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x26, 0xD9, 0xB3, 0x4B, +0x00, 0x22, 0x1A, 0x70, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x2C, 0xD0, 0x86, 0x23, 0xE3, 0x5A, 0x00, 0x2B, 0x6B, 0xD0, +0x5B, 0x00, 0x22, 0x6F, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1F, 0x09, 0x29, 0xE0, 0xAB, 0x4B, 0xE3, 0x61, 0xAF, 0x23, +0xE3, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0xA9, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x04, 0xD0, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, +0x87, 0xFE, 0xDA, 0xE7, 0xFF, 0xF7, 0x64, 0xFE, 0xA3, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xF4, 0xE7, 0xA0, 0x4B, 0xE3, 0x61, +0x9E, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xD2, 0xD0, 0x9F, 0x4B, 0x18, 0x68, 0x00, 0x28, 0xCE, 0xD0, 0xFB, 0xF7, 0x86, 0xFE, +0xCB, 0xE7, 0xE4, 0x33, 0xE3, 0x58, 0x19, 0x68, 0xA3, 0x6F, 0xC9, 0x1A, 0x14, 0x39, 0x09, 0x01, 0x0F, 0x09, 0xA6, 0x23, +0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x96, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, +0x94, 0x4A, 0x13, 0x43, 0xA3, 0x82, 0xE7, 0x60, 0xFB, 0xF7, 0x56, 0xF9, 0x02, 0x90, 0xFD, 0xF7, 0x2B, 0xF9, 0x03, 0x90, +0xAE, 0xF7, 0x12, 0xFB, 0x06, 0x00, 0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0x00, 0xD1, 0x38, 0xE2, 0x00, 0x25, 0x00, 0x28, +0x2B, 0xD0, 0x8B, 0x4B, 0xA2, 0x6F, 0x1A, 0x60, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x5C, 0xE1, 0x88, 0x4A, +0xD2, 0x88, 0x22, 0x61, 0x01, 0x2B, 0x00, 0xD0, 0xDA, 0xE1, 0xA7, 0x33, 0xE3, 0x5C, 0xA7, 0x21, 0x61, 0x5C, 0x5B, 0x18, +0x1B, 0x11, 0x83, 0x49, 0x4B, 0x43, 0x93, 0x42, 0x00, 0xD2, 0x13, 0x00, 0x23, 0x61, 0xCD, 0xE1, 0xA6, 0x23, 0xE3, 0x5C, +0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x1A, 0x40, 0x78, 0x4B, 0x59, 0x78, 0x0F, 0x23, 0x0B, 0x40, 0x13, 0x43, 0x7B, 0x4A, +0x13, 0x43, 0xA3, 0x82, 0x01, 0x27, 0x7F, 0x42, 0xC2, 0xE7, 0xA5, 0xF7, 0x73, 0xF9, 0x60, 0x60, 0x03, 0x9B, 0x00, 0x2B, +0x52, 0xD0, 0x76, 0x4B, 0x23, 0x61, 0x11, 0x23, 0xA3, 0x75, 0x8E, 0x33, 0xE3, 0x5C, 0x01, 0x2B, 0x47, 0xD0, 0x00, 0x25, +0x48, 0x23, 0x9B, 0x46, 0xAF, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x48, 0x30, 0x7E, 0xF7, 0x83, 0xFA, 0x6E, 0x4A, +0x12, 0x68, 0x92, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0xE0, 0xE0, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x01, 0xD1, 0x6A, 0x4B, +0x23, 0x61, 0x40, 0x44, 0xC3, 0xB2, 0xA7, 0x22, 0xA2, 0x5C, 0x11, 0x00, 0x19, 0x43, 0x06, 0xD0, 0xD3, 0x18, 0x65, 0x4A, +0x53, 0x43, 0x22, 0x69, 0x94, 0x46, 0x63, 0x44, 0x23, 0x61, 0x23, 0x69, 0x62, 0x4A, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, +0x23, 0x61, 0x5A, 0x46, 0x21, 0x69, 0x20, 0x00, 0xFB, 0xF7, 0x16, 0xF8, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, +0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0xA7, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x50, 0x4B, 0xA2, 0x6F, +0x1A, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0xB6, 0xFF, 0x00, 0x28, 0x00, 0xD0, 0xAE, 0xE1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, +0x49, 0xE1, 0x37, 0x33, 0x9B, 0x46, 0xB7, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x6B, 0xD0, 0x00, 0x23, 0x00, 0x25, 0x3E, 0x4A, +0x90, 0x46, 0xA1, 0x22, 0x94, 0x46, 0x02, 0xE0, 0x01, 0x33, 0x07, 0x2B, 0x0B, 0xD0, 0x9A, 0x00, 0x41, 0x46, 0x52, 0x58, +0x00, 0x2A, 0xF7, 0xD0, 0x61, 0x46, 0x52, 0x5C, 0x00, 0x2A, 0xF3, 0xD1, 0x01, 0x35, 0xED, 0xB2, 0xF0, 0xE7, 0x01, 0x2D, +0x08, 0xD9, 0xA0, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x41, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x28, 0x23, 0x9B, 0x46, 0x93, 0xE7, +0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x23, 0xD1, 0xA7, 0x33, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x33, 0xE2, 0x5C, 0x53, 0x42, +0x5A, 0x41, 0x53, 0x42, 0x08, 0x22, 0x1A, 0x40, 0x68, 0x32, 0x38, 0x4B, 0x1B, 0x68, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, +0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, 0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, +0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, 0x9B, 0x46, 0x2C, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x6B, 0xE7, +0x01, 0x2B, 0x00, 0xD0, 0x65, 0xE1, 0xA7, 0x33, 0xE2, 0x5C, 0x53, 0x42, 0x5A, 0x41, 0x53, 0x42, 0x0C, 0x22, 0x1A, 0x40, +0x44, 0x32, 0xE3, 0x6E, 0x98, 0x46, 0xC3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x21, 0x09, 0x05, 0x8B, 0x42, 0x04, 0xD9, +0x43, 0x46, 0x1B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0x00, 0x21, 0x8B, 0x46, 0x9A, 0x42, 0x01, 0xD3, 0xD3, 0x1A, +0x9B, 0x46, 0x1B, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x48, 0xE7, 0x0A, 0x4B, 0x1B, 0x68, 0x00, 0x25, 0x01, 0x2B, 0x00, 0xD9, +0x05, 0xE7, 0x13, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x37, 0xE1, 0x13, 0x4B, 0x1B, 0x68, 0x23, 0x61, +0x00, 0x23, 0x9B, 0x46, 0x36, 0xE7, 0xC0, 0x46, 0x38, 0x27, 0x16, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x98, 0xE5, 0x10, 0x00, +0xC1, 0x60, 0x10, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0xF8, 0xE6, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x40, 0x80, 0xFF, 0xFF, +0xCC, 0xE6, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, +0xF4, 0xE1, 0x10, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x70, 0x71, 0x00, 0x00, 0x40, 0xE0, 0x10, 0x00, 0x2C, 0xE6, 0x10, 0x00, +0x00, 0x23, 0x04, 0x93, 0x05, 0x93, 0x20, 0x1D, 0x23, 0x00, 0x05, 0xAA, 0x04, 0xA9, 0xFA, 0xF7, 0xAD, 0xFE, 0x04, 0x9B, +0x00, 0x2B, 0x28, 0xD0, 0x22, 0x69, 0x9A, 0x42, 0x00, 0xD9, 0x1A, 0x00, 0x22, 0x61, 0x03, 0x26, 0x63, 0x68, 0x9A, 0x46, +0x5A, 0x46, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, 0x3B, 0xFF, 0x63, 0x68, 0x53, 0x45, 0x08, 0xD0, 0x05, 0x9B, 0x53, 0x44, +0x1B, 0x01, 0x1B, 0x09, 0x63, 0x60, 0x01, 0x3E, 0xF6, 0xB2, 0x00, 0x2E, 0xEC, 0xD1, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, +0x00, 0xD0, 0x0E, 0xE7, 0x63, 0x68, 0x03, 0x33, 0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x23, 0x69, 0x70, 0x4A, 0x94, 0x46, +0x63, 0x44, 0x23, 0x61, 0x03, 0xE7, 0x02, 0x9B, 0x00, 0x2B, 0x00, 0xD1, 0x9B, 0xE6, 0xEA, 0xE7, 0xA7, 0x23, 0xE3, 0x5C, +0x00, 0x2B, 0x00, 0xD0, 0x7B, 0xE0, 0xA8, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x76, 0xE0, 0xB3, 0x33, 0xE3, 0x5C, +0x00, 0x2B, 0x00, 0xD0, 0x71, 0xE0, 0x65, 0x4B, 0x23, 0x61, 0x73, 0x42, 0x73, 0x41, 0x5B, 0x42, 0x4B, 0x22, 0x93, 0x43, +0x60, 0x33, 0x5B, 0x00, 0x62, 0x68, 0x94, 0x46, 0x63, 0x44, 0x60, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xB0, 0x23, 0x09, 0x22, +0xE2, 0x54, 0x20, 0x00, 0xCF, 0xF7, 0xA8, 0xFE, 0x00, 0x28, 0x00, 0xD0, 0xA0, 0xE0, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, +0x00, 0x2E, 0x3A, 0xD0, 0xA5, 0xF7, 0x0E, 0xF8, 0x57, 0x4B, 0x18, 0x60, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x66, 0x60, 0x80, 0xE0, 0x00, 0x2E, 0x00, 0xD1, 0x86, 0xE0, 0x51, 0x4B, 0x23, 0x61, +0x20, 0x00, 0xFD, 0xF7, 0x57, 0xFE, 0x60, 0x60, 0x18, 0x26, 0x65, 0x68, 0x00, 0x22, 0x21, 0x69, 0x01, 0x98, 0xFA, 0xF7, +0xD1, 0xFE, 0x63, 0x68, 0xAB, 0x42, 0x06, 0xD0, 0x75, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x65, 0x60, 0x18, 0x36, 0x60, 0x2E, +0xEF, 0xD1, 0x20, 0x00, 0xCF, 0xF7, 0x76, 0xFE, 0x00, 0x28, 0x6F, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xCF, 0xE7, +0x39, 0x00, 0x14, 0x31, 0x09, 0x01, 0x09, 0x09, 0x48, 0x46, 0x40, 0x4B, 0x98, 0x47, 0xCB, 0xE7, 0xA0, 0x23, 0x00, 0x22, +0xE2, 0x54, 0xA3, 0x7D, 0x10, 0x2B, 0x01, 0xD8, 0x11, 0x23, 0xA3, 0x75, 0x02, 0x9B, 0x00, 0x2B, 0xBC, 0xD0, 0x01, 0x2D, +0xBA, 0xD1, 0x39, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0xB5, 0xD1, 0x37, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0x9F, 0x23, +0xE3, 0x5C, 0x01, 0x2B, 0xAE, 0xD1, 0x35, 0x4B, 0x1B, 0x68, 0x23, 0x61, 0xAA, 0xE7, 0x34, 0x4B, 0xDB, 0x88, 0x23, 0x61, +0xA1, 0x23, 0xE3, 0x5C, 0x04, 0x2B, 0xB0, 0xD0, 0x00, 0x2E, 0xB1, 0xD1, 0x30, 0x4B, 0x23, 0x61, 0xA7, 0x23, 0xE3, 0x5C, +0x00, 0x2B, 0x03, 0xD1, 0xA8, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x2E, 0xD0, 0xA8, 0x22, 0xA1, 0x5C, 0xCB, 0x18, 0x2A, 0x49, +0x59, 0x43, 0x29, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x21, 0x61, 0x23, 0x4B, 0x1A, 0x68, 0x53, 0x6F, 0x58, 0x42, 0x43, 0x41, +0x5B, 0x42, 0x1B, 0x48, 0x03, 0x40, 0x24, 0x48, 0x84, 0x46, 0x63, 0x44, 0x92, 0x68, 0x00, 0x2A, 0x02, 0xD0, 0x22, 0x4A, +0x12, 0x68, 0x9B, 0x1A, 0x99, 0x42, 0x00, 0xD9, 0x19, 0x00, 0x21, 0x61, 0x66, 0x68, 0x28, 0x22, 0x20, 0x00, 0xFA, 0xF7, +0x63, 0xFE, 0x01, 0x28, 0x00, 0xD1, 0x7C, 0xE7, 0x9F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x63, 0x68, 0x03, 0x33, +0x03, 0x22, 0x93, 0x43, 0x63, 0x60, 0x20, 0x00, 0xCF, 0xF7, 0x06, 0xFE, 0x00, 0x28, 0x9B, 0xD0, 0xA1, 0x23, 0xE3, 0x5C, +0x04, 0x2B, 0x8F, 0xD0, 0x08, 0x21, 0x48, 0x46, 0x11, 0x4B, 0x98, 0x47, 0x5E, 0xE7, 0x00, 0x25, 0xC7, 0xE5, 0x00, 0x25, +0xC5, 0xE5, 0x00, 0x23, 0x9B, 0x46, 0xFF, 0xE5, 0xAA, 0xF8, 0xFF, 0xFF, 0x98, 0x12, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x0F, +0x34, 0xE6, 0x10, 0x00, 0x88, 0x13, 0x00, 0x00, 0xB9, 0x4C, 0x0B, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x40, 0xE0, 0x10, 0x00, +0x44, 0xE0, 0x10, 0x00, 0x5C, 0xAB, 0x16, 0x00, 0x5C, 0x1C, 0x00, 0x00, 0x7C, 0x42, 0x00, 0x00, 0xE8, 0xE1, 0x10, 0x00, +0x95, 0x0F, 0x0B, 0x00, 0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0xB7, 0x4B, 0xB8, 0x4A, +0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0xFD, 0xF7, 0x5A, 0xFA, 0xB5, 0x4B, 0x1B, 0x68, 0x9B, 0x68, 0x00, 0x2B, +0x09, 0xD0, 0xB2, 0x4B, 0x1D, 0x68, 0x02, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0xA3, 0x42, 0x00, 0xD1, 0x42, 0xE1, 0xB0, 0x4F, +0x84, 0xE0, 0xFA, 0xF7, 0xFD, 0xFD, 0xF2, 0xE7, 0xAE, 0x4A, 0x93, 0x42, 0x46, 0xD1, 0xAE, 0x4B, 0x4B, 0x60, 0x43, 0xE0, +0xAD, 0x49, 0x8B, 0x42, 0x00, 0xD1, 0xE5, 0xE0, 0xAC, 0x49, 0x8B, 0x42, 0x16, 0xD1, 0xAC, 0x4B, 0x1A, 0x68, 0x00, 0x2A, +0x38, 0xD0, 0x23, 0x01, 0xED, 0x18, 0xA9, 0x68, 0x8B, 0x00, 0x9B, 0x58, 0x00, 0x9A, 0x48, 0x46, 0x02, 0x43, 0xD2, 0xB2, +0x00, 0x2A, 0x04, 0xD0, 0x00, 0x29, 0x00, 0xD0, 0xCC, 0xE0, 0xD8, 0x22, 0x1A, 0x86, 0x00, 0x22, 0x9A, 0x62, 0x25, 0xE0, +0xA1, 0x49, 0x8B, 0x42, 0x22, 0xD1, 0x02, 0x2A, 0x20, 0xD1, 0x00, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xA5, 0xFB, 0x1B, 0xE0, +0x9D, 0x4B, 0x1D, 0x68, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x04, 0xD0, 0x00, 0x23, 0xAB, 0x62, +0x34, 0x33, 0x01, 0x22, 0xEA, 0x54, 0xAE, 0xF7, 0x53, 0xF8, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0xC0, 0x22, 0x92, 0x01, +0x13, 0x40, 0x80, 0x22, 0x52, 0x01, 0x94, 0x46, 0x63, 0x44, 0x2B, 0x86, 0x12, 0x23, 0x6B, 0x86, 0x86, 0x4B, 0x1B, 0x68, +0x52, 0x46, 0x98, 0x18, 0x45, 0x68, 0x00, 0x2D, 0x00, 0xD1, 0xD1, 0xE0, 0x42, 0x46, 0x04, 0x3A, 0x51, 0x42, 0x4A, 0x41, +0xD2, 0xB2, 0x31, 0x01, 0x5B, 0x18, 0x99, 0x68, 0x00, 0x68, 0xA8, 0x47, 0x7D, 0x4B, 0x1D, 0x68, 0x33, 0x01, 0xEB, 0x18, +0x85, 0x4A, 0x5B, 0x68, 0x93, 0x42, 0x00, 0xD1, 0xC5, 0xE0, 0x33, 0x01, 0xEB, 0x18, 0x00, 0x22, 0x1A, 0x73, 0x03, 0x32, +0xFF, 0x32, 0xAB, 0x5C, 0x01, 0x3B, 0xAB, 0x54, 0x02, 0x23, 0xFF, 0x33, 0xEA, 0x5C, 0x0F, 0x21, 0xA2, 0x42, 0x00, 0xD1, +0xC5, 0xE0, 0x01, 0x34, 0x0C, 0x40, 0x23, 0x01, 0xEB, 0x18, 0x1B, 0x7B, 0x00, 0x2B, 0xF5, 0xD0, 0x80, 0x23, 0x5B, 0x00, +0xEC, 0x54, 0xA2, 0x42, 0x00, 0xD1, 0xBB, 0xE0, 0x26, 0x00, 0x75, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1B, 0x88, 0x9B, 0x06, +0x5B, 0x0F, 0x98, 0x46, 0x03, 0x3B, 0x02, 0x2B, 0x00, 0xD9, 0xAF, 0xE0, 0xFB, 0xF7, 0x70, 0xFD, 0x00, 0x90, 0x01, 0x90, +0x3A, 0x68, 0x00, 0x23, 0x01, 0x21, 0x91, 0x42, 0x5B, 0x41, 0xDB, 0xB2, 0x99, 0x46, 0x23, 0x01, 0x9A, 0x46, 0xE9, 0x18, +0x4B, 0x68, 0x69, 0x48, 0x83, 0x42, 0x62, 0xD0, 0x00, 0xD9, 0x63, 0xE7, 0x67, 0x4A, 0x93, 0x42, 0x88, 0xD0, 0x63, 0x4A, +0x93, 0x42, 0x00, 0xD0, 0x56, 0xE7, 0x65, 0x4B, 0x1D, 0x68, 0x00, 0x23, 0xAB, 0x62, 0x51, 0x33, 0x01, 0x22, 0xEA, 0x54, +0xAD, 0xF7, 0xDE, 0xFF, 0x00, 0x28, 0x05, 0xD0, 0x80, 0x23, 0x9B, 0x01, 0xAB, 0x85, 0x06, 0x23, 0xEB, 0x85, 0x8F, 0xE7, +0x50, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x0B, 0xD0, 0x00, 0x9B, 0x4A, 0x46, 0x13, 0x43, 0xDB, 0xB2, 0x00, 0x2B, 0x1C, 0xD1, +0x80, 0x23, 0x1B, 0x01, 0xAB, 0x85, 0x12, 0x23, 0xEB, 0x85, 0x7F, 0xE7, 0x55, 0x4B, 0xEB, 0x61, 0x01, 0x9B, 0x00, 0x2B, +0x03, 0xD1, 0xFD, 0xF7, 0x13, 0xFA, 0x01, 0x28, 0x07, 0xD9, 0x00, 0x9A, 0xD3, 0x02, 0xAB, 0x85, 0x09, 0x23, 0x9B, 0x1A, +0x5B, 0x00, 0xEB, 0x85, 0x6E, 0xE7, 0x80, 0x23, 0x5B, 0x00, 0xAB, 0x85, 0xEE, 0x3B, 0xEB, 0x85, 0x68, 0xE7, 0xFD, 0xF7, +0x41, 0xF9, 0x01, 0x28, 0x00, 0xD8, 0x63, 0xE7, 0x80, 0x23, 0xDB, 0x01, 0xAB, 0x85, 0x08, 0x23, 0xEB, 0x85, 0x5D, 0xE7, +0xC8, 0x22, 0x92, 0x00, 0x1A, 0x86, 0x30, 0xE7, 0x01, 0x2A, 0x00, 0xD9, 0x56, 0xE7, 0x01, 0x9B, 0x00, 0x2B, 0x00, 0xD1, +0x52, 0xE7, 0x23, 0x01, 0xED, 0x18, 0xAB, 0x68, 0x9B, 0x00, 0x3E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x68, 0xC0, 0x22, +0x12, 0x01, 0xDA, 0x66, 0x46, 0xE7, 0x02, 0x2A, 0x00, 0xD0, 0x43, 0xE7, 0x23, 0x01, 0xED, 0x18, 0x2B, 0x7A, 0x9B, 0x00, +0x37, 0x4A, 0x9D, 0x58, 0xAF, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD1, 0x35, 0x4B, 0x1B, 0x78, 0x01, 0x2B, 0x09, 0xD0, +0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, 0x00, 0xD0, 0x30, 0xE7, 0x01, 0x21, 0x02, 0x20, 0xFC, 0xF7, 0xB5, 0xFA, 0x2B, 0xE7, +0xFF, 0xF7, 0x92, 0xFA, 0x00, 0x23, 0x2D, 0x4A, 0x13, 0x70, 0xEF, 0xE7, 0x2C, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0x98, 0x47, 0x30, 0xE7, 0x24, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x00, 0xD1, 0x34, 0xE7, 0x11, 0x22, 0x9A, 0x75, +0x31, 0xE7, 0xFB, 0xF7, 0x93, 0xFB, 0x11, 0xE0, 0x80, 0x20, 0x80, 0x00, 0x7A, 0xF7, 0xE2, 0xFD, 0x13, 0xE0, 0x80, 0x23, +0x5B, 0x00, 0xEC, 0x54, 0x81, 0x23, 0x5B, 0x00, 0xEB, 0x5C, 0x00, 0x2B, 0x04, 0xD1, 0x05, 0x33, 0xFF, 0x33, 0xEB, 0x58, +0x00, 0x2B, 0xEA, 0xD0, 0x07, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0xE6, 0xD0, 0x02, 0xB0, +0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, +0xF4, 0xE1, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x31, 0xC3, 0x0A, 0x00, 0xE1, 0xA1, 0x10, 0x00, 0xE9, 0x8F, 0x0C, 0x00, +0xCD, 0x05, 0x0D, 0x00, 0xF0, 0x29, 0x16, 0x00, 0x5D, 0x74, 0x0B, 0x00, 0x20, 0x27, 0x16, 0x00, 0xD9, 0xEA, 0x0A, 0x00, +0x00, 0x10, 0x06, 0x04, 0x11, 0x6F, 0x0B, 0x00, 0x99, 0xCA, 0x0A, 0x00, 0x28, 0x27, 0x16, 0x00, 0x01, 0x00, 0x10, 0x00, +0x84, 0x29, 0x16, 0x00, 0x38, 0x27, 0x16, 0x00, 0xD8, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x04, 0x4B, +0x1B, 0x7F, 0x01, 0x2B, 0x00, 0xD0, 0x10, 0xBD, 0x02, 0x4B, 0x98, 0x47, 0xFB, 0xE7, 0xC0, 0x46, 0x24, 0x2A, 0x16, 0x00, +0x69, 0x44, 0x0D, 0x00, 0x10, 0xB5, 0x05, 0x4B, 0x80, 0x22, 0xD2, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, +0xAF, 0xF8, 0xFF, 0xF7, 0xE7, 0xFF, 0x10, 0xBD, 0x08, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x2D, 0x4B, 0x1B, 0x68, 0xC0, 0x22, +0x92, 0x02, 0x13, 0x42, 0x16, 0xD1, 0x5A, 0x03, 0x1E, 0xD4, 0x1A, 0x03, 0x2D, 0xD4, 0xDA, 0x02, 0x34, 0xD4, 0x9A, 0x02, +0x36, 0xD4, 0x5A, 0x02, 0x38, 0xD4, 0xDA, 0x01, 0x39, 0xD4, 0x9A, 0x01, 0x3E, 0xD4, 0x5B, 0x01, 0x0F, 0xD5, 0xFD, 0xF7, +0x1B, 0xFF, 0x22, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x08, 0xE0, 0x20, 0x4D, 0x91, 0x24, 0xE4, 0x00, 0x00, 0x23, +0x2B, 0x51, 0x84, 0xF7, 0x7F, 0xFB, 0x1E, 0x4B, 0x2B, 0x51, 0x70, 0xBD, 0x1D, 0x4B, 0x1C, 0x78, 0xFE, 0xF7, 0x84, 0xFE, +0x02, 0x2C, 0x04, 0xD0, 0x17, 0x4B, 0x80, 0x22, 0xD2, 0x02, 0x1A, 0x60, 0xF3, 0xE7, 0x19, 0x4B, 0x01, 0x22, 0x1A, 0x70, +0x84, 0xF7, 0x32, 0xFB, 0xED, 0xE7, 0x12, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, +0x3F, 0xFD, 0xE4, 0xE7, 0x01, 0x20, 0x84, 0xF7, 0x3D, 0xFB, 0xE0, 0xE7, 0x02, 0x20, 0x84, 0xF7, 0x39, 0xFB, 0xDC, 0xE7, +0xFF, 0xF7, 0xA6, 0xFF, 0xD9, 0xE7, 0xFA, 0xF7, 0xF1, 0xFD, 0x07, 0x4B, 0x80, 0x22, 0x52, 0x04, 0x1A, 0x60, 0xD2, 0xE7, +0xFA, 0xF7, 0x9A, 0xFF, 0x03, 0x4B, 0x80, 0x22, 0x92, 0x04, 0x1A, 0x60, 0xCB, 0xE7, 0xC0, 0x46, 0x1C, 0x41, 0x04, 0x40, +0x08, 0x41, 0x04, 0x40, 0x28, 0x19, 0x16, 0x00, 0x31, 0x6D, 0x10, 0x00, 0xE0, 0x1D, 0x16, 0x00, 0xE1, 0x1D, 0x16, 0x00, +0x10, 0xB5, 0x04, 0x4B, 0x80, 0x22, 0x12, 0x03, 0x1A, 0x60, 0x80, 0x20, 0x40, 0x00, 0x7A, 0xF7, 0x0F, 0xFD, 0x10, 0xBD, +0x08, 0x41, 0x04, 0x40, 0x10, 0xB5, 0x09, 0x4B, 0xDB, 0x7F, 0x00, 0x2B, 0x08, 0xD0, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x29, +0x04, 0xD0, 0x01, 0x20, 0x80, 0xF7, 0xD6, 0xFF, 0x84, 0xF7, 0x00, 0xFD, 0x03, 0x49, 0x40, 0x22, 0x0B, 0x6B, 0x1A, 0x42, +0xFC, 0xD0, 0x10, 0xBD, 0x3C, 0x95, 0x16, 0x00, 0x00, 0x60, 0x50, 0x40, 0x70, 0xB5, 0x82, 0xB0, 0x27, 0x4A, 0xD3, 0x69, +0x0F, 0x24, 0xA3, 0x43, 0xD3, 0x61, 0x26, 0x4B, 0x99, 0x68, 0x80, 0x20, 0x01, 0x43, 0x99, 0x60, 0x59, 0x68, 0x01, 0x43, +0x59, 0x60, 0x19, 0x68, 0x01, 0x43, 0x19, 0x60, 0x13, 0x69, 0xA3, 0x43, 0x13, 0x61, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, +0xEF, 0xFC, 0x01, 0x9C, 0x00, 0x9B, 0x1E, 0x00, 0x7A, 0x36, 0x9C, 0x22, 0x92, 0x00, 0x96, 0x42, 0x19, 0xD9, 0xF8, 0x3B, +0xFF, 0x3B, 0x1E, 0x00, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x80, 0x25, 0x2D, 0x05, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, +0xDB, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0xAB, 0x42, 0xF5, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xF2, 0xD0, +0x00, 0x9B, 0xB3, 0x42, 0xEF, 0xD3, 0x02, 0xB0, 0x70, 0xBD, 0xB3, 0x42, 0xE9, 0xD2, 0x80, 0x25, 0x2D, 0x05, 0x02, 0xE0, +0x00, 0x9B, 0xB3, 0x42, 0xF5, 0xD2, 0x69, 0x46, 0x01, 0xA8, 0xA4, 0xF7, 0xC1, 0xFC, 0x01, 0x9A, 0xA3, 0x1A, 0x1B, 0x01, +0x1B, 0x09, 0xAB, 0x42, 0xF2, 0xD9, 0x12, 0x1B, 0x12, 0x01, 0xEF, 0xD0, 0xE7, 0xE7, 0xC0, 0x46, 0x00, 0x30, 0x50, 0x40, +0x00, 0x40, 0x50, 0x40, 0x70, 0xB5, 0x10, 0x4B, 0x9A, 0x69, 0x10, 0x4B, 0x1A, 0x42, 0x0A, 0xD1, 0x0F, 0x4D, 0x10, 0x4C, +0x29, 0x68, 0x00, 0x20, 0xFA, 0xF7, 0xD0, 0xFC, 0x7B, 0xF7, 0x96, 0xFD, 0x23, 0x68, 0x01, 0x2B, 0xF6, 0xD0, 0x0C, 0x4A, +0x13, 0x68, 0x01, 0x33, 0x13, 0x60, 0x0B, 0x4B, 0x1B, 0x68, 0x03, 0x3B, 0x01, 0x2B, 0x00, 0xD9, 0x70, 0xBD, 0x03, 0x4A, +0x80, 0x23, 0x1B, 0x02, 0x91, 0x69, 0x0B, 0x43, 0x93, 0x61, 0xF7, 0xE7, 0x3C, 0x95, 0x16, 0x00, 0x01, 0x20, 0x00, 0x00, +0x58, 0xE6, 0x10, 0x00, 0x5C, 0xE6, 0x10, 0x00, 0x20, 0xE6, 0x10, 0x00, 0x50, 0xE0, 0x10, 0x00, 0x02, 0x38, 0x01, 0x28, +0x11, 0xD8, 0x09, 0x4A, 0x80, 0x23, 0x5B, 0x00, 0x08, 0x21, 0xD1, 0x50, 0x07, 0x49, 0x8B, 0x68, 0x07, 0x4A, 0x1A, 0x40, +0x80, 0x23, 0x9B, 0x02, 0x13, 0x43, 0x8B, 0x60, 0x22, 0x22, 0x0B, 0x6B, 0x13, 0x40, 0x02, 0x2B, 0xFB, 0xD1, 0x70, 0x47, +0x00, 0x00, 0x50, 0x40, 0x00, 0x60, 0x50, 0x40, 0xFF, 0xFF, 0xFB, 0xFF, 0x70, 0xB5, 0xA6, 0xF7, 0x3D, 0xFF, 0x04, 0x1E, +0x0D, 0xD1, 0x1A, 0x4B, 0x18, 0x68, 0x00, 0x28, 0x09, 0xD0, 0xEF, 0xF3, 0x10, 0x83, 0xDB, 0x07, 0x17, 0xD4, 0x72, 0xB6, +0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x62, 0xB6, 0x20, 0x00, 0x70, 0xBD, 0x13, 0x4B, 0x1D, 0x68, 0x00, 0x21, +0xCF, 0xF7, 0x7A, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x0E, 0x4A, 0x13, 0x60, +0x0E, 0x4B, 0x98, 0x47, 0xEC, 0xE7, 0x3E, 0x23, 0xC3, 0x5C, 0x00, 0x2B, 0xE9, 0xD1, 0x09, 0x4B, 0x1D, 0x68, 0x00, 0x21, +0xCF, 0xF7, 0x66, 0xFC, 0x2B, 0x6B, 0x5B, 0x00, 0x6A, 0x68, 0x9B, 0x18, 0x1B, 0x01, 0x1B, 0x09, 0x04, 0x4A, 0x13, 0x60, +0x04, 0x4B, 0x98, 0x47, 0xD9, 0xE7, 0xC0, 0x46, 0x28, 0x27, 0x16, 0x00, 0x24, 0x27, 0x16, 0x00, 0x18, 0x2C, 0x16, 0x00, +0x15, 0xE6, 0x0A, 0x00, 0x10, 0xB5, 0xA5, 0xF7, 0xC7, 0xFA, 0x00, 0x28, 0x0F, 0xD1, 0x0B, 0x4B, 0x19, 0x68, 0x00, 0x29, +0x0B, 0xD0, 0x0A, 0x4B, 0xCB, 0x61, 0x0A, 0x4B, 0x1C, 0x00, 0x41, 0x34, 0xFF, 0x34, 0x1A, 0x78, 0x09, 0x2A, 0x03, 0xD0, +0x40, 0x33, 0xA3, 0x42, 0xF9, 0xD1, 0x10, 0xBD, 0x0B, 0x69, 0x05, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x0B, 0x61, 0xF8, 0xE7, +0x18, 0x27, 0x16, 0x00, 0x51, 0x04, 0x10, 0x00, 0x70, 0xA6, 0x16, 0x00, 0x78, 0xEC, 0xFF, 0xFF, 0x10, 0xB5, 0x02, 0x00, +0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xC2, 0xFF, 0x04, 0x70, 0xCC, 0xF7, 0x1F, 0xFE, 0x10, 0xBD, +0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x02, 0x00, 0x0C, 0x00, 0x01, 0x23, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0xB4, 0xFF, +0x04, 0x70, 0xCC, 0xF7, 0x11, 0xFE, 0x10, 0xBD, 0x02, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x23, 0x13, 0x4A, 0x00, 0x21, +0x13, 0x48, 0x7A, 0xF7, 0xA7, 0xFF, 0x13, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x1B, 0x09, 0x12, 0x4A, 0x12, 0x78, 0x02, 0x2A, +0x0B, 0xD0, 0x01, 0x2A, 0x10, 0xD0, 0x0E, 0x4A, 0x2D, 0x23, 0xD3, 0x5C, 0x03, 0x71, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, +0xF5, 0xFD, 0x00, 0x20, 0x10, 0xBD, 0x0B, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x9B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xEE, 0xE7, +0x08, 0x4A, 0xD2, 0x5C, 0x80, 0x23, 0x5B, 0x00, 0x13, 0x43, 0x43, 0x80, 0xE7, 0xE7, 0xC0, 0x46, 0x2D, 0x0C, 0x00, 0x00, +0x01, 0x11, 0x00, 0x00, 0x60, 0x92, 0x16, 0x00, 0xB4, 0xE5, 0x10, 0x00, 0x30, 0xE0, 0x10, 0x00, 0x28, 0xE0, 0x10, 0x00, +0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x19, 0x78, 0x03, 0x4A, 0x2D, 0x23, 0xD1, 0x54, 0x00, 0x21, 0xFF, 0xF7, 0xB2, 0xFF, +0x00, 0x20, 0x10, 0xBD, 0x60, 0x92, 0x16, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0xD1, 0xF7, 0x96, 0xFF, +0x06, 0x00, 0x2C, 0x4B, 0x99, 0x6F, 0x00, 0x29, 0x15, 0xD0, 0xF8, 0x22, 0x20, 0x00, 0xD1, 0xF7, 0xBB, 0xFF, 0x00, 0x21, +0x00, 0x28, 0x0A, 0xD1, 0x26, 0x4A, 0x30, 0x23, 0xD3, 0x5C, 0x01, 0x2B, 0x21, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x86, 0xFF, +0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x21, 0x4B, 0x98, 0x6F, 0x7B, 0xF7, 0xBF, 0xF8, 0xFF, 0x20, 0x06, 0x40, 0xF8, 0x2E, +0x00, 0xD9, 0xF8, 0x26, 0x70, 0x1C, 0x00, 0x21, 0x7B, 0xF7, 0x12, 0xF8, 0x1A, 0x4B, 0x98, 0x67, 0x07, 0x21, 0x00, 0x28, +0xE2, 0xD0, 0x32, 0x00, 0x21, 0x00, 0xD1, 0xF7, 0x2F, 0xFE, 0x16, 0x4B, 0x9B, 0x6F, 0x00, 0x22, 0x9A, 0x55, 0x00, 0x21, +0xD8, 0xE7, 0x7F, 0x33, 0x5B, 0x00, 0x2F, 0x22, 0x00, 0x21, 0x12, 0x48, 0x7A, 0xF7, 0x2A, 0xFF, 0x06, 0x00, 0x01, 0xA9, +0x0D, 0x70, 0x2D, 0x0A, 0x4D, 0x70, 0xF8, 0x23, 0x8B, 0x70, 0x03, 0x22, 0xD1, 0xF7, 0x18, 0xFE, 0xF0, 0x1C, 0xF8, 0x22, +0x21, 0x00, 0xD1, 0xF7, 0x13, 0xFE, 0x0A, 0x4B, 0x01, 0x22, 0x1A, 0x70, 0x30, 0x00, 0x0C, 0x38, 0x08, 0x4B, 0x98, 0x47, +0x08, 0x4B, 0x5B, 0x7F, 0x5B, 0xB2, 0x04, 0x2B, 0xBE, 0xDC, 0x01, 0x33, 0x05, 0x4A, 0x53, 0x77, 0xBA, 0xE7, 0xC0, 0x46, +0x68, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0x68, 0xE6, 0x10, 0x00, 0xA5, 0x4B, 0x0D, 0x00, 0x24, 0x2A, 0x16, 0x00, +0xF8, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x16, 0x00, 0x1F, 0x00, 0x02, 0x20, 0x79, 0xF7, 0x46, 0xFE, 0x6B, 0x1E, 0x1C, 0x70, +0x63, 0x1E, 0x03, 0x2B, 0x22, 0xD8, 0x04, 0x2C, 0x10, 0xD0, 0x68, 0x1E, 0x16, 0x4B, 0x18, 0x61, 0x1E, 0x83, 0x5F, 0x61, +0x1B, 0x7F, 0xFF, 0x2B, 0x25, 0xD1, 0x13, 0x4B, 0x00, 0x22, 0x1A, 0x77, 0x71, 0x1C, 0x1A, 0x68, 0x54, 0x68, 0x11, 0x4A, +0xA0, 0x47, 0x1C, 0xE0, 0x2B, 0x78, 0x2F, 0x2B, 0xEB, 0xD1, 0x0F, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0xE7, 0xD0, 0x19, 0x23, +0x2B, 0x70, 0xE2, 0x33, 0x6B, 0x70, 0x0B, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xFD, 0x26, 0xDE, 0xE7, 0x09, 0x4D, 0x00, 0x23, +0x00, 0x22, 0x01, 0x21, 0x20, 0x00, 0xEE, 0x6E, 0xB0, 0x47, 0xED, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x01, 0x21, 0x20, 0x00, +0xA8, 0x47, 0xF8, 0xBD, 0x58, 0x1E, 0x16, 0x00, 0x19, 0x74, 0x08, 0x00, 0x68, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, +0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0xC0, 0xB5, 0x86, 0xB0, 0x04, 0x00, 0x0E, 0x00, 0x03, 0x92, 0xCE, 0xF7, +0x93, 0xFE, 0x07, 0x00, 0xB8, 0x4B, 0x1D, 0x25, 0x5D, 0x57, 0x2B, 0x00, 0x80, 0x33, 0x00, 0xD1, 0x61, 0xE1, 0x01, 0x3D, +0x6D, 0xB2, 0xB4, 0x4B, 0x5D, 0x77, 0x00, 0x28, 0x00, 0xD1, 0x18, 0xE1, 0x00, 0x2D, 0x00, 0xDA, 0x59, 0xE1, 0x80, 0x78, +0x0F, 0x23, 0x18, 0x40, 0x08, 0x28, 0x5F, 0xD8, 0x83, 0x00, 0xAE, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x05, 0x23, 0x99, 0x46, +0x67, 0xE0, 0x06, 0x28, 0x1E, 0xD0, 0x01, 0x2E, 0x00, 0xD8, 0x3B, 0xE1, 0x03, 0x9A, 0x53, 0x78, 0x1B, 0x02, 0x12, 0x78, +0x13, 0x43, 0x0B, 0x2B, 0x00, 0xD9, 0x22, 0xE1, 0xA5, 0x4A, 0xD2, 0x18, 0x12, 0x7E, 0x00, 0x2A, 0x00, 0xD1, 0x2D, 0xE1, +0xA2, 0x04, 0x37, 0xD4, 0xA2, 0x4A, 0x94, 0x42, 0x34, 0xD0, 0x27, 0xD8, 0xA1, 0x4A, 0x94, 0x42, 0x30, 0xD0, 0xA1, 0x4A, +0x94, 0x42, 0x00, 0xD0, 0x20, 0xE1, 0x2B, 0xE0, 0x05, 0x2E, 0x00, 0xD8, 0x1C, 0xE1, 0x9E, 0x4D, 0x00, 0x23, 0x99, 0x46, +0x07, 0xE0, 0x01, 0x23, 0x9C, 0x46, 0xE1, 0x44, 0x07, 0x35, 0x4B, 0x46, 0x07, 0x2B, 0x00, 0xD1, 0x10, 0xE1, 0x2B, 0x78, +0x00, 0x2B, 0xF4, 0xD0, 0x69, 0x1C, 0x06, 0x22, 0x03, 0x98, 0xD1, 0xF7, 0x2D, 0xFD, 0x00, 0x28, 0xED, 0xD1, 0x4B, 0x46, +0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x26, 0xE0, 0x90, 0x4A, 0x94, 0x42, 0x04, 0xD8, 0x90, 0x4A, +0x94, 0x42, 0x00, 0xD8, 0xF8, 0xE0, 0x03, 0xE0, 0x8E, 0x4A, 0x94, 0x42, 0x00, 0xD0, 0xF3, 0xE0, 0x1B, 0x02, 0x04, 0x22, +0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x14, 0xE0, 0x1B, 0x02, 0x01, 0x22, 0x13, 0x43, 0x9B, 0xB2, 0x99, 0x46, 0x0E, 0xE0, +0x87, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xA8, 0x47, 0xAF, 0xE0, 0x03, 0x23, 0x99, 0x46, 0x04, 0xE0, +0x02, 0x23, 0x99, 0x46, 0x01, 0xE0, 0x00, 0x23, 0x99, 0x46, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x00, 0x22, +0x1A, 0x80, 0x7E, 0x4B, 0x92, 0x46, 0x9C, 0x42, 0x59, 0xD0, 0x00, 0x2E, 0x00, 0xD1, 0xAD, 0xE0, 0x7D, 0x68, 0x00, 0x2D, +0x00, 0xD1, 0x9C, 0xE0, 0xBB, 0x78, 0x5B, 0x06, 0x65, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, +0x03, 0x99, 0x00, 0x20, 0xA8, 0x47, 0xC5, 0xB2, 0x01, 0x2D, 0x66, 0xD0, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, +0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x6F, 0x48, 0x7A, 0xF7, 0x00, 0xFE, 0x81, 0x46, 0x00, 0x2D, 0x07, 0xD0, 0x6A, 0x4B, +0xDB, 0x6E, 0x9B, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xD8, 0x47, 0x4B, 0x46, 0x00, 0x2B, 0x59, 0xD0, +0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x00, 0x2B, 0x0F, 0xD0, 0x7B, 0x68, 0x9B, 0x46, 0x00, 0x2B, +0x0B, 0xD0, 0xBB, 0x78, 0x5B, 0x06, 0x51, 0xD5, 0xB3, 0xB2, 0x0E, 0x22, 0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, +0x48, 0x46, 0xD8, 0x47, 0xC5, 0xB2, 0x00, 0x2D, 0x06, 0xD0, 0x58, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, +0x28, 0x00, 0xB0, 0x47, 0x48, 0x46, 0x7A, 0xF7, 0xF9, 0xFD, 0x54, 0x4B, 0x9C, 0x42, 0x4A, 0xD1, 0x53, 0x46, 0x00, 0x2B, +0x47, 0xD0, 0x50, 0x46, 0x7A, 0xF7, 0x3C, 0xFF, 0x43, 0xE0, 0x75, 0x1C, 0x01, 0x21, 0x28, 0x00, 0x7A, 0xF7, 0x92, 0xFE, +0x82, 0x46, 0x03, 0x99, 0x0B, 0x78, 0x03, 0x70, 0x72, 0x1E, 0x42, 0x70, 0x01, 0x31, 0x02, 0x30, 0xD1, 0xF7, 0xAE, 0xFC, +0xEE, 0xB2, 0x49, 0x48, 0x7C, 0xF7, 0xB6, 0xFE, 0x53, 0x46, 0x03, 0x93, 0x8F, 0xE7, 0xB3, 0xB2, 0x00, 0x95, 0x0E, 0x22, +0x02, 0xA9, 0x8C, 0x46, 0x62, 0x44, 0x03, 0x99, 0x00, 0x20, 0x7D, 0xF7, 0x57, 0xF8, 0x05, 0x00, 0x96, 0xE7, 0x21, 0x00, +0x40, 0x48, 0x7C, 0xF7, 0xA3, 0xFE, 0x00, 0x23, 0x12, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3E, 0x4D, 0xA8, 0x47, 0xC8, 0xE7, +0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x3B, 0x4D, 0xA8, 0x47, 0xC2, 0xE7, 0xB3, 0xB2, 0x5A, 0x46, 0x00, 0x92, 0x0E, 0x22, +0x62, 0x44, 0x03, 0x99, 0x48, 0x46, 0x7D, 0xF7, 0x3B, 0xF8, 0x05, 0x00, 0xAB, 0xE7, 0x00, 0x23, 0x01, 0x22, 0x21, 0x00, +0x00, 0x20, 0x32, 0x4C, 0xA0, 0x47, 0x06, 0xB0, 0x1C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xA3, 0x46, 0xF0, 0xBD, 0x0E, 0x23, +0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x27, 0x48, 0x7A, 0xF7, 0x71, 0xFD, 0x81, 0x46, +0x04, 0x25, 0x70, 0xE7, 0x0E, 0x23, 0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x22, 0x00, 0x49, 0x46, 0x21, 0x48, +0x7A, 0xF7, 0x64, 0xFD, 0x81, 0x46, 0x35, 0x00, 0x6B, 0xE7, 0x22, 0x4A, 0x13, 0x40, 0x1A, 0x00, 0x80, 0x3A, 0x92, 0xB2, +0x06, 0x2A, 0x09, 0xD8, 0x80, 0x3B, 0xD9, 0x00, 0xC9, 0x1A, 0x0F, 0x4A, 0x52, 0x18, 0x24, 0x32, 0x12, 0x78, 0x02, 0x2A, +0x00, 0xD1, 0x11, 0xE7, 0x21, 0x00, 0x1A, 0x48, 0x7C, 0xF7, 0x50, 0xFE, 0x03, 0x9B, 0x02, 0x22, 0x21, 0x00, 0x38, 0x00, +0x14, 0x4C, 0xA0, 0x47, 0xC3, 0xE7, 0x00, 0x28, 0xBB, 0xD0, 0x00, 0x23, 0x07, 0x22, 0x21, 0x00, 0x38, 0x00, 0x10, 0x4C, +0xA0, 0x47, 0xBA, 0xE7, 0x24, 0x2A, 0x16, 0x00, 0x2C, 0xD2, 0x10, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x2D, 0x0C, 0x00, 0x00, +0x06, 0x04, 0x00, 0x00, 0x1D, 0x04, 0x00, 0x00, 0xF0, 0xAA, 0x16, 0x00, 0x7C, 0x0C, 0x00, 0x00, 0x7A, 0x0C, 0x00, 0x00, +0x05, 0x14, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0x57, 0xFD, 0x00, 0x00, 0x05, 0x11, 0x00, 0x00, 0x14, 0xD2, 0x10, 0x00, +0x20, 0xD2, 0x10, 0x00, 0x7D, 0x4A, 0x0D, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0x08, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x20, +0x7B, 0xF7, 0x10, 0xFA, 0x08, 0x4C, 0xA1, 0x7A, 0x20, 0x89, 0x62, 0x68, 0xFF, 0xF7, 0x54, 0xFE, 0x60, 0x68, 0x00, 0x28, +0x03, 0xD0, 0x7A, 0xF7, 0x7F, 0xFE, 0x00, 0x22, 0x62, 0x60, 0x02, 0x48, 0x02, 0x4B, 0x98, 0x47, 0x10, 0xBD, 0xC0, 0x46, +0x58, 0x1E, 0x16, 0x00, 0xA5, 0x73, 0x08, 0x00, 0x30, 0xB5, 0x0C, 0x4C, 0x25, 0x68, 0x29, 0x60, 0x24, 0x68, 0x60, 0x60, +0xA2, 0x60, 0xE3, 0x60, 0x09, 0x4B, 0x0A, 0x4A, 0x98, 0x50, 0x0A, 0x48, 0x1A, 0x58, 0x0A, 0x43, 0x1A, 0x50, 0x04, 0x30, +0x1A, 0x58, 0x11, 0x43, 0x19, 0x50, 0x07, 0x49, 0x5A, 0x58, 0x01, 0x20, 0x02, 0x43, 0x5A, 0x50, 0x30, 0xBD, 0xC0, 0x46, +0xFC, 0xE1, 0x10, 0x00, 0x00, 0x00, 0x07, 0x40, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, +0x70, 0xB5, 0x0D, 0x00, 0x1A, 0x4C, 0x30, 0x21, 0x61, 0x5C, 0x01, 0x29, 0x04, 0xD0, 0x29, 0x00, 0x18, 0x4C, 0xA0, 0x47, +0x00, 0x20, 0x70, 0xBD, 0x14, 0x0A, 0x84, 0xF7, 0x99, 0xFD, 0x06, 0x1E, 0x1F, 0xD0, 0x6A, 0x88, 0xA9, 0x88, 0x14, 0x4B, +0x9C, 0x46, 0x61, 0x44, 0x00, 0x89, 0x60, 0x44, 0xD1, 0xF7, 0xB8, 0xFB, 0x08, 0x23, 0x00, 0x22, 0x21, 0x00, 0x10, 0x48, +0x7A, 0xF7, 0xBA, 0xFC, 0x33, 0x89, 0x43, 0x60, 0x2B, 0x88, 0x03, 0x80, 0x6B, 0x88, 0x43, 0x80, 0xCC, 0xF7, 0x12, 0xFB, +0x20, 0x00, 0x80, 0x30, 0x01, 0x21, 0x0A, 0x4B, 0x98, 0x47, 0xA8, 0x88, 0x84, 0xF7, 0xCA, 0xFD, 0xD8, 0xE7, 0x08, 0x4B, +0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEF, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x49, 0x86, 0x0A, 0x00, +0x00, 0x00, 0x61, 0x40, 0x06, 0x11, 0x00, 0x00, 0xC1, 0xDC, 0x09, 0x00, 0x28, 0x19, 0x16, 0x00, 0x42, 0x7A, 0x12, 0x02, +0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x83, 0x7A, 0x8B, 0x70, 0x70, 0x47, 0xC2, 0x7A, 0x12, 0x02, 0x83, 0x7A, 0x13, 0x43, +0x4B, 0x80, 0x42, 0x7A, 0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x83, 0x7A, 0x8B, 0x70, 0x42, 0x7A, +0x12, 0x02, 0x03, 0x7A, 0x13, 0x43, 0x0B, 0x80, 0x70, 0x47, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x00, 0x22, 0x02, 0x73, +0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, 0x01, 0x21, 0xA0, 0x47, 0x04, 0x20, 0x7A, 0xF7, 0x91, 0xF8, 0x10, 0xBD, +0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x01, 0x22, 0x02, 0x73, 0x08, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x03, 0x4A, +0xA0, 0x47, 0x04, 0x20, 0x79, 0xF7, 0xAC, 0xFB, 0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, +0x02, 0x22, 0x02, 0x73, 0x40, 0x68, 0x1A, 0x68, 0x14, 0x68, 0x01, 0x4A, 0xA0, 0x47, 0x10, 0xBD, 0x59, 0x78, 0x10, 0x00, +0x10, 0xB5, 0x03, 0x00, 0x03, 0x22, 0x02, 0x73, 0x0B, 0x30, 0x1A, 0x68, 0x14, 0x68, 0x02, 0x4A, 0x01, 0x21, 0xA0, 0x47, +0x10, 0xBD, 0xC0, 0x46, 0x59, 0x78, 0x10, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x01, 0x23, 0x10, 0x22, 0x00, 0x21, 0x0B, 0x48, +0x7A, 0xF7, 0x38, 0xFC, 0x00, 0x23, 0x03, 0x70, 0xCC, 0xF7, 0x94, 0xFA, 0x20, 0x00, 0x08, 0x30, 0x02, 0x22, 0x00, 0x21, +0x78, 0xF7, 0xB2, 0xFC, 0xE3, 0x7A, 0xA3, 0x72, 0x20, 0x00, 0xFF, 0xF7, 0xDB, 0xFF, 0x04, 0x20, 0x7A, 0xF7, 0x4A, 0xF8, +0x10, 0xBD, 0xC0, 0x46, 0x03, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x06, 0x20, 0x7B, 0xF7, 0x1A, 0xF9, 0x16, 0x4C, 0x17, 0x49, +0x20, 0x00, 0xFF, 0xF7, 0x83, 0xFF, 0xA4, 0x7A, 0x00, 0x2C, 0x09, 0xD1, 0x12, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, +0xFF, 0xF7, 0x56, 0xFD, 0x20, 0x00, 0xFF, 0xF7, 0x93, 0xFF, 0x10, 0xBD, 0x0D, 0x4B, 0x18, 0x89, 0xCD, 0xF7, 0x9C, 0xFA, +0x84, 0x42, 0x03, 0xD9, 0x0A, 0x48, 0xFF, 0xF7, 0xC3, 0xFF, 0xF4, 0xE7, 0x08, 0x4C, 0xA0, 0x7A, 0x01, 0x21, 0x7A, 0xF7, +0xCF, 0xFC, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x20, 0x00, 0xA1, 0x7A, 0xFF, 0xF7, 0x9C, 0xFF, 0xE7, 0xE7, 0x02, 0x48, +0xFF, 0xF7, 0xB2, 0xFF, 0xE3, 0xE7, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x82, 0xB0, +0x04, 0x00, 0x0E, 0x4B, 0x01, 0x93, 0x01, 0x00, 0x08, 0x31, 0x04, 0x22, 0x01, 0xA8, 0xD1, 0xF7, 0xB5, 0xFA, 0x00, 0x28, +0x0B, 0xD0, 0x04, 0x20, 0x79, 0xF7, 0x2A, 0xFB, 0x63, 0x7A, 0x23, 0x72, 0xA3, 0x7A, 0x63, 0x72, 0xE3, 0x7A, 0xA3, 0x72, +0x00, 0x20, 0x02, 0xB0, 0x10, 0xBD, 0x00, 0x22, 0x00, 0x21, 0x03, 0x48, 0xCD, 0xF7, 0x6C, 0xFA, 0x01, 0x20, 0xF6, 0xE7, +0x01, 0x03, 0x0C, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x29, 0x0B, 0xD0, 0x01, 0x29, 0x02, 0xD0, +0x03, 0x7B, 0x00, 0x2B, 0x03, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x7C, 0xFF, 0x10, 0xBD, 0xFF, 0xF7, 0x3F, 0xFF, 0xFB, 0xE7, +0x03, 0x7B, 0x02, 0x2B, 0x44, 0xD0, 0x0F, 0xD8, 0x00, 0x2B, 0x17, 0xD0, 0x40, 0x7B, 0x02, 0x28, 0x25, 0xD0, 0x03, 0x28, +0x27, 0xD0, 0x01, 0x28, 0x1D, 0xD0, 0xA1, 0x7B, 0x34, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xE7, 0xE7, +0x03, 0x2B, 0x59, 0xD1, 0xFF, 0xF7, 0xB4, 0xFF, 0x00, 0x28, 0x51, 0xD0, 0x20, 0x00, 0xFF, 0xF7, 0x21, 0xFF, 0xDD, 0xE7, +0xC3, 0x7A, 0x43, 0x73, 0x5A, 0x1E, 0x02, 0x2A, 0x04, 0xD8, 0x2B, 0x4A, 0xD1, 0x5C, 0xFF, 0xF7, 0x27, 0xFF, 0xD3, 0xE7, +0xFF, 0xF7, 0x4E, 0xFF, 0xD0, 0xE7, 0x05, 0x30, 0x7B, 0xF7, 0x5E, 0xF8, 0xCC, 0xE7, 0x08, 0x20, 0x7B, 0xF7, 0x5A, 0xF8, +0xC8, 0xE7, 0x21, 0x00, 0x08, 0x31, 0x20, 0x00, 0xFF, 0xF7, 0xFD, 0xFE, 0xA1, 0x7A, 0x20, 0x89, 0xCD, 0xF7, 0x2E, 0xFC, +0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0xA1, 0x7A, 0x20, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0xB7, 0xE7, 0x20, 0x00, 0xFF, 0xF7, +0x31, 0xFF, 0xB3, 0xE7, 0x40, 0x7B, 0x02, 0x28, 0x0E, 0xD0, 0x03, 0x28, 0x15, 0xD0, 0x01, 0x28, 0x06, 0xD0, 0xA1, 0x7B, +0x13, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0xA0, 0x47, 0xA5, 0xE7, 0x06, 0x30, 0x7B, 0xF7, 0x33, 0xF8, 0xA1, 0xE7, +0x61, 0x89, 0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0xB9, 0xFB, 0x20, 0x00, 0xFF, 0xF7, 0xDC, 0xFE, 0x98, 0xE7, 0xA1, 0x7A, +0x20, 0x89, 0x62, 0x68, 0xCD, 0xF7, 0x2E, 0xFC, 0x20, 0x00, 0xFF, 0xF7, 0xD3, 0xFE, 0x8F, 0xE7, 0x20, 0x00, 0xFF, 0xF7, +0xFB, 0xFE, 0x8B, 0xE7, 0x03, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x84, 0xE7, 0xC0, 0x46, +0x28, 0x19, 0x16, 0x00, 0xC8, 0xDF, 0x10, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x03, 0x05, 0x1B, 0x0D, 0x82, 0x0B, 0x0B, 0x2B, +0x1C, 0xD8, 0x00, 0x2A, 0x4C, 0xD1, 0x19, 0x02, 0x04, 0x22, 0x0A, 0x43, 0x92, 0xB2, 0xF8, 0x21, 0x09, 0x01, 0x08, 0x42, +0x1F, 0xD1, 0xFB, 0x21, 0xFF, 0x2A, 0x46, 0xD0, 0x8C, 0x42, 0x44, 0xD8, 0xFF, 0x23, 0x13, 0x40, 0x02, 0x2B, 0x26, 0xD9, +0x04, 0x2B, 0x26, 0xD1, 0xB3, 0xF7, 0x8A, 0xFC, 0x00, 0x28, 0x3A, 0xD0, 0x25, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x46, 0xE0, +0x01, 0x2A, 0x31, 0xD0, 0x00, 0x2A, 0x32, 0xD1, 0xF8, 0x22, 0x12, 0x01, 0x10, 0x42, 0x2E, 0xD0, 0x00, 0x21, 0xFF, 0x22, +0x86, 0x2B, 0xE1, 0xD8, 0x00, 0xE0, 0xFB, 0x21, 0x80, 0x3B, 0xDD, 0x00, 0xED, 0x1A, 0x1C, 0x48, 0x40, 0x19, 0x24, 0x30, +0x00, 0x78, 0x02, 0x28, 0xD6, 0xD1, 0x1B, 0x02, 0x01, 0x22, 0x1A, 0x43, 0x92, 0xB2, 0x18, 0x49, 0xD2, 0xE7, 0x00, 0x2B, +0x06, 0xD1, 0x17, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x10, 0xE0, 0x84, 0xF7, 0xE0, 0xFB, +0x00, 0x28, 0x03, 0xD0, 0x0E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x18, 0xE0, 0x10, 0x48, 0x7C, 0xF7, 0xEB, 0xFB, 0x04, 0xE0, +0x01, 0x2A, 0x02, 0xD1, 0x0B, 0x4B, 0x9C, 0x42, 0xEE, 0xD9, 0x01, 0x23, 0x1A, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x7A, 0xF7, +0xDB, 0xFA, 0x01, 0x25, 0x05, 0x70, 0xCC, 0xF7, 0x37, 0xF9, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xA5, 0xFB, 0x07, 0x4B, +0x9D, 0x77, 0x70, 0xBD, 0x00, 0x00, 0x61, 0x40, 0xCC, 0xAA, 0x16, 0x00, 0xFD, 0x03, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, +0x50, 0xD2, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x24, 0x2A, 0x16, 0x00, 0x10, 0xB5, 0x08, 0x20, 0x7A, 0xF7, 0xBA, 0xFF, +0x10, 0x4C, 0x11, 0x49, 0x20, 0x00, 0xFF, 0xF7, 0x2B, 0xFE, 0x61, 0x89, 0x00, 0x29, 0x0E, 0xD0, 0x20, 0x89, 0xFF, 0xF7, +0x77, 0xFF, 0x60, 0x60, 0x00, 0x28, 0x04, 0xD0, 0x09, 0x48, 0x41, 0x89, 0xFF, 0xF7, 0x52, 0xFE, 0x0C, 0xE0, 0x20, 0x00, +0xFF, 0xF7, 0x68, 0xFE, 0x08, 0xE0, 0x05, 0x4C, 0x20, 0x89, 0x00, 0x22, 0x00, 0x21, 0xCD, 0xF7, 0x01, 0xFB, 0x20, 0x00, +0xFF, 0xF7, 0x24, 0xFE, 0x10, 0xBD, 0xC0, 0x46, 0x58, 0x1E, 0x16, 0x00, 0x60, 0x1E, 0x16, 0x00, 0x10, 0xB5, 0x7F, 0xF7, +0xBD, 0xFD, 0x06, 0x49, 0x06, 0x20, 0x7A, 0xF7, 0x47, 0xFF, 0x05, 0x49, 0x07, 0x20, 0x7A, 0xF7, 0x43, 0xFF, 0x04, 0x49, +0x08, 0x20, 0x7A, 0xF7, 0x3F, 0xFF, 0x10, 0xBD, 0xA5, 0x77, 0x10, 0x00, 0xB9, 0x75, 0x10, 0x00, 0x65, 0x7A, 0x10, 0x00, +0x10, 0xB5, 0x0A, 0x00, 0x41, 0x23, 0x00, 0x21, 0x0C, 0x48, 0x7A, 0xF7, 0x7B, 0xFA, 0x04, 0x00, 0x01, 0x30, 0x28, 0x22, +0x0A, 0x49, 0xD1, 0xF7, 0x6D, 0xF9, 0xE2, 0x79, 0x2F, 0x23, 0x13, 0x40, 0xE3, 0x71, 0x20, 0x00, 0x29, 0x30, 0x18, 0x22, +0x00, 0x21, 0x78, 0xF7, 0xEF, 0xFA, 0x00, 0x23, 0x23, 0x70, 0x20, 0x00, 0xCC, 0xF7, 0xC6, 0xF8, 0x00, 0x20, 0x10, 0xBD, +0x01, 0x11, 0x00, 0x00, 0xA4, 0xB5, 0x0D, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x0D, 0x00, 0x90, 0x46, 0x06, 0x0A, +0xB2, 0x00, 0x11, 0x4B, 0xD7, 0x58, 0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x7A, 0xF7, 0x51, 0xFA, 0x04, 0x00, +0x43, 0x46, 0x03, 0x70, 0x2D, 0x02, 0x81, 0x35, 0xFF, 0x35, 0x75, 0x19, 0x45, 0x80, 0x00, 0x23, 0x83, 0x72, 0x88, 0x23, +0xFF, 0x33, 0xFB, 0x5C, 0xC3, 0x72, 0x39, 0x00, 0x72, 0x31, 0x04, 0x30, 0x06, 0x22, 0xD1, 0xF7, 0x35, 0xF9, 0x20, 0x00, +0xCC, 0xF7, 0x9A, 0xF8, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, +0x70, 0xB5, 0x05, 0x00, 0x0E, 0x00, 0x04, 0x78, 0x02, 0x2C, 0x21, 0xD8, 0x00, 0x2C, 0x04, 0xD1, 0x14, 0x4A, 0x30, 0x23, +0x00, 0x21, 0xD1, 0x54, 0x1B, 0xE0, 0x03, 0x20, 0x88, 0xF7, 0x2E, 0xFC, 0x04, 0x1E, 0x1C, 0xD1, 0x2B, 0x78, 0x0F, 0x49, +0x30, 0x22, 0x8B, 0x54, 0x01, 0x2B, 0x10, 0xD1, 0xDF, 0x20, 0x00, 0x21, 0x80, 0x00, 0x7A, 0xF7, 0xE7, 0xFA, 0x0B, 0x4B, +0x18, 0x60, 0x0B, 0x4A, 0x24, 0x23, 0x01, 0x21, 0xD1, 0x54, 0x00, 0x21, 0x00, 0x20, 0x92, 0xF7, 0xA1, 0xF8, 0x00, 0xE0, +0x12, 0x24, 0x21, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x3B, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x0C, 0x24, 0xF7, 0xE7, 0xC0, 0x46, +0x68, 0x9E, 0x16, 0x00, 0x64, 0xA2, 0x16, 0x00, 0xCC, 0xAA, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, +0x5B, 0x68, 0x02, 0x00, 0x06, 0x21, 0x01, 0x20, 0x98, 0x47, 0x20, 0x78, 0x63, 0x78, 0x1B, 0x02, 0x03, 0x43, 0xA0, 0x78, +0x00, 0x04, 0x03, 0x43, 0xE0, 0x78, 0x00, 0x06, 0x18, 0x43, 0x23, 0x79, 0x61, 0x79, 0x09, 0x02, 0x19, 0x43, 0xA4, 0xF7, +0xFF, 0xF8, 0x20, 0x00, 0xB3, 0xF7, 0x3C, 0xFF, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x10, 0xFA, 0x00, 0x20, 0x70, 0xBD, +0x94, 0x92, 0x16, 0x00, 0x10, 0x4A, 0xFF, 0x21, 0x13, 0x68, 0x8B, 0x43, 0x0F, 0x48, 0x00, 0x78, 0x03, 0x43, 0x80, 0x20, +0x03, 0x43, 0x0E, 0x48, 0x03, 0x60, 0x0E, 0x4B, 0x1B, 0x78, 0x1B, 0x01, 0x0B, 0x40, 0xD0, 0x68, 0x88, 0x43, 0x03, 0x43, +0x0B, 0x49, 0x0B, 0x60, 0x0B, 0x4B, 0x00, 0x21, 0x19, 0x60, 0x13, 0x69, 0x0A, 0x4A, 0x13, 0x40, 0x0A, 0x4A, 0x13, 0x60, +0x0A, 0x4B, 0x0B, 0x4A, 0x1A, 0x60, 0x0B, 0x4A, 0x1A, 0x60, 0x70, 0x47, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, +0x08, 0x01, 0x60, 0x40, 0xF7, 0xE8, 0x10, 0x00, 0x28, 0x10, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, 0xFF, 0x0F, 0xF0, 0xFF, +0x34, 0x08, 0x62, 0x40, 0x00, 0x00, 0x62, 0x40, 0x00, 0x01, 0x0A, 0x01, 0x00, 0x01, 0x0F, 0x01, 0x0B, 0x4B, 0x1B, 0x78, +0x00, 0x2B, 0x11, 0xD1, 0x0A, 0x4B, 0x1B, 0x68, 0x03, 0x60, 0x0A, 0x4B, 0x1B, 0x68, 0x43, 0x60, 0x09, 0x4B, 0x1B, 0x68, +0x83, 0x60, 0x09, 0x4B, 0x1B, 0x68, 0xC3, 0x60, 0x08, 0x4B, 0x1B, 0x68, 0x03, 0x61, 0x02, 0x4B, 0x01, 0x22, 0x1A, 0x70, +0x70, 0x47, 0xC0, 0x46, 0xD3, 0xE6, 0x10, 0x00, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, +0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0x09, 0x4B, 0x02, 0x68, 0x1A, 0x60, 0x09, 0x4B, 0x42, 0x68, 0x1A, 0x60, +0x08, 0x4B, 0x82, 0x68, 0x1A, 0x60, 0x08, 0x4B, 0xC2, 0x68, 0x1A, 0x60, 0x02, 0x69, 0x07, 0x4B, 0x1A, 0x60, 0x07, 0x4B, +0x00, 0x22, 0x1A, 0x70, 0x70, 0x47, 0xC0, 0x46, 0x08, 0x01, 0x60, 0x40, 0x00, 0x00, 0x62, 0x40, 0x1C, 0x10, 0x62, 0x40, +0x28, 0x10, 0x62, 0x40, 0x34, 0x08, 0x62, 0x40, 0xD3, 0xE6, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x03, 0x78, +0x00, 0x2B, 0x17, 0xD0, 0x02, 0x20, 0xF9, 0xF7, 0x8D, 0xFD, 0x0E, 0x48, 0xFF, 0xF7, 0xB0, 0xFF, 0x62, 0x78, 0x0D, 0x4B, +0x1A, 0x70, 0xA2, 0x78, 0x0C, 0x4B, 0x1A, 0x70, 0xFF, 0xF7, 0x70, 0xFF, 0x21, 0x78, 0x0B, 0x48, 0x7C, 0xF7, 0x46, 0xFA, +0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0x82, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0xFF, 0xF7, 0xBF, 0xFF, 0x01, 0x20, +0xF9, 0xF7, 0x72, 0xFD, 0xEE, 0xE7, 0xC0, 0x46, 0xE4, 0xE6, 0x10, 0x00, 0x14, 0xE7, 0x10, 0x00, 0xF7, 0xE8, 0x10, 0x00, +0x5C, 0xD2, 0x10, 0x00, 0x00, 0x23, 0x03, 0x73, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x88, +0x12, 0x21, 0x15, 0x2B, 0x04, 0xD9, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x01, 0x9A, 0x82, 0x00, 0x21, 0xFF, 0xF7, 0x50, 0xF9, +0x00, 0x20, 0x10, 0xBD, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, +0x0B, 0xD0, 0x29, 0x00, 0x20, 0x00, 0x0D, 0x4B, 0x98, 0x47, 0x0D, 0x4B, 0x80, 0x22, 0x12, 0x01, 0x1A, 0x83, 0x12, 0x22, +0x5A, 0x83, 0x00, 0x20, 0x70, 0xBD, 0xFA, 0xF7, 0x09, 0xFC, 0x00, 0x28, 0xEF, 0xD1, 0x23, 0x78, 0x9B, 0x07, 0xEC, 0xD5, +0x05, 0x4B, 0x80, 0x22, 0x92, 0x00, 0x1A, 0x83, 0xEF, 0x3A, 0xFF, 0x3A, 0x5A, 0x83, 0xE4, 0xE7, 0x50, 0xE0, 0x10, 0x00, +0x15, 0x28, 0x09, 0x00, 0x68, 0x9E, 0x16, 0x00, 0x70, 0xB5, 0x0C, 0x00, 0x0B, 0x4A, 0x8C, 0x23, 0xD3, 0x5C, 0x0C, 0x25, +0x01, 0x2B, 0x05, 0xD0, 0x29, 0x00, 0x20, 0x00, 0xFF, 0xF7, 0x18, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xA4, 0xF7, 0xB8, 0xFC, +0x05, 0x1E, 0xF5, 0xD0, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, 0xC0, 0x46, +0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, 0x01, 0x21, 0x99, 0x42, +0x9B, 0x41, 0x11, 0x31, 0x19, 0x40, 0xFF, 0xF7, 0xFB, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, +0x08, 0x00, 0x1C, 0x00, 0x47, 0x4B, 0x9C, 0x42, 0x43, 0xD0, 0x23, 0xD8, 0x46, 0x4B, 0x9C, 0x42, 0x51, 0xD0, 0x13, 0xD8, +0x45, 0x4B, 0x9C, 0x42, 0x45, 0xD0, 0x45, 0x4B, 0x9C, 0x42, 0x04, 0xD1, 0x43, 0x49, 0xFF, 0xF7, 0x43, 0xF9, 0x00, 0x25, +0x6A, 0xE0, 0x42, 0x4B, 0x9C, 0x42, 0x00, 0xD0, 0x70, 0xE0, 0x40, 0x49, 0xFF, 0xF7, 0xB6, 0xFF, 0x00, 0x25, 0x61, 0xE0, +0x3E, 0x4B, 0x9C, 0x42, 0x3E, 0xD0, 0x3E, 0x4B, 0x9C, 0x42, 0x65, 0xD1, 0x3C, 0x49, 0x00, 0x20, 0xFF, 0xF7, 0x16, 0xFE, +0x00, 0x25, 0x55, 0xE0, 0x3A, 0x4B, 0x9C, 0x42, 0x20, 0xD0, 0x0A, 0xD9, 0x39, 0x4B, 0x9C, 0x42, 0x12, 0xD0, 0x39, 0x4B, +0x9C, 0x42, 0x55, 0xD1, 0x19, 0x00, 0xFF, 0xF7, 0xDB, 0xF8, 0x00, 0x25, 0x46, 0xE0, 0x36, 0x4B, 0x9C, 0x42, 0x28, 0xD0, +0x35, 0x4B, 0x9C, 0x42, 0x2A, 0xD1, 0x34, 0x49, 0xFF, 0xF7, 0x84, 0xFE, 0x00, 0x25, 0x3B, 0xE0, 0x2E, 0x49, 0xFF, 0xF7, +0x01, 0xF9, 0x00, 0x25, 0x36, 0xE0, 0x24, 0x49, 0xFF, 0xF7, 0x42, 0xFE, 0x00, 0x25, 0x31, 0xE0, 0x28, 0x49, 0xFF, 0xF7, +0x15, 0xFF, 0x00, 0x25, 0x2C, 0xE0, 0x00, 0x23, 0x0B, 0x73, 0x20, 0x4B, 0x28, 0x00, 0x29, 0x4D, 0xA8, 0x47, 0x05, 0x00, +0x24, 0xE0, 0x1C, 0x49, 0xFF, 0xF7, 0x3A, 0xFF, 0x00, 0x25, 0x1F, 0xE0, 0x1D, 0x49, 0xFF, 0xF7, 0x47, 0xFF, 0x00, 0x25, +0x1A, 0xE0, 0x20, 0x49, 0xFF, 0xF7, 0x88, 0xFF, 0x00, 0x25, 0x15, 0xE0, 0x23, 0x00, 0x28, 0x00, 0x1E, 0x4D, 0xA8, 0x47, +0x05, 0x00, 0x1E, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x1D, 0x4B, 0x08, 0x22, 0x21, 0x00, 0x91, 0x43, 0x99, 0x42, 0x04, 0xD1, +0x02, 0x20, 0xF9, 0xF7, 0x81, 0xFC, 0xFA, 0xF7, 0x63, 0xF9, 0x19, 0x4B, 0x9C, 0x42, 0x05, 0xD0, 0x21, 0x00, 0x18, 0x48, +0x7C, 0xF7, 0x40, 0xF9, 0x28, 0x00, 0x70, 0xBD, 0x01, 0x20, 0xF9, 0xF7, 0x73, 0xFC, 0xF5, 0xE7, 0x23, 0x00, 0x01, 0x00, +0x28, 0x00, 0x0E, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xE0, 0xE7, 0xC0, 0x46, 0x02, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, +0x05, 0x04, 0x00, 0x00, 0x13, 0x0C, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x1A, 0x0C, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, +0xC6, 0xFC, 0x00, 0x00, 0xC7, 0xFC, 0x00, 0x00, 0xC9, 0xFC, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x70, 0xFC, 0x00, 0x00, +0x1D, 0x0C, 0x09, 0x00, 0x06, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, 0x6C, 0xD2, 0x10, 0x00, +0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x04, 0x23, 0x02, 0x00, 0x00, 0x21, 0x03, 0x48, 0x7A, 0xF7, 0x03, 0xF8, 0x05, 0x70, +0x44, 0x80, 0xCB, 0xF7, 0x5F, 0xFE, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x10, 0x00, 0x1A, 0x88, +0x0C, 0x21, 0xFF, 0xF7, 0xE9, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, +0x45, 0x46, 0xE0, 0xB5, 0x83, 0xB0, 0x80, 0x46, 0x0C, 0x00, 0x91, 0x46, 0x0F, 0x0A, 0xBA, 0x00, 0x2E, 0x4B, 0xD5, 0x58, +0x08, 0x00, 0x7A, 0xF7, 0xB7, 0xFB, 0x02, 0x26, 0x00, 0x28, 0x19, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x4F, 0xD0, +0x3C, 0x23, 0xEE, 0x5C, 0x02, 0x2E, 0x03, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x00, 0x2B, 0x1B, 0xD1, 0xFA, 0x21, 0x49, 0x01, +0xA9, 0x83, 0xFF, 0xB2, 0x36, 0x23, 0xEA, 0x5C, 0x38, 0x00, 0xA1, 0xF7, 0x6D, 0xFE, 0xA9, 0x8B, 0x38, 0x00, 0xAB, 0xF7, +0x31, 0xFC, 0x00, 0x26, 0x43, 0x46, 0x1A, 0x88, 0x31, 0x00, 0x48, 0x46, 0xFF, 0xF7, 0xB2, 0xFF, 0x00, 0x20, 0x03, 0xB0, +0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0xFB, 0xB2, 0x9B, 0x46, 0x06, 0x23, 0x6B, 0x44, +0x9A, 0x46, 0x6B, 0x46, 0x5A, 0x1D, 0x51, 0x46, 0x58, 0x46, 0x8B, 0xF7, 0x65, 0xFE, 0x43, 0x46, 0x5A, 0x88, 0x53, 0x46, +0x19, 0x88, 0x8A, 0x42, 0x13, 0xD9, 0x6B, 0x46, 0x05, 0x33, 0x1B, 0x78, 0x00, 0x2B, 0xCD, 0xD0, 0x4B, 0x43, 0x9A, 0x42, +0xCA, 0xD8, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x58, 0x46, 0xAB, 0xF7, 0x73, 0xFA, 0x22, 0x00, 0x21, 0x00, 0x07, 0x48, +0x79, 0xF7, 0xD2, 0xFF, 0xBE, 0xE7, 0x43, 0x46, 0x1A, 0x88, 0x12, 0x21, 0x48, 0x46, 0xFF, 0xF7, 0x7F, 0xFF, 0xC5, 0xE7, +0x0C, 0x26, 0xC3, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x22, 0x06, 0x00, 0x00, 0xF0, 0xB5, 0x93, 0xB0, 0x01, 0x90, 0x0C, 0x00, +0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x37, 0x4B, 0xD5, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x4E, 0xFB, 0x04, 0x28, 0x06, 0xD0, +0x09, 0x28, 0x18, 0xD0, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x42, 0xFB, 0x10, 0xE0, 0x3C, 0x22, 0x30, 0x49, 0x03, 0xA8, +0xD0, 0xF7, 0x62, 0xFE, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x38, 0xFB, 0x2D, 0x4A, 0xE8, 0x23, 0xD5, 0x58, 0x03, 0xAB, +0x01, 0x22, 0x01, 0x21, 0x20, 0x00, 0xA8, 0x47, 0x00, 0x20, 0x13, 0xB0, 0xF0, 0xBD, 0x21, 0x00, 0x28, 0x48, 0x79, 0xF7, +0x0F, 0xFF, 0x01, 0x21, 0x20, 0x00, 0x7A, 0xF7, 0xC9, 0xFA, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x21, 0xFB, 0xBC, 0x23, +0x5B, 0x00, 0xEB, 0x5C, 0xDB, 0x43, 0x9B, 0x07, 0x21, 0xD1, 0x00, 0x23, 0x01, 0x9A, 0x93, 0x71, 0xFF, 0xB2, 0x29, 0x00, +0x38, 0x31, 0x38, 0x00, 0x88, 0xF7, 0x70, 0xF9, 0x00, 0x28, 0x1C, 0xD0, 0x1B, 0x48, 0x7C, 0xF7, 0x3F, 0xF8, 0x01, 0x23, +0xAF, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x43, 0x22, 0xAB, 0x54, 0x20, 0x00, 0x93, 0xF7, 0xA0, 0xF9, 0x88, 0xF7, 0x64, 0xFA, +0x00, 0x28, 0x19, 0xD1, 0xC4, 0x20, 0x22, 0x00, 0x21, 0x00, 0xC0, 0x00, 0x79, 0xF7, 0x68, 0xFF, 0xC8, 0xE7, 0x22, 0x00, +0x21, 0x00, 0x10, 0x48, 0x79, 0xF7, 0x62, 0xFF, 0xD7, 0xE7, 0x0F, 0x48, 0x7C, 0xF7, 0x22, 0xF8, 0x44, 0x23, 0x01, 0x22, +0xEA, 0x54, 0x0B, 0x3B, 0xEA, 0x5C, 0x33, 0x21, 0x38, 0x00, 0xA1, 0xF7, 0x39, 0xFC, 0xE1, 0xE7, 0x22, 0x00, 0x21, 0x00, +0x08, 0x48, 0x79, 0xF7, 0x4F, 0xFF, 0xDF, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x80, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, +0x06, 0x06, 0x00, 0x00, 0x74, 0xD2, 0x10, 0x00, 0x14, 0x06, 0x00, 0x00, 0x7C, 0xD2, 0x10, 0x00, 0x1D, 0x06, 0x00, 0x00, +0x70, 0xB5, 0x04, 0x00, 0x0E, 0x00, 0x15, 0x00, 0x41, 0x88, 0x80, 0x23, 0x1B, 0x01, 0x99, 0x42, 0x06, 0xD3, 0x22, 0x88, +0x0C, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xE4, 0xFE, 0x00, 0x20, 0x70, 0xBD, 0x03, 0x48, 0x7B, 0xF7, 0xEF, 0xFF, 0x30, 0x0A, +0x00, 0x21, 0xAB, 0xF7, 0xA7, 0xF8, 0xF0, 0xE7, 0x84, 0xD2, 0x10, 0x00, 0x70, 0xB5, 0x0E, 0x00, 0x15, 0x00, 0x07, 0x23, +0x02, 0x00, 0x00, 0x21, 0x06, 0x48, 0x79, 0xF7, 0xDB, 0xFE, 0x04, 0x00, 0x06, 0x70, 0x01, 0x30, 0x06, 0x22, 0x29, 0x00, +0xD0, 0xF7, 0xCC, 0xFD, 0x20, 0x00, 0xCB, 0xF7, 0x31, 0xFD, 0x70, 0xBD, 0x01, 0x11, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, +0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x22, 0x4B, 0xD4, 0x58, 0x08, 0x00, 0x7A, 0xF7, 0x98, 0xFA, +0x00, 0x28, 0x1A, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x16, 0xD9, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, +0x03, 0xD1, 0x36, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x00, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x81, 0xFA, 0x36, 0x23, +0xE3, 0x5C, 0x00, 0x2B, 0x11, 0xD1, 0x2A, 0x00, 0x29, 0x00, 0x14, 0x48, 0x79, 0xF7, 0xE6, 0xFE, 0x03, 0xE0, 0x02, 0x21, +0x30, 0x00, 0x91, 0xF7, 0x73, 0xFA, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x0C, 0x21, 0x30, 0x00, 0x91, 0xF7, 0x6C, 0xFA, +0xF7, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0x93, 0xFE, 0x05, 0x00, 0x00, 0x23, 0x03, 0x70, +0x01, 0x9B, 0x1B, 0x88, 0x43, 0x80, 0xF8, 0xB2, 0xAB, 0xF7, 0x32, 0xFA, 0xC0, 0x03, 0x40, 0x0C, 0xA8, 0x80, 0x28, 0x00, +0xCB, 0xF7, 0xE4, 0xFC, 0xE1, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x16, 0x06, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, +0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x16, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x31, 0x4A, 0x9F, 0x58, 0x08, 0x00, +0x7A, 0xF7, 0x46, 0xFA, 0x00, 0x28, 0x53, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x02, 0x24, 0x03, 0x28, 0x4F, 0xD9, 0x01, 0x99, +0x4B, 0x88, 0xA8, 0x22, 0xD2, 0x00, 0x10, 0x34, 0x93, 0x42, 0x48, 0xD8, 0xDA, 0x07, 0x46, 0xD4, 0x8A, 0x88, 0x05, 0x2A, +0x43, 0xD9, 0xD0, 0x07, 0x41, 0xD4, 0x08, 0x00, 0xC9, 0x88, 0x00, 0x29, 0x3D, 0xD0, 0x00, 0x89, 0x84, 0x46, 0x28, 0x28, +0x39, 0xD8, 0x58, 0x08, 0x81, 0x42, 0x36, 0xD8, 0x93, 0x42, 0x34, 0xD3, 0x61, 0x44, 0x49, 0x00, 0x99, 0x42, 0x30, 0xD2, +0x7B, 0x8C, 0x06, 0x3C, 0x5B, 0x07, 0x2C, 0xD5, 0x3C, 0x23, 0xFC, 0x5C, 0x00, 0x2C, 0x01, 0xD0, 0x0C, 0x24, 0x26, 0xE0, +0x38, 0x00, 0x54, 0x30, 0x07, 0x21, 0xA1, 0xF7, 0x47, 0xFA, 0x00, 0x28, 0x01, 0xD1, 0x1A, 0x24, 0x1D, 0xE0, 0x08, 0x23, +0x2A, 0x00, 0x29, 0x00, 0x11, 0x48, 0x79, 0xF7, 0x31, 0xFE, 0x01, 0x9B, 0x5A, 0x88, 0x02, 0x80, 0x9B, 0x88, 0x43, 0x80, +0xC0, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x00, 0xD9, 0x01, 0x80, 0xC0, 0x22, 0x52, 0x00, 0x93, 0x42, 0x00, 0xD9, 0x42, 0x80, +0x01, 0x9A, 0xD3, 0x88, 0x83, 0x80, 0x13, 0x89, 0xC3, 0x80, 0x79, 0xF7, 0x45, 0xFE, 0x00, 0xE0, 0x02, 0x24, 0x21, 0x00, +0x30, 0x00, 0x91, 0xF7, 0xE7, 0xF9, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, 0x0D, 0x06, 0x00, 0x00, +0x70, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x15, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0F, 0x4A, 0x9E, 0x58, 0x7A, 0xF7, 0xDA, 0xF9, +0x02, 0x21, 0x00, 0x28, 0x10, 0xD0, 0x63, 0x88, 0xF0, 0x22, 0x10, 0x31, 0x1A, 0x42, 0x0B, 0xD1, 0xE6, 0x3A, 0x01, 0x39, +0x1A, 0x42, 0x07, 0xD1, 0x73, 0x84, 0x2C, 0x32, 0xB1, 0x5C, 0x00, 0x29, 0x08, 0xD1, 0x35, 0x3A, 0x93, 0x43, 0x73, 0x84, +0x22, 0x88, 0x28, 0x00, 0xFF, 0xF7, 0xE0, 0xFD, 0x00, 0x20, 0x70, 0xBD, 0x00, 0x21, 0xF7, 0xE7, 0x64, 0xA2, 0x16, 0x00, +0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0E, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x4B, 0x4B, +0x9C, 0x42, 0x5D, 0xD0, 0x0E, 0xD9, 0x4A, 0x4B, 0x9C, 0x42, 0x67, 0xD0, 0x42, 0xD9, 0x49, 0x4B, 0x9C, 0x42, 0x00, 0xD0, +0x81, 0xE0, 0x47, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xDA, 0xFD, 0x00, 0x25, 0x43, 0xE0, 0x44, 0x4B, 0x9C, 0x42, +0x69, 0xD0, 0x01, 0x33, 0x9C, 0x42, 0x13, 0xD3, 0x42, 0x4B, 0xE3, 0x18, 0x9B, 0xB2, 0x03, 0x2B, 0x00, 0xD9, 0x6E, 0xE0, +0x10, 0x00, 0x7A, 0xF7, 0x91, 0xF9, 0x43, 0x28, 0x51, 0xD8, 0x41, 0x28, 0x51, 0xD8, 0x32, 0x00, 0x0C, 0x21, 0x20, 0x00, +0xFF, 0xF7, 0xCE, 0xFE, 0x00, 0x25, 0x29, 0xE0, 0x39, 0x4B, 0x9C, 0x42, 0x37, 0xD0, 0x39, 0x4B, 0x9C, 0x42, 0x5A, 0xD1, +0x38, 0x48, 0x7B, 0xF7, 0xAB, 0xFE, 0xB5, 0x1D, 0x16, 0x23, 0x9A, 0x46, 0xB2, 0x44, 0x36, 0x4B, 0x99, 0x46, 0x29, 0x78, +0x48, 0x46, 0x7B, 0xF7, 0xA1, 0xFE, 0x01, 0x35, 0x55, 0x45, 0xF8, 0xD1, 0x2F, 0x4B, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, +0x30, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x0B, 0xE0, 0x2F, 0x4B, 0x9C, 0x42, 0x38, 0xD0, 0x2F, 0x4B, 0x9C, 0x42, 0x3C, 0xD1, +0x2D, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x8B, 0xFD, 0x00, 0x25, 0x21, 0x00, 0x2B, 0x48, 0x7B, 0xF7, 0x86, 0xFE, +0x28, 0x00, 0x03, 0xB0, 0x0C, 0xBC, 0x91, 0x46, 0x9A, 0x46, 0xF0, 0xBD, 0x1A, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, +0xFB, 0xFE, 0x00, 0x25, 0xEE, 0xE7, 0x1C, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0xEC, 0xFD, 0x05, 0x00, 0xE7, 0xE7, +0x14, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x6B, 0xFE, 0x05, 0x00, 0xE0, 0xE7, 0x4A, 0x28, 0xAD, 0xD1, 0x23, 0x00, +0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x16, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xD6, 0xE7, 0x0E, 0x4A, 0x39, 0x00, 0x30, 0x00, +0xFF, 0xF7, 0x8A, 0xFE, 0x05, 0x00, 0xCF, 0xE7, 0x11, 0x4A, 0x39, 0x00, 0x30, 0x00, 0xFF, 0xF7, 0x43, 0xFF, 0x05, 0x00, +0xC8, 0xE7, 0x23, 0x00, 0x3A, 0x00, 0x31, 0x00, 0x01, 0x98, 0x0B, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0xC0, 0xE7, 0xC0, 0x46, +0x03, 0x08, 0x00, 0x00, 0x28, 0x0C, 0x00, 0x00, 0x37, 0x0C, 0x00, 0x00, 0x1F, 0x04, 0x00, 0x00, 0xD4, 0xFB, 0xFF, 0xFF, +0x09, 0x04, 0x00, 0x00, 0x0B, 0x04, 0x00, 0x00, 0x90, 0xD2, 0x10, 0x00, 0x98, 0xD2, 0x10, 0x00, 0xC1, 0xDB, 0x09, 0x00, +0x0D, 0x08, 0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x9C, 0xD2, 0x10, 0x00, 0x10, 0xB5, 0x03, 0x00, 0x08, 0x00, 0x1B, 0x78, +0x00, 0x21, 0x01, 0x2B, 0x00, 0xD9, 0x12, 0x31, 0xB2, 0xF7, 0x7C, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0x08, 0x00, +0x00, 0x21, 0xB2, 0xF7, 0x75, 0xFF, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, +0x45, 0x46, 0xE0, 0xB5, 0xAD, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x02, 0xAB, 0x00, 0x22, 0xDA, 0x71, 0x60, 0x32, 0x00, 0x21, +0x14, 0xA8, 0x77, 0xF7, 0x8B, 0xFD, 0x9B, 0x4A, 0x9B, 0x4B, 0xD3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xC8, 0xE1, 0x99, 0x4B, +0x02, 0x21, 0xD1, 0x54, 0x02, 0xAB, 0x00, 0x21, 0xD9, 0x71, 0x44, 0x32, 0x00, 0x20, 0x00, 0x23, 0x01, 0x26, 0x11, 0x78, +0x05, 0x29, 0x26, 0xD0, 0x01, 0x33, 0xDB, 0xB2, 0x40, 0x32, 0x30, 0x00, 0x0C, 0x2B, 0xF6, 0xD1, 0x02, 0xAB, 0x0C, 0x22, +0xDA, 0x71, 0x27, 0x78, 0x00, 0x2F, 0x24, 0xD0, 0x60, 0x7A, 0x07, 0x23, 0x07, 0x00, 0x9F, 0x43, 0x00, 0x97, 0x00, 0xD0, +0xB5, 0xE1, 0x8A, 0x49, 0x0F, 0x22, 0x02, 0x40, 0x03, 0x09, 0x8E, 0x5C, 0xCB, 0x5C, 0xF6, 0x18, 0xF6, 0xB2, 0x00, 0x2E, +0x61, 0xDD, 0x23, 0x00, 0x0A, 0x33, 0x3A, 0x00, 0x02, 0x37, 0x07, 0x40, 0x01, 0x21, 0x01, 0x40, 0xA4, 0x46, 0x0C, 0x00, +0x1E, 0xE0, 0x00, 0x28, 0x01, 0xD0, 0x02, 0xAA, 0xD3, 0x71, 0x0C, 0x21, 0x00, 0x27, 0x0B, 0x2B, 0x00, 0xD8, 0x8D, 0xE1, +0xD7, 0xE7, 0xA1, 0x78, 0xE0, 0x1C, 0xB2, 0xF7, 0x35, 0xFF, 0x0B, 0x21, 0x00, 0x28, 0x00, 0xD0, 0x84, 0xE1, 0xD1, 0xE7, +0x59, 0x88, 0x18, 0x88, 0x81, 0x42, 0x46, 0xD8, 0x03, 0x29, 0x44, 0xD9, 0x03, 0x28, 0x42, 0xD9, 0x01, 0x32, 0x10, 0x33, +0xB2, 0x42, 0x04, 0xDA, 0x00, 0x2F, 0xF1, 0xD0, 0x94, 0x42, 0xEF, 0xD1, 0xF6, 0xE7, 0x64, 0x46, 0x23, 0x00, 0x0E, 0x33, +0x00, 0x98, 0xC8, 0x22, 0x12, 0x01, 0x91, 0x46, 0x6B, 0x4A, 0x92, 0x46, 0xFA, 0x22, 0x52, 0x00, 0x93, 0x46, 0xA4, 0x46, +0xA8, 0x46, 0x1F, 0x88, 0x5A, 0x88, 0x97, 0x42, 0x2D, 0xD8, 0x1D, 0x89, 0x59, 0x89, 0x8D, 0x42, 0x29, 0xD8, 0xD9, 0x88, +0x05, 0x2F, 0x26, 0xD9, 0x4A, 0x45, 0x24, 0xD8, 0x0F, 0x00, 0x0A, 0x3F, 0xBF, 0xB2, 0x57, 0x45, 0x1F, 0xD8, 0x9F, 0x88, +0x5F, 0x45, 0x1C, 0xD2, 0x8C, 0x00, 0x61, 0x18, 0x49, 0x00, 0x01, 0x37, 0x57, 0x43, 0xBA, 0x00, 0xD2, 0x19, 0x01, 0x32, +0x52, 0x10, 0x91, 0x42, 0x11, 0xDB, 0x01, 0x30, 0x10, 0x33, 0xB0, 0x42, 0xDB, 0xDB, 0x64, 0x46, 0x45, 0x46, 0xA3, 0x78, +0x01, 0x2B, 0x0F, 0xD9, 0x12, 0x21, 0x00, 0x27, 0x38, 0xE1, 0x64, 0x46, 0x96, 0x42, 0xC3, 0xDD, 0x12, 0x21, 0x00, 0x27, +0x32, 0xE1, 0x64, 0x46, 0x45, 0x46, 0x86, 0x42, 0xEF, 0xDD, 0x12, 0x21, 0x00, 0x27, 0x2B, 0xE1, 0x63, 0x78, 0x03, 0x2B, +0x00, 0xD9, 0x35, 0xE1, 0xDB, 0x07, 0x06, 0xD5, 0x49, 0x49, 0x4A, 0x48, 0x7B, 0xF7, 0x98, 0xFD, 0x00, 0x28, 0x00, 0xD0, +0x2F, 0xE1, 0x02, 0xAB, 0xD8, 0x1D, 0xB3, 0xF7, 0x71, 0xF9, 0x01, 0x00, 0x01, 0x90, 0x00, 0x27, 0x00, 0x28, 0x00, 0xD0, +0x14, 0xE1, 0x00, 0x2E, 0x00, 0xDC, 0x25, 0xE1, 0x0E, 0x23, 0x99, 0x46, 0xA1, 0x44, 0x14, 0xAF, 0x00, 0x9B, 0x9A, 0x46, +0x00, 0x23, 0x9B, 0x46, 0xA0, 0x46, 0x4C, 0x46, 0xA9, 0x46, 0x55, 0x46, 0x13, 0xE0, 0x78, 0x60, 0x39, 0x60, 0xBA, 0x60, +0xFB, 0x60, 0x5B, 0x46, 0xBB, 0x74, 0xFB, 0x74, 0x02, 0xAB, 0xDB, 0x79, 0x3B, 0x82, 0x38, 0x00, 0xCF, 0xF7, 0xCA, 0xFA, +0x00, 0x28, 0x18, 0xD1, 0x01, 0x35, 0x10, 0x34, 0x20, 0x37, 0xB5, 0x42, 0x24, 0xDA, 0x23, 0x00, 0x21, 0x88, 0x49, 0x00, +0x22, 0x89, 0x8A, 0x42, 0x00, 0xD9, 0x0A, 0x00, 0x02, 0x2A, 0x00, 0xD2, 0x02, 0x22, 0x58, 0x88, 0x40, 0x00, 0x5B, 0x89, +0x83, 0x42, 0x00, 0xD9, 0x03, 0x00, 0x93, 0x42, 0xD9, 0xD2, 0x13, 0x00, 0xD7, 0xE7, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, +0x51, 0x46, 0x25, 0x48, 0x7B, 0xF7, 0x10, 0xFD, 0x51, 0x46, 0x24, 0x48, 0x7B, 0xF7, 0x0C, 0xFD, 0x01, 0x9F, 0x3B, 0x21, +0x56, 0x45, 0x00, 0xDD, 0xCC, 0xE0, 0x06, 0xE0, 0xAA, 0x46, 0x44, 0x46, 0x4D, 0x46, 0x51, 0x46, 0x1D, 0x48, 0x7B, 0xF7, +0xFF, 0xFC, 0x02, 0xAB, 0xDA, 0x79, 0x92, 0x01, 0x13, 0x4B, 0x9B, 0x18, 0x9B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x19, 0x4B, +0x9B, 0x6E, 0x00, 0x22, 0x11, 0x00, 0x10, 0x00, 0x98, 0x47, 0x60, 0x78, 0x02, 0x28, 0x2D, 0xD0, 0x0E, 0xD8, 0x00, 0x28, +0x2A, 0xD0, 0x0B, 0x49, 0x02, 0xAB, 0xD8, 0x79, 0x80, 0x01, 0x08, 0x18, 0x0C, 0x30, 0x11, 0x4B, 0x9C, 0x46, 0x61, 0x44, +0x06, 0x22, 0xD0, 0xF7, 0xD3, 0xFA, 0x2B, 0xE0, 0x03, 0x28, 0xF0, 0xD0, 0x0B, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x1A, 0x00, +0x19, 0x00, 0xB8, 0x47, 0x22, 0xE0, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0xE4, 0x98, 0x0D, 0x00, +0x76, 0x0C, 0x00, 0x00, 0xB4, 0x98, 0x0D, 0x00, 0xFA, 0xA7, 0x16, 0x00, 0xA4, 0xD2, 0x10, 0x00, 0xB0, 0xD2, 0x10, 0x00, +0x28, 0x19, 0x16, 0x00, 0x0E, 0x03, 0x00, 0x00, 0x4E, 0x4A, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, 0x9B, 0x01, 0xD3, 0x18, +0xC2, 0x21, 0x89, 0x00, 0x8C, 0x46, 0x62, 0x44, 0x11, 0x68, 0xD9, 0x60, 0x92, 0x88, 0x1A, 0x82, 0x02, 0xAB, 0x07, 0x33, +0x1B, 0x78, 0x46, 0x4F, 0x9A, 0x01, 0xBA, 0x18, 0x94, 0x60, 0x01, 0x33, 0x9B, 0x01, 0xFB, 0x18, 0x05, 0x22, 0x1A, 0x71, +0xE1, 0x1C, 0x01, 0x32, 0x0E, 0x20, 0x02, 0xAB, 0x9C, 0x46, 0x60, 0x44, 0xD0, 0xF7, 0x92, 0xFA, 0x3E, 0x4B, 0xF9, 0x18, +0x05, 0x22, 0x07, 0xA8, 0xD0, 0xF7, 0x8C, 0xFA, 0x67, 0x7A, 0x04, 0xAB, 0x9F, 0x74, 0x00, 0x2E, 0x17, 0xDD, 0x22, 0x00, +0x0A, 0x32, 0x14, 0xA9, 0x10, 0x88, 0x18, 0x83, 0x50, 0x88, 0x58, 0x83, 0x48, 0x69, 0x40, 0x08, 0x98, 0x83, 0x88, 0x69, +0xD8, 0x83, 0x10, 0x89, 0x18, 0x84, 0x50, 0x89, 0x58, 0x84, 0x00, 0x98, 0x01, 0x30, 0x00, 0x90, 0x10, 0x32, 0x0C, 0x33, +0x20, 0x31, 0xB0, 0x42, 0xEA, 0xDB, 0x05, 0x23, 0x3B, 0x40, 0x05, 0x2B, 0x20, 0xD0, 0x02, 0xAB, 0x07, 0x33, 0x1B, 0x78, +0x04, 0xA8, 0xC3, 0x74, 0x62, 0x78, 0x02, 0x75, 0xA2, 0x78, 0x42, 0x75, 0x22, 0x78, 0x82, 0x75, 0x24, 0x4A, 0x9B, 0x01, +0xD3, 0x18, 0xD9, 0x68, 0x04, 0x91, 0x1B, 0x8A, 0x83, 0x80, 0x01, 0x23, 0x43, 0x74, 0x22, 0x4B, 0xD2, 0x5C, 0x3C, 0x23, +0xC2, 0x54, 0xC7, 0xF7, 0x29, 0xFF, 0x01, 0x00, 0x01, 0x27, 0x00, 0x28, 0x1E, 0xD0, 0x03, 0x21, 0x01, 0x27, 0x1B, 0xE0, +0x01, 0x3E, 0x04, 0xA8, 0x43, 0x8B, 0x0C, 0x22, 0x72, 0x43, 0x82, 0x18, 0x51, 0x8B, 0x5F, 0x18, 0x02, 0x8B, 0xBA, 0x42, +0x00, 0xD2, 0x07, 0x83, 0x0C, 0x22, 0x72, 0x43, 0x04, 0xA8, 0x84, 0x46, 0x62, 0x44, 0x12, 0x8B, 0xBA, 0x42, 0xCA, 0xD2, +0x0C, 0x22, 0x72, 0x43, 0x62, 0x44, 0x5B, 0x18, 0x13, 0x83, 0xC4, 0xE7, 0x0C, 0x21, 0x00, 0x27, 0x28, 0x00, 0xB2, 0xF7, +0x9B, 0xFD, 0x38, 0x00, 0x2D, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x12, 0x21, +0x00, 0x27, 0xF1, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEE, 0xE7, 0x12, 0x21, 0x00, 0x27, 0xEB, 0xE7, 0x00, 0x9B, 0x9A, 0x46, +0x1F, 0xE7, 0xC0, 0x46, 0xEC, 0xA4, 0x16, 0x00, 0x19, 0x03, 0x00, 0x00, 0xD6, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, +0x00, 0xB5, 0x80, 0x46, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x58, 0x4B, 0xE3, 0x18, 0x9A, 0xB2, 0x39, 0x2A, 0x00, 0xD9, +0x90, 0xE0, 0x93, 0x00, 0x55, 0x4A, 0xD3, 0x58, 0x9F, 0x46, 0x02, 0x20, 0xF8, 0xF7, 0x40, 0xFF, 0x53, 0x4B, 0x00, 0x22, +0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, +0x00, 0x26, 0x7C, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x2F, 0xFF, 0x4B, 0x4B, 0x11, 0x22, 0x44, 0x21, 0x5A, 0x54, 0x40, 0x31, +0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x40, 0x31, 0x5A, 0x54, 0x00, 0x26, 0x6B, 0xE0, 0x45, 0x4B, +0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x66, 0xD0, 0x43, 0x49, 0x28, 0x00, 0xFF, 0xF7, 0xB0, 0xFD, 0x05, 0x00, 0x21, 0x00, +0x41, 0x48, 0x7B, 0xF7, 0xDB, 0xFB, 0x41, 0x4B, 0x9C, 0x42, 0x6E, 0xD1, 0x00, 0x26, 0x3B, 0x4A, 0x3F, 0x4B, 0x00, 0x21, +0xD1, 0x54, 0x62, 0xE0, 0x39, 0x4B, 0x1B, 0x78, 0x00, 0x26, 0x00, 0x2B, 0x4F, 0xD0, 0x00, 0x21, 0x3B, 0x48, 0xB2, 0xF7, +0x1F, 0xFD, 0x00, 0x25, 0xE7, 0xE7, 0x4B, 0x78, 0x02, 0x2B, 0x27, 0xD0, 0x38, 0x4E, 0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, +0x77, 0xF7, 0x3E, 0xFB, 0x36, 0x4B, 0xF3, 0x18, 0x36, 0x49, 0x58, 0x5C, 0x1F, 0x22, 0x02, 0x40, 0x5A, 0x54, 0x35, 0x4B, +0x1B, 0x78, 0xEB, 0x81, 0x2B, 0x82, 0x12, 0x23, 0xAB, 0x81, 0x6B, 0x7A, 0x9A, 0x07, 0x07, 0xD5, 0x02, 0x22, 0x93, 0x43, +0x6B, 0x72, 0x12, 0x23, 0xAB, 0x83, 0x6B, 0x8B, 0x9B, 0x00, 0x6B, 0x83, 0x6B, 0x7A, 0x00, 0x26, 0x5B, 0x07, 0x24, 0xD5, +0x12, 0x23, 0xAB, 0x85, 0x6B, 0x8D, 0x5B, 0x00, 0x6B, 0x85, 0x1E, 0xE0, 0x00, 0x23, 0x4B, 0x70, 0xD4, 0xE7, 0x23, 0x4E, +0x05, 0x22, 0xFF, 0x21, 0x30, 0x00, 0x77, 0xF7, 0x13, 0xFB, 0x21, 0x4B, 0xF0, 0x18, 0x21, 0x4A, 0x81, 0x5C, 0x1F, 0x23, +0x0B, 0x40, 0x83, 0x54, 0x20, 0x4B, 0xC6, 0x5C, 0x00, 0x2E, 0x0A, 0xD0, 0x13, 0x4A, 0x00, 0x21, 0xD1, 0x54, 0x06, 0xE0, +0x11, 0x4A, 0x16, 0x4B, 0x00, 0x21, 0xD1, 0x54, 0x00, 0x26, 0x00, 0xE0, 0x00, 0x26, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, +0x40, 0x46, 0x18, 0x4D, 0xA8, 0x47, 0x05, 0x00, 0x21, 0x00, 0x0D, 0x48, 0x7B, 0xF7, 0x72, 0xFB, 0x0C, 0x4B, 0x9C, 0x42, +0x97, 0xD0, 0x00, 0x2E, 0x03, 0xD0, 0x06, 0x4A, 0x10, 0x4B, 0x01, 0x21, 0xD1, 0x54, 0x28, 0x00, 0x04, 0xBC, 0x90, 0x46, +0xF0, 0xBD, 0xC0, 0x46, 0xF6, 0xDF, 0xFF, 0xFF, 0xC4, 0xD2, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x60, 0xE6, 0x10, 0x00, +0x0A, 0x20, 0x00, 0x00, 0xB8, 0xD2, 0x10, 0x00, 0x3B, 0x20, 0x00, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x39, 0x20, 0x00, 0x00, +0x05, 0xA8, 0x16, 0x00, 0xE7, 0xFC, 0xFF, 0xFF, 0x1D, 0x03, 0x00, 0x00, 0xE2, 0xE1, 0x10, 0x00, 0xD6, 0x03, 0x00, 0x00, +0x15, 0xC9, 0x0B, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x17, 0x00, 0x1C, 0x00, 0x17, 0x4B, 0x9C, 0x42, +0x24, 0xD0, 0x17, 0x4B, 0x9C, 0x42, 0x13, 0xD1, 0xCB, 0x88, 0x10, 0x2B, 0x01, 0xD9, 0x10, 0x23, 0xCB, 0x80, 0x14, 0x4B, +0x1B, 0x78, 0x6A, 0x88, 0x9A, 0x42, 0x01, 0xD8, 0x6B, 0x80, 0xAB, 0x80, 0xEB, 0x88, 0xAA, 0x88, 0x69, 0x88, 0x28, 0x89, +0x00, 0x90, 0x0F, 0x48, 0x7B, 0xF7, 0x26, 0xFB, 0x23, 0x00, 0x3A, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0C, 0x4D, 0xA8, 0x47, +0x05, 0x00, 0x21, 0x00, 0x0B, 0x48, 0x7B, 0xF7, 0x1B, 0xFB, 0x28, 0x00, 0x03, 0xB0, 0xF0, 0xBD, 0x0A, 0x88, 0x00, 0x21, +0x02, 0x48, 0xFF, 0xF7, 0x03, 0xFA, 0x00, 0x25, 0xF1, 0xE7, 0xC0, 0x46, 0x0D, 0x08, 0x00, 0x00, 0x13, 0x20, 0x00, 0x00, +0xE2, 0xE1, 0x10, 0x00, 0xAC, 0xD3, 0x10, 0x00, 0x09, 0x1C, 0x0C, 0x00, 0xBC, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0xCE, 0x46, +0x47, 0x46, 0x80, 0xB5, 0x14, 0x0A, 0xA4, 0x00, 0x0E, 0x4D, 0x65, 0x59, 0x44, 0x24, 0x2C, 0x5D, 0x03, 0x27, 0x3E, 0x00, +0x26, 0x40, 0x27, 0x42, 0x11, 0xD0, 0xB9, 0x46, 0xBC, 0x43, 0xA4, 0x46, 0x44, 0x24, 0x67, 0x46, 0x2F, 0x55, 0xB9, 0xF7, +0x7F, 0xF8, 0x2B, 0x5D, 0x4A, 0x46, 0x93, 0x43, 0x1E, 0x43, 0x2E, 0x55, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, +0xF8, 0xBD, 0xB9, 0xF7, 0x73, 0xF8, 0xF7, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x70, 0xB5, 0x0D, 0x00, 0x14, 0x0A, 0xA2, 0x00, +0x29, 0x4B, 0xD6, 0x58, 0x0B, 0x2C, 0x06, 0xD8, 0x00, 0x2E, 0x04, 0xD0, 0x44, 0x23, 0xF3, 0x5C, 0xDB, 0x43, 0x9B, 0x07, +0x11, 0xD1, 0x2D, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x06, 0xD0, 0x2A, 0x00, 0x16, 0x21, 0x20, 0x00, 0x21, 0x4B, 0x98, 0x47, +0x00, 0x20, 0x70, 0xBD, 0x45, 0x22, 0xB1, 0x5C, 0x7F, 0x23, 0x0B, 0x40, 0xB3, 0x54, 0x00, 0x20, 0xF7, 0xE7, 0x00, 0x21, +0x20, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x00, 0x28, 0x2C, 0xD1, 0x42, 0x23, 0xF3, 0x5A, 0xDB, 0x06, 0x04, 0xD5, 0x28, 0x00, +0xB8, 0xF7, 0x92, 0xFC, 0x00, 0x28, 0x25, 0xD0, 0x28, 0x00, 0xB8, 0xF7, 0x8D, 0xFC, 0x00, 0x28, 0x0E, 0xD1, 0x2A, 0x00, +0x00, 0x21, 0x20, 0x00, 0xB8, 0xF7, 0x20, 0xFC, 0x28, 0x00, 0xB8, 0xF7, 0x83, 0xFC, 0x01, 0x00, 0x00, 0x22, 0x20, 0x00, +0x0D, 0x4B, 0x98, 0x47, 0x01, 0x20, 0xD4, 0xE7, 0x28, 0x00, 0xB8, 0xF7, 0x79, 0xFC, 0x01, 0x28, 0xEB, 0xD0, 0x0A, 0x4B, +0xDE, 0x6E, 0x28, 0x00, 0xB8, 0xF7, 0x72, 0xFC, 0x01, 0x00, 0x00, 0x23, 0x00, 0x22, 0x20, 0x00, 0xB0, 0x47, 0xE0, 0xE7, +0x02, 0x20, 0xC2, 0xE7, 0x02, 0x20, 0xC0, 0xE7, 0x5C, 0xA9, 0x16, 0x00, 0x81, 0x45, 0x0C, 0x00, 0xF5, 0x46, 0x0C, 0x00, +0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, +0x13, 0x0A, 0x9B, 0x00, 0x0E, 0x4A, 0x9B, 0x58, 0x00, 0x2B, 0x0E, 0xD0, 0x89, 0x88, 0x0D, 0x4B, 0x9C, 0x46, 0x61, 0x44, +0x01, 0xAB, 0x98, 0x46, 0x01, 0x22, 0x18, 0x00, 0xD0, 0xF7, 0x5A, 0xF8, 0x43, 0x46, 0x19, 0x78, 0x08, 0x48, 0x7B, 0xF7, +0x61, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0xB9, 0xF7, 0x91, 0xF9, 0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, +0xF0, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, 0xC8, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x05, 0x00, +0x0E, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x08, 0x4A, 0x9B, 0x58, 0x9B, 0x6A, 0x00, 0x2B, 0x03, 0xD0, +0x59, 0x7A, 0x06, 0x48, 0x7B, 0xF7, 0x40, 0xFA, 0x3B, 0x00, 0x22, 0x00, 0x31, 0x00, 0x28, 0x00, 0xB9, 0xF7, 0x50, 0xFA, +0xF8, 0xBD, 0xC0, 0x46, 0x5C, 0xA9, 0x16, 0x00, 0xD4, 0xD3, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x06, 0x0A, 0xB2, 0x00, +0x28, 0x4B, 0xD5, 0x58, 0x28, 0x00, 0x54, 0x30, 0x2A, 0x21, 0xA0, 0xF7, 0x31, 0xFD, 0x00, 0x28, 0x3C, 0xD0, 0xF6, 0xB2, +0x30, 0x00, 0xAA, 0xF7, 0xB5, 0xF8, 0x20, 0x00, 0x91, 0xF7, 0x02, 0xFA, 0x43, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x23, 0xD0, +0x1F, 0x4B, 0xEB, 0x5C, 0x00, 0x2B, 0x14, 0xD0, 0x95, 0x23, 0x9B, 0x00, 0xEF, 0x18, 0x38, 0x00, 0x86, 0xF7, 0x80, 0xFA, +0x36, 0x23, 0xE9, 0x5C, 0x3A, 0x00, 0x30, 0x00, 0xA1, 0xF7, 0x42, 0xF8, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x0A, 0xD0, +0x2D, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x76, 0xFC, 0x22, 0xE0, 0x36, 0x23, 0xE9, 0x5C, 0x30, 0x00, 0xA1, 0xF7, 0x4B, 0xF8, +0xF0, 0xE7, 0x2B, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x6B, 0xFC, 0x17, 0xE0, 0x36, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x04, 0xD0, +0x60, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x62, 0xFC, 0x0E, 0xE0, 0x61, 0x21, 0x20, 0x00, 0x79, 0xF7, 0x5D, 0xFC, 0x09, 0xE0, +0x00, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xAB, 0x54, 0x05, 0x4A, 0xAB, 0x54, 0x00, 0x21, 0x20, 0x00, 0x93, 0xF7, 0xA6, 0xFB, +0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0xF8, 0xB5, 0x05, 0x00, +0x0E, 0x00, 0x07, 0x0A, 0xBA, 0x00, 0x1D, 0x4B, 0xD4, 0x58, 0x1D, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0A, 0xD1, 0x1B, 0x4B, +0x00, 0x22, 0xE2, 0x54, 0x09, 0x3B, 0xE3, 0x5C, 0x00, 0x2B, 0x27, 0xD0, 0x28, 0x00, 0xFF, 0xF7, 0x8F, 0xFF, 0xF8, 0xBD, +0x93, 0xF7, 0xCC, 0xF8, 0x00, 0x28, 0x03, 0xD0, 0x14, 0x4B, 0xE3, 0x5C, 0x00, 0x2B, 0x0C, 0xD0, 0x11, 0x4B, 0xE3, 0x5C, +0x00, 0x2B, 0xE8, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0xE3, 0xD0, 0x43, 0x23, 0x01, 0x22, 0xE2, 0x54, +0xDF, 0xE7, 0x04, 0x33, 0x06, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x79, 0xF7, 0xA3, 0xF8, 0x06, 0x70, 0x80, 0x37, 0x47, 0x80, +0xCA, 0xF7, 0xFE, 0xFE, 0x43, 0x23, 0x00, 0x22, 0xE2, 0x54, 0xE3, 0xE7, 0x31, 0x00, 0x28, 0x00, 0x93, 0xF7, 0x60, 0xFB, +0xD5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xB9, 0x02, 0x00, 0x00, 0xC5, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, +0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8C, 0xB0, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, 0x4A, 0x4B, 0xD6, 0x58, +0x08, 0x00, 0x79, 0xF7, 0x55, 0xFC, 0x20, 0x28, 0x07, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x47, 0x4B, 0x98, 0x47, 0x0C, 0xB0, +0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2A, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x69, 0x1C, 0x29, 0x3A, +0x30, 0x00, 0xCB, 0x30, 0xFF, 0x30, 0xCF, 0xF7, 0x61, 0xFF, 0xFD, 0x23, 0x5B, 0x00, 0x98, 0x46, 0xB0, 0x44, 0x09, 0xAB, +0x07, 0x93, 0x43, 0x46, 0x06, 0x93, 0x02, 0xA8, 0x10, 0x22, 0x31, 0x00, 0xCB, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0x52, 0xFF, +0x6A, 0x46, 0x33, 0x00, 0x6C, 0x33, 0xF1, 0x6E, 0x00, 0x91, 0x9B, 0x88, 0x93, 0x80, 0xCD, 0x23, 0x5B, 0x00, 0xF3, 0x5A, +0x35, 0x00, 0x9B, 0x35, 0xFF, 0x35, 0x68, 0x88, 0x00, 0x04, 0x18, 0x43, 0xAB, 0x88, 0xE9, 0x88, 0x09, 0x04, 0x19, 0x43, +0x2B, 0x89, 0x6A, 0x89, 0x12, 0x04, 0x1A, 0x43, 0xAB, 0x89, 0x9C, 0x46, 0xEB, 0x89, 0x1B, 0x04, 0x65, 0x46, 0x2B, 0x43, +0x83, 0xF7, 0xDA, 0xFD, 0x27, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD0, 0x39, 0x23, 0xF2, 0x5C, 0xF8, 0xB2, 0x41, 0x46, +0xA0, 0xF7, 0x93, 0xFE, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x00, 0x2B, 0x1B, 0xD0, 0x88, 0x23, 0xFF, 0x33, 0xF3, 0x5C, +0x00, 0x2B, 0x05, 0xD0, 0x01, 0x23, 0xAC, 0x22, 0x92, 0x00, 0xB3, 0x54, 0x1C, 0x4A, 0xB3, 0x54, 0x37, 0x23, 0xF3, 0x5C, +0x05, 0x2B, 0x27, 0xD0, 0x00, 0x21, 0x20, 0x00, 0xFF, 0xF7, 0x44, 0xFF, 0x00, 0x20, 0x9C, 0xE7, 0x0C, 0x22, 0x09, 0xA9, +0x16, 0x4B, 0xF0, 0x18, 0xCF, 0xF7, 0x08, 0xFF, 0xD8, 0xE7, 0x17, 0x33, 0x18, 0x22, 0x00, 0x21, 0x13, 0x48, 0x79, 0xF7, +0x09, 0xF8, 0x05, 0x00, 0xC0, 0x23, 0x5B, 0x00, 0xF3, 0x5C, 0x83, 0x75, 0x06, 0x22, 0x31, 0x00, 0x72, 0x31, 0xCF, 0xF7, +0xF7, 0xFE, 0xA8, 0x1D, 0x10, 0x22, 0x31, 0x00, 0x9B, 0x31, 0xFF, 0x31, 0xCF, 0xF7, 0xF0, 0xFE, 0x28, 0x00, 0xCA, 0xF7, +0x55, 0xFE, 0xC8, 0xE7, 0x05, 0x21, 0x20, 0x00, 0x93, 0xF7, 0x2E, 0xFB, 0x00, 0x20, 0x74, 0xE7, 0x64, 0xA2, 0x16, 0x00, +0x01, 0x4A, 0x0A, 0x00, 0xC5, 0x02, 0x00, 0x00, 0xB3, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, +0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0B, 0x0A, 0x9B, 0x00, 0x0B, 0x4A, 0x9E, 0x58, 0x08, 0x00, 0x79, 0xF7, 0xAE, 0xFB, +0x24, 0x28, 0x04, 0xD0, 0x21, 0x00, 0x28, 0x00, 0x07, 0x4B, 0x98, 0x47, 0x70, 0xBD, 0xBE, 0x23, 0x5B, 0x00, 0xF3, 0x5C, +0x00, 0x2B, 0xF5, 0xD1, 0x7D, 0x33, 0xFF, 0x33, 0x01, 0x22, 0xF2, 0x54, 0xF0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, +0x55, 0x45, 0x0A, 0x00, 0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x0F, 0x0A, 0xBA, 0x00, +0x2F, 0x4B, 0xD6, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x42, 0x78, 0x37, 0x23, 0xF2, 0x54, +0x08, 0x00, 0x79, 0xF7, 0x83, 0xFB, 0x18, 0x28, 0x04, 0xD8, 0x01, 0x23, 0x83, 0x40, 0x28, 0x4A, 0x13, 0x42, 0x2B, 0xD1, +0xFB, 0xB2, 0x99, 0x46, 0x18, 0x00, 0xAA, 0xF7, 0x81, 0xF9, 0x80, 0x46, 0x24, 0x4B, 0x01, 0x22, 0xF2, 0x54, 0x21, 0x00, +0x23, 0x48, 0x78, 0xF7, 0x51, 0xFF, 0x23, 0x4B, 0xF3, 0x5C, 0x00, 0x2B, 0x1F, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, +0x2D, 0xD0, 0x48, 0x46, 0xA9, 0xF7, 0x24, 0xFF, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x2A, 0xD1, 0x43, 0x46, 0x58, 0x00, +0x40, 0x44, 0x40, 0x00, 0x80, 0xB2, 0x7B, 0xF7, 0xE7, 0xF8, 0x02, 0x00, 0x21, 0x00, 0x16, 0x48, 0x78, 0xF7, 0xBE, 0xFE, +0x19, 0x21, 0x20, 0x00, 0x79, 0xF7, 0xF0, 0xFA, 0x00, 0x20, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x04, 0x23, +0x06, 0x22, 0x00, 0x21, 0x10, 0x48, 0x78, 0xF7, 0x6F, 0xFF, 0x6B, 0x78, 0x03, 0x70, 0x80, 0x37, 0x47, 0x80, 0xCA, 0xF7, +0xC9, 0xFD, 0x00, 0x23, 0x0A, 0x4A, 0xB3, 0x54, 0x43, 0x22, 0xB3, 0x54, 0xCD, 0xE7, 0x20, 0x00, 0x09, 0x4B, 0x98, 0x47, +0xCD, 0xE7, 0x43, 0x46, 0x58, 0x00, 0x40, 0x44, 0x80, 0xB2, 0xD4, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x01, 0x00, 0x40, 0x01, +0xC2, 0x02, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0xB9, 0x02, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0xF5, 0x3A, 0x09, 0x00, +0x00, 0x20, 0x70, 0x47, 0xF0, 0xB5, 0x83, 0xB0, 0x0C, 0x00, 0x04, 0x23, 0x5B, 0x4A, 0x00, 0x21, 0x5B, 0x48, 0x78, 0xF7, +0x41, 0xFF, 0x05, 0x00, 0x21, 0x78, 0x5A, 0x48, 0x7B, 0xF7, 0x40, 0xF8, 0x23, 0x78, 0x01, 0x2B, 0x65, 0xD0, 0x06, 0x2B, +0x00, 0xD1, 0x80, 0xE0, 0x00, 0x2B, 0x05, 0xD0, 0x28, 0x00, 0xCA, 0xF7, 0x91, 0xFD, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, +0xA2, 0x78, 0x52, 0x4B, 0x1A, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x4F, 0x4B, 0x1B, 0x78, +0xEB, 0x70, 0x63, 0x78, 0x01, 0x2B, 0xEB, 0xD1, 0x4D, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0xE7, 0xD1, 0x49, 0x4B, 0x1B, 0x78, +0x06, 0x2B, 0xE3, 0xD1, 0xFC, 0xF7, 0x66, 0xF9, 0x49, 0x4C, 0x4A, 0x4B, 0x02, 0x22, 0xE2, 0x54, 0x6B, 0x46, 0xDF, 0x1D, +0x38, 0x00, 0xB2, 0xF7, 0x2D, 0xFC, 0x3E, 0x78, 0x10, 0x23, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x78, 0xF7, 0x06, 0xFF, +0xB6, 0x01, 0xA6, 0x19, 0xB0, 0x60, 0x3B, 0x78, 0x9B, 0x01, 0xE3, 0x18, 0x9B, 0x68, 0x01, 0x22, 0x9A, 0x70, 0x00, 0x26, +0x1E, 0x71, 0x80, 0x22, 0x92, 0x01, 0xDA, 0x80, 0x1A, 0x81, 0x1E, 0x70, 0x5E, 0x70, 0x38, 0x78, 0x43, 0x1C, 0x9B, 0x01, +0xE3, 0x18, 0x06, 0x22, 0x1A, 0x71, 0x38, 0x4A, 0xA3, 0x5C, 0x03, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x83, 0x01, 0xE3, 0x18, +0x1E, 0x86, 0x5E, 0x86, 0x34, 0x4B, 0x98, 0x47, 0x3B, 0x78, 0x5A, 0x1C, 0x92, 0x01, 0xA2, 0x18, 0x07, 0x21, 0x11, 0x71, +0x9B, 0x01, 0xE3, 0x18, 0x98, 0x68, 0x0C, 0x38, 0x78, 0xF7, 0x27, 0xFF, 0x3B, 0x78, 0x9B, 0x01, 0xE4, 0x18, 0xA6, 0x60, +0x9E, 0xE7, 0xA3, 0x78, 0x00, 0x2B, 0x0C, 0xD1, 0x24, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, 0x10, 0x2B, 0x02, 0xD8, +0x21, 0x4A, 0x13, 0x70, 0x07, 0xE0, 0x20, 0x4B, 0x10, 0x22, 0x1A, 0x70, 0x03, 0xE0, 0x1E, 0x4A, 0x13, 0x78, 0x01, 0x3B, +0x13, 0x70, 0x00, 0x23, 0x2B, 0x70, 0x01, 0x33, 0x6B, 0x70, 0xA3, 0x78, 0xAB, 0x70, 0x19, 0x4B, 0x1B, 0x78, 0xEB, 0x70, +0x80, 0xE7, 0xE2, 0x78, 0x12, 0x02, 0xA3, 0x78, 0x13, 0x43, 0x1B, 0x4A, 0x1B, 0xB2, 0x93, 0x42, 0x00, 0xD0, 0x77, 0xE7, +0x19, 0x4B, 0x1A, 0x80, 0x61, 0x79, 0x09, 0x02, 0x22, 0x79, 0x0A, 0x43, 0x5A, 0x80, 0xE1, 0x79, 0x09, 0x02, 0xA2, 0x79, +0x0A, 0x43, 0x9A, 0x80, 0x98, 0x68, 0x00, 0x28, 0x01, 0xD0, 0x79, 0xF7, 0x11, 0xF8, 0x20, 0x7A, 0x10, 0x4E, 0xB0, 0x71, +0x01, 0x21, 0x78, 0xF7, 0x67, 0xFF, 0xB0, 0x60, 0xB2, 0x79, 0x21, 0x00, 0x09, 0x31, 0xCF, 0xF7, 0x87, 0xFD, 0x59, 0xE7, +0x57, 0xFD, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0xE0, 0xD3, 0x10, 0x00, 0xD0, 0xE5, 0x10, 0x00, 0x48, 0x06, 0x16, 0x00, +0xA8, 0xE5, 0x10, 0x00, 0xEC, 0xA4, 0x16, 0x00, 0x6D, 0x04, 0x00, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xE1, 0xEA, 0x0B, 0x00, +0x88, 0xAC, 0xFF, 0xFF, 0xC4, 0xE5, 0x10, 0x00, 0x09, 0x4B, 0x1B, 0x68, 0xDA, 0x6E, 0x53, 0x1C, 0x0C, 0xD0, 0x08, 0x4B, +0x19, 0x68, 0x4B, 0x68, 0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x06, 0x48, 0x83, 0x42, 0x03, 0xD9, 0x04, 0x32, 0x12, 0x01, +0x12, 0x09, 0x4A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0xF4, 0xE1, 0x10, 0x00, 0x28, 0x27, 0x16, 0x00, 0xFE, 0xFF, 0xFF, 0x07, +0x30, 0xB5, 0x83, 0xB0, 0x68, 0x46, 0x77, 0xF7, 0xE5, 0xFC, 0x00, 0x9D, 0x34, 0x4C, 0x23, 0x68, 0x01, 0x22, 0x93, 0x43, +0x23, 0x60, 0x82, 0xF7, 0x51, 0xFE, 0xB1, 0xF7, 0x69, 0xFE, 0x22, 0x68, 0x8C, 0x23, 0x5B, 0x01, 0x13, 0x43, 0x23, 0x60, +0x2E, 0x4B, 0x1B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x41, 0xD0, 0x2A, 0x49, 0x0B, 0x68, 0x2B, 0x4A, 0x1A, 0x40, +0x80, 0x23, 0xDB, 0x00, 0x13, 0x43, 0x0B, 0x60, 0x27, 0x4B, 0x5B, 0x68, 0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x36, 0xD0, +0x23, 0x49, 0x0B, 0x68, 0x25, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x01, 0x13, 0x43, 0x0B, 0x60, 0x20, 0x4B, 0x9B, 0x68, +0x5A, 0x1C, 0x09, 0xD0, 0xAB, 0x42, 0x2B, 0xD0, 0x1C, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x00, +0x13, 0x43, 0x0B, 0x60, 0x1D, 0x48, 0x78, 0xF7, 0x3F, 0xFA, 0x18, 0x4B, 0x5B, 0x7F, 0x00, 0x2B, 0x1F, 0xD1, 0x7F, 0xF7, +0x9B, 0xFE, 0x02, 0x28, 0x21, 0xD1, 0x19, 0x49, 0x0B, 0x68, 0x19, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x9B, 0x03, 0x13, 0x43, +0x0B, 0x60, 0x17, 0x4B, 0x1A, 0x68, 0x01, 0x21, 0x0A, 0x43, 0x1A, 0x60, 0x1A, 0x68, 0x01, 0x31, 0x8A, 0x43, 0x1A, 0x60, +0x03, 0xB0, 0x30, 0xBD, 0x77, 0xF7, 0x4E, 0xFB, 0xC2, 0xE7, 0x77, 0xF7, 0x5F, 0xFB, 0xCD, 0xE7, 0x77, 0xF7, 0x70, 0xFB, +0xD8, 0xE7, 0xFC, 0xF7, 0x49, 0xFB, 0x05, 0x4B, 0x00, 0x22, 0x5A, 0x77, 0xD9, 0xE7, 0x7F, 0xF7, 0x75, 0xFE, 0x03, 0x28, +0xEA, 0xD1, 0xD8, 0xE7, 0x0C, 0x00, 0x60, 0x40, 0x3C, 0x95, 0x16, 0x00, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, +0xFF, 0xFD, 0xFF, 0xFF, 0x01, 0x20, 0x00, 0x00, 0x58, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xDF, 0xFF, 0x18, 0x00, 0x58, 0x40, +0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x91, 0x46, 0x9C, 0x4B, 0x1E, 0x68, 0x80, 0x00, 0x84, 0x59, +0x3C, 0x23, 0xE3, 0x5C, 0x98, 0x46, 0x9A, 0x4B, 0xE3, 0x61, 0xBD, 0xF7, 0x4D, 0xFA, 0x01, 0x90, 0x00, 0x23, 0xA3, 0x62, +0x00, 0x20, 0xCE, 0xF7, 0x51, 0xFF, 0x96, 0x4B, 0x1D, 0x68, 0xEB, 0x6E, 0x5A, 0x1C, 0x16, 0xD0, 0x63, 0x60, 0x00, 0x23, +0xA3, 0x60, 0xE7, 0x8E, 0xA7, 0x62, 0x92, 0x49, 0x9A, 0x00, 0x52, 0x58, 0x00, 0x2A, 0x25, 0xD1, 0x01, 0x33, 0x07, 0x2B, +0xF8, 0xD1, 0x00, 0x23, 0x9C, 0x46, 0x8E, 0x4B, 0x18, 0x00, 0x41, 0x30, 0xFF, 0x30, 0x00, 0x22, 0x00, 0x21, 0x00, 0x91, +0x1E, 0xE0, 0x8B, 0x4B, 0x1B, 0x68, 0x01, 0x33, 0x09, 0xD0, 0x8A, 0x4B, 0x1B, 0x68, 0x5B, 0x00, 0x01, 0x9A, 0x94, 0x46, +0x63, 0x44, 0x88, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xDB, 0xE7, 0xA3, 0x8E, 0xE2, 0x8E, 0x9B, 0x1A, 0x5B, 0x00, 0x01, 0x9A, +0x94, 0x46, 0x63, 0x44, 0x82, 0x4A, 0x13, 0x40, 0x63, 0x60, 0xD0, 0xE7, 0x01, 0x23, 0x9C, 0x46, 0xDB, 0xE7, 0x40, 0x33, +0x83, 0x42, 0x07, 0xD0, 0x19, 0x78, 0x09, 0x29, 0xF9, 0xD1, 0x01, 0x32, 0xD2, 0xB2, 0x08, 0x39, 0x00, 0x91, 0xF4, 0xE7, +0xEB, 0x6E, 0x59, 0x1C, 0x21, 0xD0, 0x63, 0x60, 0x75, 0x4B, 0x9A, 0x88, 0x77, 0x4B, 0x9A, 0x42, 0x02, 0xD9, 0x77, 0x4B, +0x9C, 0x46, 0x62, 0x44, 0x76, 0x4B, 0x7B, 0x43, 0x93, 0x42, 0x00, 0xD9, 0x13, 0x00, 0x75, 0x4A, 0x93, 0x42, 0x00, 0xD2, +0x13, 0x00, 0x23, 0x61, 0xB3, 0x68, 0x80, 0x22, 0x52, 0x05, 0x93, 0x42, 0x3B, 0xD2, 0x62, 0x68, 0xD3, 0x1A, 0x1B, 0x01, +0x1B, 0x09, 0x6F, 0x4A, 0x93, 0x42, 0x34, 0xD8, 0x6E, 0x4B, 0x98, 0x47, 0xAF, 0xE0, 0x65, 0x4B, 0x1B, 0x68, 0x01, 0x33, +0x07, 0xD0, 0x64, 0x4B, 0x18, 0x68, 0x01, 0x9B, 0x1D, 0x18, 0x63, 0x48, 0x05, 0x40, 0x65, 0x60, 0xD2, 0xE7, 0x63, 0x46, +0x00, 0x2B, 0x03, 0xD1, 0x66, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x08, 0xD0, 0x5C, 0x4B, 0x18, 0x68, 0x80, 0x00, 0x01, 0x9B, +0xC5, 0x18, 0x5B, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xC2, 0xE7, 0x00, 0x9B, 0x00, 0x2B, 0xBF, 0xD0, 0x5F, 0x4B, 0x1B, 0x68, +0x01, 0x2B, 0x06, 0xD9, 0xD3, 0x01, 0x01, 0x9A, 0x9D, 0x18, 0x54, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xB4, 0xE7, 0x51, 0x4B, +0x1B, 0x68, 0x01, 0x9A, 0xD5, 0x18, 0x50, 0x4B, 0x1D, 0x40, 0x65, 0x60, 0xAC, 0xE7, 0x4B, 0x46, 0x00, 0x2B, 0x05, 0xD1, +0x55, 0x4A, 0x26, 0x33, 0xD3, 0x5C, 0xA3, 0x75, 0x63, 0x68, 0xE3, 0x62, 0x52, 0x4A, 0x27, 0x23, 0xD2, 0x5C, 0x18, 0x3B, +0x1A, 0x40, 0xC0, 0x23, 0xDB, 0x01, 0x13, 0x43, 0xA3, 0x82, 0x3F, 0x23, 0xE1, 0x5C, 0x1B, 0x33, 0x42, 0x46, 0x53, 0x43, +0x4C, 0x4A, 0x98, 0x18, 0x8A, 0x00, 0x11, 0x43, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x02, 0x80, 0x21, 0x8D, 0x49, 0x4A, +0x9A, 0x18, 0x11, 0x80, 0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x3A, 0x01, 0x2A, 0x5A, 0xD9, 0x46, 0x4A, 0x98, 0x18, 0xA1, 0x6A, +0x80, 0x22, 0xD2, 0x01, 0x91, 0x42, 0x00, 0xD3, 0x43, 0x49, 0x44, 0x4A, 0x0A, 0x43, 0x92, 0xB2, 0x02, 0x80, 0x00, 0x21, +0x42, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x32, 0x7D, 0x92, 0x07, 0x14, 0xD5, 0xF1, 0x7B, 0x09, 0x02, 0xB2, 0x7B, 0x0A, 0x43, +0x3E, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7C, 0x09, 0x02, 0x32, 0x7C, 0x0A, 0x43, 0x3C, 0x49, 0x59, 0x18, 0x0A, 0x80, +0xF1, 0x7C, 0x09, 0x02, 0xB2, 0x7C, 0x0A, 0x43, 0x39, 0x49, 0x59, 0x18, 0x0A, 0x80, 0x71, 0x7D, 0xB5, 0x7D, 0x38, 0x4A, +0x97, 0x78, 0x7A, 0x1E, 0x97, 0x41, 0x30, 0x7D, 0x80, 0x07, 0xC0, 0x0F, 0x01, 0x22, 0x94, 0x46, 0x00, 0x2D, 0x00, 0xD1, +0x84, 0x46, 0x33, 0x4A, 0x9E, 0x18, 0x09, 0x02, 0xAA, 0x01, 0x0A, 0x43, 0xFF, 0x00, 0x3A, 0x43, 0x80, 0x00, 0x02, 0x43, +0x61, 0x46, 0x0A, 0x43, 0x32, 0x80, 0x2E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x1F, 0x21, 0x8A, 0x43, 0x11, 0x00, +0x3E, 0x22, 0xA2, 0x5C, 0x0A, 0x43, 0x1A, 0x80, 0x20, 0x00, 0xCC, 0xF7, 0x71, 0xFF, 0x00, 0x28, 0x0D, 0xD1, 0x00, 0x23, +0x47, 0x22, 0xA3, 0x54, 0x63, 0x87, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x22, 0x49, 0x23, 0x4A, +0x9A, 0x18, 0x11, 0x80, 0x9F, 0xE7, 0x22, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xEE, 0xE7, +0xE4, 0x29, 0x16, 0x00, 0x71, 0x00, 0x10, 0x00, 0xF4, 0xE1, 0x10, 0x00, 0x38, 0x27, 0x16, 0x00, 0x70, 0xA6, 0x16, 0x00, +0x5C, 0xAB, 0x16, 0x00, 0xE4, 0xE1, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x0F, 0xC4, 0x09, 0x00, 0x00, 0x3C, 0xF6, 0xFF, 0xFF, +0xE2, 0x04, 0x00, 0x00, 0xA6, 0x0E, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xC2, 0x0C, 0x00, 0xF0, 0x29, 0x16, 0x00, +0x50, 0xE0, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x7A, 0x01, 0x61, 0x40, 0x96, 0x01, 0x61, 0x40, 0x90, 0x01, 0x61, 0x40, +0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xBC, 0x01, 0x61, 0x40, 0x7C, 0x01, 0x61, 0x40, 0x7E, 0x01, 0x61, 0x40, +0x80, 0x01, 0x61, 0x40, 0xE8, 0x29, 0x16, 0x00, 0x8A, 0x01, 0x61, 0x40, 0x76, 0x01, 0x61, 0x40, 0x72, 0x3E, 0x00, 0x00, +0x9E, 0x01, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0x10, 0x23, 0x0F, 0x4A, 0x00, 0x21, 0x0F, 0x48, 0x78, 0xF7, +0x53, 0xFC, 0x00, 0x22, 0x02, 0x70, 0x05, 0x23, 0x43, 0x70, 0x04, 0x3B, 0x83, 0x70, 0x80, 0x21, 0x89, 0x00, 0x81, 0x80, +0xFE, 0x39, 0xFF, 0x39, 0x81, 0x71, 0xC3, 0x71, 0x0B, 0x31, 0x01, 0x72, 0x43, 0x72, 0x53, 0x31, 0x41, 0x81, 0x57, 0x39, +0x81, 0x81, 0x83, 0x73, 0xC2, 0x73, 0xCA, 0xF7, 0x9B, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0xC0, 0x46, 0x53, 0xFD, 0x00, 0x00, +0x01, 0x11, 0x00, 0x00, 0x10, 0xB5, 0x10, 0x4A, 0x11, 0x68, 0xA0, 0x23, 0x5B, 0x03, 0x0B, 0x43, 0x13, 0x60, 0x0E, 0x4C, +0x01, 0x23, 0x23, 0x60, 0x05, 0x20, 0x7F, 0xF7, 0x10, 0xFD, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x49, 0x04, 0x22, 0x0B, 0x68, +0x1A, 0x42, 0xFC, 0xD0, 0x06, 0x4A, 0x13, 0x68, 0x08, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x08, 0x4C, 0x01, 0x23, 0x23, 0x60, +0x05, 0x20, 0x7F, 0xF7, 0xFE, 0xFC, 0x00, 0x23, 0x23, 0x60, 0x10, 0xBD, 0x58, 0x40, 0x34, 0x40, 0x54, 0x40, 0x34, 0x40, +0x80, 0x40, 0x34, 0x40, 0xFF, 0xFF, 0xEB, 0xFF, 0x48, 0x20, 0x62, 0x40, 0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, +0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x04, 0x90, 0x0F, 0x00, 0x16, 0x00, 0xEF, 0xF3, 0x10, 0x83, 0x01, 0x22, 0x11, 0x00, +0x19, 0x40, 0x05, 0x91, 0x1A, 0x42, 0x00, 0xD1, 0x72, 0xB6, 0x04, 0x9A, 0x93, 0x00, 0xA3, 0x49, 0x8C, 0x46, 0x63, 0x44, +0x1C, 0x68, 0xA2, 0x46, 0xA1, 0x4B, 0x63, 0x62, 0xE5, 0x6C, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD5, 0x4F, 0xE2, +0x93, 0x00, 0x9E, 0x4A, 0x9B, 0x58, 0x1A, 0x8A, 0x00, 0x2A, 0x0E, 0xD0, 0x84, 0x23, 0xE3, 0x5A, 0x5B, 0x07, 0x00, 0xD5, +0x36, 0xE2, 0x9A, 0x4B, 0x23, 0x61, 0xA2, 0x6E, 0x99, 0x4B, 0x1B, 0x68, 0x9A, 0x42, 0x00, 0xD1, 0x3C, 0xE2, 0x96, 0x4B, +0x2F, 0xE2, 0x06, 0x32, 0x1A, 0x82, 0x96, 0x48, 0x7A, 0xF7, 0xD0, 0xFC, 0xEA, 0xE7, 0x96, 0x23, 0x00, 0x22, 0xE2, 0x54, +0x00, 0x2E, 0x00, 0xD1, 0x34, 0xE2, 0x20, 0x3B, 0xE3, 0x5A, 0x00, 0x2B, 0x00, 0xD1, 0x2F, 0xE2, 0x80, 0x21, 0xC9, 0x00, +0x8E, 0x4A, 0x02, 0x40, 0x8A, 0x42, 0x00, 0xD0, 0x28, 0xE2, 0x02, 0x07, 0x00, 0xD5, 0x25, 0xE2, 0x4A, 0x22, 0xA2, 0x5C, +0x00, 0x2A, 0x00, 0xD0, 0x20, 0xE2, 0xA2, 0x6E, 0x5A, 0x43, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA1, 0x5A, +0x5B, 0x18, 0xA3, 0x52, 0x96, 0x23, 0x7D, 0x3A, 0xE2, 0x54, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x81, 0x4A, 0x93, 0x42, +0x00, 0xD8, 0x13, 0xE2, 0xE7, 0x6D, 0x2B, 0xE2, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x26, 0xE2, 0x7C, 0x33, +0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x79, 0x4A, 0x9B, 0xB2, 0x93, 0x42, +0x00, 0xD9, 0x19, 0xE2, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x21, 0xD1, 0x40, 0x33, 0xE3, 0x5A, 0x5D, 0x19, 0x2D, 0x01, +0x2D, 0x09, 0xC3, 0x07, 0x00, 0xD4, 0xCA, 0xE1, 0x44, 0x23, 0xE3, 0x5A, 0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, +0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, +0xE2, 0x54, 0x48, 0x33, 0xE0, 0x5C, 0x68, 0x4B, 0x98, 0x47, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0xBB, 0xE1, +0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, 0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, +0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, 0xA1, 0x6E, 0x2F, 0x00, 0x5E, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, +0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, 0xDB, 0xE1, 0x2F, 0x00, 0xD9, 0xE1, 0x00, 0x2B, 0x00, 0xD1, 0x5F, 0xE1, 0x68, 0xE1, +0x01, 0x3B, 0x1B, 0x01, 0x1B, 0x09, 0x56, 0x4A, 0x94, 0x46, 0xE0, 0x44, 0x78, 0xE1, 0x2B, 0x00, 0x63, 0x60, 0x50, 0x46, +0xCC, 0xF7, 0xFA, 0xFD, 0x00, 0x28, 0x00, 0xD1, 0x2E, 0xE1, 0xA3, 0x7D, 0x50, 0x49, 0x2F, 0x22, 0x8A, 0x5C, 0x9B, 0x18, +0xA3, 0x75, 0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x02, 0xD5, 0x03, 0x9B, 0x00, 0x2B, 0x4C, 0xD0, 0xA3, 0x6E, 0x9C, 0x46, +0x65, 0x44, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, 0xA3, 0x52, 0xA3, 0x7D, 0x01, 0x33, 0xA3, 0x75, +0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0x8C, 0xE0, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x99, 0x45, 0x00, 0xD8, +0xF5, 0xE0, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0xCF, 0xD5, 0x72, 0x23, 0xE3, 0x5E, 0x98, 0x46, 0x63, 0x6D, 0xEE, 0x1A, +0x36, 0x01, 0x36, 0x09, 0x77, 0xF7, 0x3C, 0xFF, 0x14, 0x23, 0x00, 0x28, 0x02, 0xD1, 0xC4, 0x33, 0x37, 0x4A, 0xD3, 0x5A, +0x7A, 0x22, 0xA0, 0x5A, 0xC0, 0x18, 0x70, 0x43, 0xC8, 0x21, 0xC9, 0x00, 0xCE, 0xF7, 0xA2, 0xFD, 0x20, 0x30, 0x46, 0x00, +0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0x00, 0xD5, 0x04, 0xE1, 0x74, 0x23, 0xE2, 0x5A, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, +0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD0, 0x05, 0xE1, 0x46, 0x23, +0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0x8E, 0xE1, 0xFF, 0xE0, 0xF7, 0xF7, 0xB1, 0xFE, 0x00, 0x28, 0xAE, 0xD0, 0x24, 0x4B, +0x1A, 0x78, 0x01, 0x23, 0x00, 0x2A, 0x08, 0xD0, 0x22, 0x4B, 0x1B, 0x78, 0x01, 0x3B, 0x5A, 0x1E, 0x93, 0x41, 0x5B, 0x42, +0x06, 0x22, 0x93, 0x43, 0x08, 0x33, 0xA0, 0x6E, 0x02, 0x00, 0x5A, 0x43, 0x80, 0x21, 0x49, 0x00, 0x8A, 0x42, 0x0C, 0xD9, +0x5A, 0x1E, 0xD2, 0xB2, 0x42, 0x43, 0x8C, 0x46, 0x00, 0xE0, 0x0A, 0x00, 0x01, 0x3B, 0xDB, 0xB2, 0x62, 0x45, 0x02, 0xD9, +0x11, 0x1A, 0x00, 0x2B, 0xF7, 0xD1, 0x55, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x7E, 0x21, 0x62, 0x5A, 0xD3, 0x18, 0x63, 0x52, +0x01, 0x23, 0x03, 0x93, 0x8B, 0xE7, 0xC0, 0x46, 0xF4, 0x29, 0x16, 0x00, 0x95, 0x9D, 0x10, 0x00, 0x5C, 0xA9, 0x16, 0x00, +0xDE, 0x0D, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xEC, 0xD3, 0x10, 0x00, 0x04, 0x04, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, +0xFE, 0x7F, 0x00, 0x00, 0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x7C, 0x91, 0x0D, 0x00, +0x8C, 0xA9, 0x16, 0x00, 0xB4, 0xE6, 0x10, 0x00, 0xB3, 0xE6, 0x10, 0x00, 0x46, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, +0x6D, 0xE7, 0x7C, 0x33, 0xE3, 0x5A, 0x7E, 0x22, 0xA2, 0x5A, 0x9B, 0x18, 0x48, 0x22, 0xA2, 0x5A, 0x9B, 0x1A, 0x9F, 0x4A, +0x9B, 0xB2, 0x93, 0x42, 0x00, 0xD9, 0x60, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x26, 0xD1, 0x40, 0x33, 0xE3, 0x5A, +0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x00, 0xD4, 0x76, 0xE0, 0x44, 0x23, 0xE3, 0x5A, +0x5B, 0x08, 0x5D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, +0xE3, 0x6B, 0xE3, 0x66, 0x8E, 0x23, 0xE0, 0x5C, 0x8E, 0x4B, 0x98, 0x47, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xE3, 0x6E, +0x99, 0x46, 0x84, 0x23, 0xE3, 0x5A, 0xDB, 0x07, 0x01, 0xD4, 0x47, 0x23, 0xE2, 0x54, 0x7C, 0x23, 0xE2, 0x5A, 0x02, 0x33, +0xE3, 0x5A, 0xD2, 0x18, 0x48, 0x23, 0xE3, 0x5A, 0xD2, 0x1A, 0x92, 0xB2, 0x53, 0x1E, 0x9B, 0xB2, 0x00, 0x2A, 0x0A, 0xD0, +0xA1, 0x6E, 0x2F, 0x00, 0x81, 0x4A, 0x7F, 0x1A, 0x3F, 0x01, 0x3F, 0x09, 0x01, 0x3B, 0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD1, +0x1D, 0xE7, 0x2F, 0x00, 0x1B, 0xE7, 0x7D, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0x7C, 0x4B, 0x1B, 0x68, 0x00, 0x21, 0x1B, 0x02, +0x0A, 0xD5, 0x7B, 0x48, 0x7A, 0xF7, 0x2E, 0xFB, 0x84, 0x23, 0xE2, 0x5A, 0x92, 0x07, 0xD2, 0x17, 0x4F, 0x3B, 0x9A, 0x43, +0x3E, 0x32, 0x0A, 0xE0, 0x01, 0x20, 0xF8, 0xF7, 0x85, 0xFA, 0x01, 0x21, 0xEF, 0xE7, 0x84, 0x23, 0xE3, 0x5A, 0x08, 0x22, +0x9B, 0x07, 0x00, 0xD4, 0xB6, 0xE0, 0x01, 0x21, 0x04, 0x98, 0x70, 0x4B, 0x98, 0x47, 0x05, 0x9B, 0x00, 0x2B, 0x00, 0xD1, +0x62, 0xB6, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x8F, 0x23, 0x00, 0x22, +0xE2, 0x54, 0xE5, 0x64, 0x0B, 0x3B, 0xE3, 0x5A, 0x9A, 0x07, 0x02, 0xD5, 0x62, 0x4A, 0x00, 0x21, 0x11, 0x70, 0xDB, 0x07, +0xE7, 0xD5, 0x70, 0x23, 0x42, 0x46, 0xE2, 0x52, 0x1C, 0x36, 0x26, 0x65, 0xE1, 0xE7, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, +0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, 0xE3, 0x66, 0x91, 0xE7, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, +0x91, 0xE0, 0xA2, 0x6E, 0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0x5B, 0x08, 0xB3, 0x42, +0xBF, 0xD9, 0x73, 0x08, 0x9B, 0x46, 0x54, 0x49, 0x18, 0x00, 0xCE, 0xF7, 0x81, 0xFC, 0x01, 0x00, 0x2B, 0x1A, 0x1B, 0x01, +0x1B, 0x09, 0x40, 0x01, 0x40, 0x1A, 0x80, 0x00, 0x40, 0x18, 0x82, 0x00, 0x80, 0x18, 0x42, 0x46, 0x59, 0x46, 0x52, 0x1A, +0x82, 0x18, 0x90, 0x46, 0x00, 0xD5, 0x7F, 0xE6, 0x42, 0x46, 0xA2, 0x60, 0x22, 0x6E, 0x92, 0x19, 0x22, 0x61, 0x81, 0xE6, +0xE3, 0x6E, 0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x08, 0x22, 0x99, 0x45, 0xA0, 0xD9, 0x00, 0x23, 0x03, 0x93, +0x1C, 0x26, 0x98, 0x46, 0x9F, 0xE6, 0xA3, 0x6B, 0xA3, 0x66, 0x42, 0x23, 0xE2, 0x5A, 0x34, 0x33, 0xE2, 0x52, 0xE3, 0x6B, +0xE3, 0x66, 0x46, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x47, 0x23, 0x01, 0x22, 0xE2, 0x54, 0x3F, 0xE6, 0x39, 0x4B, 0x23, 0x61, +0xA2, 0x6E, 0xA1, 0x6D, 0x00, 0x20, 0x01, 0x90, 0x00, 0x93, 0x00, 0x23, 0x20, 0x00, 0xF7, 0xF7, 0xC1, 0xFB, 0x35, 0x4B, +0xA2, 0x6E, 0x1A, 0x60, 0x84, 0x23, 0xE0, 0x5A, 0xC3, 0x43, 0x9B, 0x07, 0x00, 0xD1, 0xC4, 0xE5, 0x7B, 0x1B, 0x1B, 0x01, +0x1B, 0x09, 0x30, 0x4A, 0x93, 0x42, 0x13, 0xD8, 0xA1, 0x6E, 0x7E, 0x23, 0xE2, 0x5A, 0x01, 0x32, 0x92, 0xB2, 0x2C, 0x4E, +0x4D, 0x19, 0x2D, 0x01, 0x2D, 0x09, 0x03, 0x92, 0x01, 0x32, 0x92, 0xB2, 0x7B, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0xB3, 0x42, +0xF4, 0xD9, 0x7E, 0x23, 0x03, 0x9A, 0xE2, 0x52, 0xE7, 0x6D, 0x4A, 0x23, 0xE3, 0x5C, 0x01, 0x2B, 0x00, 0xD1, 0xD3, 0xE5, +0x84, 0x23, 0xE3, 0x5A, 0x9B, 0x07, 0xAB, 0xD4, 0x14, 0x23, 0xA3, 0x75, 0xA2, 0x6E, 0x53, 0x00, 0x9B, 0x18, 0x5B, 0x00, +0x99, 0x46, 0xEB, 0x1B, 0x1B, 0x01, 0x1B, 0x09, 0x4B, 0x45, 0xA7, 0xD3, 0x12, 0x4B, 0x1B, 0x78, 0x01, 0x33, 0xDB, 0xB2, +0x03, 0x2B, 0x00, 0xD9, 0x23, 0xE7, 0x0F, 0x4A, 0x13, 0x70, 0x3E, 0x22, 0x3D, 0xE7, 0x46, 0x23, 0xE3, 0x5C, 0x00, 0x2B, +0x00, 0xD1, 0x68, 0xE7, 0x00, 0x23, 0x47, 0x22, 0xA2, 0x5C, 0x00, 0x2A, 0x00, 0xD0, 0xFF, 0xE5, 0x44, 0x23, 0xE2, 0x5A, +0x53, 0x01, 0x9B, 0x1A, 0x9B, 0x00, 0x9B, 0x18, 0x9A, 0x00, 0x9B, 0x18, 0xF6, 0x18, 0x62, 0xE7, 0xFE, 0x7F, 0x00, 0x00, +0xF1, 0x12, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xE6, 0x10, 0x00, 0x58, 0x40, 0x34, 0x40, 0xF8, 0xD3, 0x10, 0x00, +0x65, 0x17, 0x0D, 0x00, 0x71, 0x02, 0x00, 0x00, 0x42, 0x0E, 0x00, 0x00, 0x64, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, +0xF8, 0xB5, 0x04, 0x1E, 0x32, 0xD0, 0xA1, 0xF7, 0x55, 0xFD, 0x05, 0x00, 0x8F, 0x23, 0xE6, 0x5C, 0x00, 0x2E, 0x17, 0xD1, +0xE3, 0x6C, 0xA2, 0x6E, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x01, 0x1B, 0x09, 0xE3, 0x64, 0x7E, 0x22, 0xA3, 0x5A, 0x01, 0x33, +0xA3, 0x52, 0xA3, 0x7D, 0x13, 0x49, 0x4F, 0x3A, 0x8A, 0x5C, 0x9B, 0x18, 0xA3, 0x75, 0x8E, 0x23, 0xE0, 0x5C, 0x00, 0x22, +0x29, 0x00, 0xFF, 0xF7, 0x01, 0xFD, 0xF8, 0xBD, 0x67, 0x68, 0xA1, 0xF7, 0x35, 0xFD, 0x03, 0x00, 0x3A, 0x00, 0x31, 0x00, +0x0B, 0x48, 0x7A, 0xF7, 0x03, 0xFA, 0x8F, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0xDA, 0xD0, 0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD3, 0xE7, 0x05, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0xE3, 0xE7, 0xC0, 0x46, 0x7C, 0x91, 0x0D, 0x00, 0x08, 0xD4, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, +0x00, 0xB5, 0x80, 0x46, 0x0F, 0x00, 0x16, 0x00, 0x1D, 0x00, 0x02, 0x21, 0x10, 0x20, 0x78, 0xF7, 0xAD, 0xF9, 0x04, 0x00, +0x04, 0x23, 0x03, 0x70, 0xFB, 0x33, 0x43, 0x70, 0xF2, 0x3B, 0x83, 0x70, 0x43, 0x46, 0xC3, 0x70, 0x47, 0x60, 0x86, 0x60, +0xC5, 0x60, 0x1F, 0x4B, 0x1B, 0x68, 0x02, 0x2B, 0x1A, 0xD0, 0x01, 0x2B, 0x30, 0xD1, 0x1D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, +0x0D, 0xD0, 0x0A, 0x25, 0x1B, 0x4F, 0x80, 0x26, 0xB6, 0x02, 0xE8, 0x20, 0x7F, 0xF7, 0xA7, 0xF9, 0x3B, 0x68, 0x33, 0x42, +0x25, 0xD1, 0x01, 0x3D, 0xED, 0xB2, 0x00, 0x2D, 0xF5, 0xD1, 0x00, 0x23, 0x15, 0x4A, 0x10, 0x21, 0x20, 0x00, 0x81, 0xF7, +0x6D, 0xFC, 0x17, 0xE0, 0x13, 0x48, 0x14, 0x49, 0x01, 0x22, 0x43, 0x58, 0x1A, 0x42, 0xFC, 0xD1, 0x10, 0x4B, 0x12, 0x4A, +0x9C, 0x50, 0x12, 0x4A, 0x99, 0x58, 0x10, 0x20, 0x01, 0x43, 0x99, 0x50, 0x81, 0x21, 0x49, 0x01, 0x5A, 0x58, 0x02, 0x43, +0x5A, 0x50, 0x0B, 0x49, 0x5A, 0x58, 0x0F, 0x38, 0x02, 0x43, 0x5A, 0x50, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0A, 0x4B, +0x80, 0x22, 0x92, 0x02, 0x1A, 0x60, 0xD8, 0xE7, 0xA8, 0xE5, 0x10, 0x00, 0x28, 0x25, 0x16, 0x00, 0x1C, 0x41, 0x04, 0x40, +0x19, 0x74, 0x08, 0x00, 0x00, 0x00, 0x07, 0x40, 0x08, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1C, 0x10, 0x00, 0x00, +0x08, 0x41, 0x04, 0x40, 0x02, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x41, 0x04, 0x40, +0x10, 0xB5, 0x01, 0x00, 0x13, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x74, 0x46, 0x0E, 0x4A, +0x94, 0x42, 0x0F, 0xD0, 0x22, 0x00, 0x0D, 0x48, 0x7A, 0xF7, 0x6A, 0xF9, 0x23, 0x00, 0x00, 0x22, 0x00, 0x21, 0x57, 0x20, +0xFF, 0xF7, 0x7A, 0xFF, 0x09, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x05, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x07, 0x48, 0x7A, 0xF7, +0x5B, 0xF9, 0x10, 0xBD, 0x06, 0x4B, 0x80, 0x22, 0xD2, 0x04, 0x1A, 0x60, 0xF4, 0xE7, 0xC0, 0x46, 0xB9, 0x25, 0x0D, 0x00, +0x40, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x18, 0xD4, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0x70, 0xB5, 0x82, 0xB0, +0x04, 0x00, 0x0D, 0x00, 0xEF, 0xF3, 0x10, 0x82, 0xD2, 0x07, 0x00, 0xD4, 0x72, 0xB6, 0x76, 0x46, 0x00, 0x93, 0x33, 0x00, +0x2A, 0x00, 0x21, 0x00, 0x09, 0x48, 0x7A, 0xF7, 0x39, 0xF9, 0x33, 0x00, 0x2A, 0x00, 0x21, 0x00, 0x57, 0x20, 0xFF, 0xF7, +0x49, 0xFF, 0x06, 0x4B, 0x1B, 0x68, 0x01, 0x2B, 0x01, 0xD0, 0x72, 0xB6, 0xFE, 0xE7, 0x04, 0x4B, 0x80, 0x22, 0xD2, 0x04, +0x1A, 0x60, 0xF8, 0xE7, 0x64, 0xD4, 0x10, 0x00, 0xA8, 0xE5, 0x10, 0x00, 0x00, 0x41, 0x04, 0x40, 0xF0, 0xB5, 0xDE, 0x46, +0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x87, 0xB0, 0x65, 0x4B, 0x1E, 0x68, 0x07, 0x20, 0xA1, 0xF7, 0xA4, 0xF9, +0x00, 0x28, 0x06, 0xD1, 0x07, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x5F, 0x4A, +0xD5, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0xDC, 0x00, 0xE4, 0x1A, 0x64, 0x00, 0x5C, 0x4B, 0xE3, 0x18, 0x1D, 0x88, 0xAD, 0xB2, +0xA1, 0xF7, 0x62, 0xF9, 0x6B, 0x07, 0xE9, 0xD1, 0x3A, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x52, 0xD0, 0x57, 0x4B, 0xE3, 0x18, +0x1B, 0x88, 0x9B, 0xB2, 0x98, 0x46, 0x56, 0x4B, 0xE2, 0x18, 0x13, 0x88, 0x5B, 0x06, 0x1B, 0x0F, 0x02, 0x2B, 0x08, 0xD0, +0x10, 0x88, 0x40, 0x06, 0x00, 0x0F, 0x52, 0x4B, 0xDF, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xB8, 0x47, 0x39, 0x23, +0xF3, 0x5C, 0x00, 0x2B, 0x01, 0xD0, 0xEB, 0x05, 0x53, 0xD4, 0x10, 0x23, 0xFF, 0x22, 0x00, 0x21, 0x4B, 0x48, 0x77, 0xF7, +0xD5, 0xFF, 0x07, 0x00, 0x00, 0x23, 0x83, 0x73, 0xFB, 0x1D, 0xBA, 0x1D, 0x02, 0x92, 0x05, 0xAA, 0x01, 0x92, 0x00, 0x22, +0x00, 0x92, 0x3A, 0x00, 0x00, 0x21, 0x40, 0x46, 0xB0, 0xF7, 0x7C, 0xFC, 0x43, 0x4B, 0x19, 0x88, 0x43, 0x4B, 0x1B, 0x88, +0x05, 0x9A, 0x92, 0x00, 0x09, 0x04, 0x0B, 0x43, 0xD3, 0x1A, 0x6A, 0xD4, 0xDB, 0x03, 0x5B, 0x0C, 0x7B, 0x81, 0x3F, 0x4B, +0x9C, 0x46, 0x64, 0x44, 0x23, 0x88, 0x3B, 0x73, 0xED, 0x05, 0xED, 0x0F, 0x7D, 0x73, 0x38, 0x00, 0x77, 0xF7, 0xD8, 0xFF, +0x3C, 0x23, 0xF3, 0x5C, 0x3B, 0x22, 0xB2, 0x5C, 0x9A, 0x42, 0x00, 0xD8, 0x96, 0xE7, 0x01, 0x33, 0x3C, 0x22, 0xB3, 0x54, +0x92, 0xE7, 0x37, 0x33, 0xF3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x8D, 0xE7, 0xEB, 0x05, 0x00, 0xD4, 0x8A, 0xE7, 0x07, 0x20, +0xA1, 0xF7, 0x2A, 0xF9, 0x00, 0x28, 0x00, 0xD1, 0x84, 0xE7, 0x25, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, +0x9B, 0x1A, 0x5B, 0x00, 0x22, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xA1, 0xF7, 0xEE, 0xF8, 0x76, 0xE7, 0x07, 0x20, +0xA1, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0xA6, 0xD0, 0x1B, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, +0x5B, 0x00, 0x19, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0x52, 0x07, 0x02, 0xD0, 0xA1, 0xF7, 0xDA, 0xF8, 0x97, 0xE7, 0x1D, 0x4A, +0x9A, 0x18, 0x11, 0x88, 0x8A, 0xB2, 0x91, 0x46, 0x1B, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0xDB, 0x08, 0x9B, 0x46, +0xFF, 0x23, 0x5A, 0x46, 0x1A, 0x40, 0x92, 0x46, 0x13, 0x00, 0x10, 0x33, 0xFF, 0x22, 0x00, 0x21, 0x0F, 0x48, 0x77, 0xF7, +0x5D, 0xFF, 0x07, 0x00, 0x5B, 0x46, 0x83, 0x73, 0x12, 0x49, 0x49, 0x44, 0x0F, 0x30, 0x52, 0x46, 0xCE, 0xF7, 0x4C, 0xFE, +0xA1, 0xF7, 0xB8, 0xF8, 0x7E, 0xE7, 0x80, 0x22, 0x52, 0x05, 0x94, 0x46, 0x63, 0x44, 0x8F, 0xE7, 0x18, 0x27, 0x16, 0x00, +0x20, 0xA3, 0x16, 0x00, 0x92, 0x69, 0x61, 0x40, 0x9C, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, +0x01, 0x05, 0x00, 0x00, 0xFA, 0x67, 0x61, 0x40, 0xF8, 0x67, 0x61, 0x40, 0x98, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, +0x96, 0x69, 0x61, 0x40, 0x00, 0x00, 0x61, 0x40, 0x70, 0xB5, 0xA1, 0xF7, 0x5F, 0xFB, 0x05, 0x00, 0x0F, 0x4B, 0x1C, 0x68, +0x00, 0x2C, 0x06, 0xD1, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x70, 0xBD, 0xFF, 0xF7, +0x03, 0xFF, 0x01, 0x21, 0x20, 0x00, 0xCC, 0xF7, 0x81, 0xFB, 0x3A, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x06, 0xD0, 0x07, 0x4B, +0x1B, 0x7D, 0xA3, 0x75, 0x65, 0x60, 0x06, 0x4B, 0x98, 0x47, 0xED, 0xE7, 0x05, 0x4B, 0x98, 0x47, 0xEA, 0xE7, 0xC0, 0x46, +0x18, 0x27, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0xE5, 0xC1, 0x0A, 0x00, 0x99, 0xC1, 0x0A, 0x00, +0x70, 0xB5, 0x0D, 0x00, 0x14, 0x00, 0x07, 0x29, 0x06, 0xD0, 0x11, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, +0x28, 0x00, 0xB0, 0x47, 0x01, 0x2C, 0x0E, 0xD9, 0x04, 0x2C, 0x0F, 0xD1, 0x0C, 0x4B, 0x1C, 0x68, 0x01, 0x21, 0x20, 0x00, +0xCC, 0xF7, 0x52, 0xFB, 0x3A, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x20, 0x00, 0x08, 0x4B, 0x98, 0x47, 0x01, 0xE0, 0xFF, 0xF7, +0xB3, 0xFF, 0x70, 0xBD, 0x03, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0x28, 0x00, 0xB0, 0x47, 0xF6, 0xE7, +0x28, 0x19, 0x16, 0x00, 0x18, 0x27, 0x16, 0x00, 0xD1, 0xC2, 0x0A, 0x00, 0x10, 0xB5, 0x01, 0x28, 0x00, 0xD0, 0x10, 0xBD, +0x00, 0x29, 0xFC, 0xD0, 0x04, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0xF8, 0xD0, 0x03, 0x4A, 0xDA, 0x61, 0x03, 0x48, 0x79, 0xF7, +0xCB, 0xFF, 0xF2, 0xE7, 0x24, 0x27, 0x16, 0x00, 0x85, 0x04, 0x10, 0x00, 0x94, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x1E, 0x4B, +0x1E, 0x4A, 0x13, 0x60, 0x80, 0x22, 0x52, 0x00, 0x9C, 0x5C, 0x1D, 0x4B, 0xE3, 0x18, 0x1B, 0x01, 0x1A, 0x88, 0xD2, 0x08, +0x06, 0x21, 0x11, 0x42, 0x08, 0xD1, 0x19, 0x88, 0x89, 0x06, 0x49, 0x0F, 0x18, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, +0x20, 0x00, 0xA8, 0x47, 0x13, 0x4B, 0x1A, 0x68, 0x81, 0x23, 0x5B, 0x00, 0xD3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x12, 0x4B, +0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x0D, 0x4B, 0x1B, 0x68, 0x22, 0x01, 0x9B, 0x18, 0x1B, 0x7B, +0x00, 0x2B, 0x05, 0xD1, 0x0B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x06, 0x4B, 0x1A, 0x68, +0x23, 0x01, 0xD3, 0x18, 0x5D, 0x68, 0x00, 0x2D, 0x03, 0xD0, 0x99, 0x68, 0x18, 0x68, 0x02, 0x22, 0xA8, 0x47, 0x70, 0xBD, +0x80, 0x2A, 0x16, 0x00, 0x0C, 0xE7, 0x10, 0x00, 0x00, 0x10, 0x06, 0x04, 0x28, 0x19, 0x16, 0x00, 0x10, 0xB5, 0xFF, 0x23, +0x9B, 0x00, 0x98, 0x42, 0x08, 0xD9, 0x05, 0x4B, 0x59, 0x80, 0x00, 0x24, 0x21, 0x00, 0x04, 0x48, 0x79, 0xF7, 0x72, 0xFF, +0x20, 0x00, 0x10, 0xBD, 0x11, 0x24, 0xF7, 0xE7, 0x54, 0x2A, 0x16, 0x00, 0xA0, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, +0x0D, 0x00, 0x81, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xE5, 0xFF, 0x01, 0x1E, 0x04, 0xD0, 0x28, 0x00, 0xFC, 0xF7, 0x90, 0xFE, +0x00, 0x20, 0x70, 0xBD, 0xE1, 0x88, 0xA0, 0x78, 0xCB, 0xF7, 0xB6, 0xFE, 0x01, 0x00, 0xF4, 0xE7, 0xF0, 0xB5, 0xCE, 0x46, +0x47, 0x46, 0x80, 0xB5, 0x89, 0xB0, 0x06, 0x00, 0x0A, 0x00, 0x04, 0x23, 0x00, 0x21, 0x26, 0x48, 0x77, 0xF7, 0x46, 0xFE, +0x80, 0x46, 0x00, 0x23, 0x43, 0x80, 0xB1, 0x79, 0x23, 0x48, 0x79, 0xF7, 0x43, 0xFF, 0xB3, 0x79, 0x00, 0x2B, 0x2A, 0xD1, +0x60, 0x24, 0x6B, 0x46, 0xDD, 0x1D, 0x16, 0x23, 0x99, 0x46, 0x1F, 0x4F, 0x07, 0xE0, 0x03, 0x23, 0x42, 0x46, 0x13, 0x70, +0x24, 0xE0, 0x01, 0x34, 0xE4, 0xB2, 0x68, 0x2C, 0x20, 0xD0, 0x4B, 0x46, 0x2B, 0x70, 0x02, 0xAA, 0x29, 0x00, 0x20, 0x00, +0x3B, 0x68, 0x98, 0x47, 0x00, 0x28, 0xF2, 0xD1, 0x06, 0x22, 0x02, 0xA9, 0x30, 0x00, 0xCE, 0xF7, 0xF3, 0xFC, 0x00, 0x28, +0xEB, 0xD1, 0x12, 0x4B, 0x9B, 0x68, 0x20, 0x00, 0x98, 0x47, 0x00, 0x28, 0xE1, 0xD1, 0x43, 0x46, 0x5B, 0x88, 0x01, 0x33, +0x42, 0x46, 0x53, 0x80, 0x04, 0xE0, 0x01, 0x2B, 0x0B, 0xD0, 0x12, 0x23, 0x42, 0x46, 0x13, 0x70, 0x40, 0x46, 0xC9, 0xF7, +0x69, 0xFC, 0x00, 0x20, 0x09, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x43, 0x46, 0x5B, 0x88, 0x08, 0x33, +0x42, 0x46, 0x53, 0x80, 0xF0, 0xE7, 0xC0, 0x46, 0x01, 0x11, 0x00, 0x00, 0xAC, 0xD4, 0x10, 0x00, 0x94, 0x92, 0x16, 0x00, +0xF0, 0xB5, 0xDE, 0x46, 0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x85, 0xB0, 0x0C, 0x00, 0x16, 0x00, 0x17, 0x0A, +0xBA, 0x00, 0x91, 0x4B, 0xD5, 0x58, 0x50, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0x4B, 0x78, 0x5B, 0x08, +0x98, 0x46, 0x7F, 0x2B, 0x11, 0xD0, 0x01, 0x93, 0x00, 0x22, 0x19, 0x00, 0x8A, 0x48, 0x79, 0xF7, 0xDD, 0xFE, 0x43, 0x46, +0x7E, 0x2B, 0x56, 0xD1, 0x36, 0x3B, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, +0x0C, 0xE0, 0x8B, 0x78, 0x9B, 0x46, 0x1A, 0x00, 0x7F, 0x21, 0x81, 0x48, 0x79, 0xF7, 0xCA, 0xFE, 0x7F, 0x23, 0x01, 0x93, +0x48, 0x23, 0xEB, 0x5C, 0x00, 0x2B, 0x43, 0xD0, 0xFB, 0xB2, 0x99, 0x46, 0x61, 0x78, 0x4F, 0x08, 0x59, 0x29, 0x00, 0xD8, +0xE0, 0xE0, 0x7F, 0x2F, 0x05, 0xD1, 0xA3, 0x78, 0x9A, 0x46, 0x0D, 0x2B, 0x55, 0xD8, 0x0B, 0x2B, 0x55, 0xD8, 0x07, 0x23, +0x02, 0xAA, 0x94, 0x46, 0x63, 0x44, 0x9A, 0x46, 0x23, 0x78, 0x52, 0x46, 0x13, 0x70, 0x14, 0x23, 0x32, 0x00, 0x31, 0x00, +0x70, 0x48, 0x77, 0xF7, 0xA3, 0xFD, 0x07, 0x00, 0x61, 0x1C, 0x52, 0x46, 0x82, 0xF7, 0x30, 0xF9, 0x02, 0x28, 0x75, 0xD0, +0x00, 0x28, 0x00, 0xD1, 0xA9, 0xE0, 0x04, 0x28, 0x00, 0xD0, 0x99, 0xE0, 0xFB, 0x22, 0x43, 0x46, 0x15, 0x3B, 0x13, 0x42, +0x00, 0xD1, 0xB1, 0xE0, 0x19, 0x24, 0x6F, 0xE0, 0x36, 0x33, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, +0x0C, 0x22, 0x7E, 0x21, 0x9F, 0xF7, 0xC7, 0xFA, 0x00, 0x23, 0x9B, 0x46, 0x7E, 0x33, 0x01, 0x93, 0xBE, 0xE7, 0x00, 0x23, +0x9B, 0x46, 0xB7, 0xE7, 0x59, 0x46, 0x40, 0x46, 0x82, 0xF7, 0x96, 0xF8, 0x00, 0x28, 0xB5, 0xD1, 0x43, 0x46, 0x7F, 0x2B, +0x0A, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x41, 0x46, 0x9F, 0xF7, +0xAC, 0xFA, 0x5A, 0xE0, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0xF8, 0xB2, 0x0C, 0x22, 0x59, 0x46, +0x9F, 0xF7, 0xB0, 0xFA, 0x4F, 0xE0, 0x15, 0x2B, 0xA9, 0xD1, 0x4B, 0x46, 0x9B, 0x00, 0x48, 0x4A, 0x9B, 0x58, 0xB2, 0x22, +0x92, 0x00, 0x9A, 0x5C, 0x00, 0x2A, 0xA0, 0xD0, 0xCA, 0x07, 0x9E, 0xD5, 0x46, 0x4A, 0x9A, 0x5C, 0xBA, 0x42, 0x14, 0xD1, +0x7F, 0x2F, 0x98, 0xD1, 0x44, 0x4A, 0x9B, 0x5C, 0x53, 0x45, 0x94, 0xD0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, +0x78, 0xF7, 0x16, 0xF9, 0x00, 0x28, 0x30, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x51, 0x46, 0x48, 0x46, 0x9F, 0xF7, 0x8A, 0xFA, +0x29, 0xE0, 0x4B, 0x46, 0x1B, 0x02, 0x01, 0x20, 0x18, 0x43, 0x78, 0xF7, 0x07, 0xF9, 0x00, 0x28, 0x21, 0xD0, 0x7F, 0x2F, +0xEE, 0xD0, 0x01, 0x23, 0x2A, 0x22, 0x39, 0x00, 0x48, 0x46, 0x9F, 0xF7, 0x6A, 0xFA, 0x18, 0xE0, 0x33, 0x4B, 0xDC, 0x6E, +0x00, 0x23, 0x00, 0x22, 0x01, 0x99, 0x08, 0x00, 0xA0, 0x47, 0x1E, 0x24, 0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x69, 0xFD, +0x43, 0x46, 0x7F, 0x2B, 0x1C, 0xD0, 0x36, 0x23, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x41, 0x46, +0x48, 0x46, 0x9F, 0xF7, 0x50, 0xFA, 0x8A, 0x23, 0xFF, 0x33, 0xEB, 0x5C, 0x00, 0x2B, 0x03, 0xD0, 0x25, 0x4B, 0xEB, 0x5C, +0x00, 0x2B, 0x18, 0xD1, 0x00, 0x20, 0x05, 0xB0, 0x3C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, +0x1E, 0x24, 0xDB, 0xE7, 0x49, 0x3B, 0xEB, 0x5C, 0x5A, 0x42, 0x53, 0x41, 0xDB, 0xB2, 0x22, 0x00, 0x59, 0x46, 0x48, 0x46, +0x9F, 0xF7, 0x42, 0xFA, 0xE1, 0xE7, 0x38, 0x00, 0x77, 0xF7, 0x16, 0xFD, 0xDD, 0xE7, 0xAA, 0x8D, 0xEB, 0x8D, 0xD2, 0x1A, +0x31, 0x00, 0x16, 0x48, 0x77, 0xF7, 0x24, 0xFC, 0xAA, 0x8D, 0x31, 0x00, 0x14, 0x48, 0x77, 0xF7, 0x1F, 0xFC, 0xD9, 0xE7, +0x38, 0x00, 0x0C, 0x38, 0x77, 0xF7, 0x29, 0xFD, 0x1A, 0x24, 0xC0, 0xE7, 0x12, 0x2F, 0x00, 0xD8, 0x23, 0xE7, 0x3A, 0x00, +0x13, 0x3A, 0xD2, 0xB2, 0x01, 0x23, 0x93, 0x40, 0x0C, 0x4A, 0x13, 0x42, 0x00, 0xD1, 0x1A, 0xE7, 0x00, 0x23, 0x9A, 0x46, +0x6D, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0xBC, 0xD4, 0x10, 0x00, 0x01, 0x06, 0x00, 0x00, 0xC6, 0x02, 0x00, 0x00, +0xC7, 0x02, 0x00, 0x00, 0x28, 0x19, 0x16, 0x00, 0xAF, 0x02, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00, +0x31, 0x00, 0x00, 0x03, 0x30, 0xB5, 0x87, 0xB0, 0x1E, 0x4C, 0x23, 0x7B, 0x03, 0x22, 0x13, 0x43, 0x23, 0x73, 0x03, 0xAD, +0x21, 0x00, 0x27, 0x31, 0x03, 0x22, 0x28, 0x00, 0xCE, 0xF7, 0x9E, 0xFB, 0xE3, 0x89, 0xAB, 0x80, 0x23, 0x8A, 0xEB, 0x80, +0xA3, 0x7C, 0x2B, 0x72, 0x23, 0x7F, 0x6B, 0x72, 0x28, 0x00, 0xA2, 0xF7, 0x3F, 0xFB, 0x23, 0x00, 0x3C, 0x33, 0x00, 0x24, +0x1A, 0x78, 0x00, 0x2A, 0x06, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0x07, 0xB0, 0x30, 0xBD, +0x06, 0x2C, 0xFB, 0xD8, 0x01, 0xA8, 0x0B, 0x4B, 0x1A, 0x8B, 0x02, 0x80, 0x5A, 0x8B, 0x42, 0x80, 0x5B, 0x7F, 0x03, 0x71, +0x44, 0x71, 0x08, 0x4A, 0xD0, 0x23, 0xD3, 0x58, 0x98, 0x47, 0x00, 0x28, 0xEC, 0xD1, 0xE3, 0x00, 0x1B, 0x19, 0x03, 0x4C, +0xE4, 0x18, 0x3C, 0x34, 0x02, 0x23, 0x23, 0x70, 0xE4, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, +0x10, 0xB5, 0x07, 0x4C, 0xA0, 0x47, 0x86, 0xF7, 0x97, 0xF8, 0x00, 0x28, 0x01, 0xD1, 0x00, 0x20, 0x10, 0xBD, 0xFF, 0xF7, +0xB1, 0xFF, 0x03, 0x48, 0x79, 0xF7, 0x66, 0xFD, 0xF7, 0xE7, 0xC0, 0x46, 0xDD, 0x90, 0x0A, 0x00, 0xCC, 0xD4, 0x10, 0x00, +0x00, 0xB5, 0x83, 0xB0, 0x01, 0xAA, 0x01, 0x23, 0x0B, 0x40, 0x30, 0x21, 0x0B, 0x43, 0x13, 0x70, 0x11, 0x00, 0x9F, 0xF7, +0x41, 0xF9, 0x03, 0xB0, 0x00, 0xBD, 0x00, 0x00, 0x30, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x0E, 0x4B, +0xD2, 0x58, 0x3C, 0x23, 0xD3, 0x5C, 0x02, 0x2B, 0x07, 0xD0, 0x96, 0x22, 0x52, 0x00, 0x21, 0x00, 0x0A, 0x48, 0x77, 0xF7, +0x7D, 0xFB, 0x03, 0xB0, 0x30, 0xBD, 0x6B, 0x46, 0x9D, 0x1D, 0xC0, 0xB2, 0x00, 0x22, 0x29, 0x00, 0x89, 0xF7, 0xEE, 0xFA, +0x28, 0x88, 0x79, 0xF7, 0x95, 0xFD, 0x40, 0x00, 0x02, 0x00, 0x2D, 0x32, 0xFF, 0x32, 0xEA, 0xE7, 0x64, 0xA2, 0x16, 0x00, +0x05, 0x06, 0x00, 0x00, 0x10, 0xB5, 0x04, 0x00, 0x00, 0x0A, 0x82, 0x00, 0x07, 0x4B, 0xD2, 0x58, 0x36, 0x23, 0xD1, 0x5C, +0xC0, 0xB2, 0xFF, 0xF7, 0xC1, 0xFF, 0x20, 0x00, 0xFF, 0xF7, 0xCC, 0xFF, 0x32, 0x21, 0x20, 0x00, 0x77, 0xF7, 0x8C, 0xFF, +0x10, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x17, 0x4B, 0xD6, 0x58, +0x20, 0x00, 0x77, 0xF7, 0xDF, 0xFF, 0x03, 0x00, 0x19, 0x28, 0x1D, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x06, 0xD8, +0x02, 0x20, 0x01, 0x2B, 0x15, 0xD1, 0x3C, 0x23, 0xF3, 0x5C, 0x02, 0x2B, 0x16, 0xD0, 0x08, 0x23, 0x14, 0x22, 0x00, 0x21, +0x0D, 0x48, 0x77, 0xF7, 0xF5, 0xFB, 0x0C, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0xC3, 0x80, 0x3C, 0x33, +0xF3, 0x5C, 0x03, 0x71, 0xC9, 0xF7, 0x4A, 0xFA, 0x00, 0x20, 0x70, 0xBD, 0x02, 0x20, 0x66, 0x2B, 0xFB, 0xD1, 0xE4, 0xE7, +0x20, 0x00, 0xFF, 0xF7, 0xB9, 0xFF, 0x00, 0x20, 0xF5, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, +0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x24, 0x4B, 0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0xA6, 0xFF, +0x01, 0x28, 0x16, 0xD0, 0x04, 0xD9, 0x16, 0x38, 0xC3, 0xB2, 0x02, 0x20, 0x03, 0x2B, 0x0E, 0xD8, 0x06, 0x23, 0x1C, 0x22, +0x00, 0x21, 0x1D, 0x48, 0x77, 0xF7, 0xC2, 0xFB, 0x02, 0x23, 0x03, 0x70, 0x80, 0x35, 0x45, 0x80, 0x00, 0x23, 0x83, 0x80, +0xC9, 0xF7, 0x1A, 0xFA, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x36, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x0E, 0xD1, 0x01, 0xA9, +0x0A, 0x33, 0x0B, 0x70, 0xE8, 0xB2, 0x9F, 0xF7, 0x9D, 0xF8, 0x20, 0x00, 0xFF, 0xF7, 0x5C, 0xFF, 0x06, 0x21, 0x20, 0x00, +0x77, 0xF7, 0x1C, 0xFF, 0x00, 0x20, 0xEA, 0xE7, 0x06, 0x23, 0x1C, 0x22, 0x00, 0x21, 0x0B, 0x48, 0x77, 0xF7, 0x9E, 0xFB, +0x04, 0x00, 0x00, 0x23, 0x03, 0x70, 0x2B, 0x00, 0x80, 0x33, 0x43, 0x80, 0xE8, 0xB2, 0xA8, 0xF7, 0x3D, 0xFF, 0x00, 0x04, +0x40, 0x0C, 0xA0, 0x80, 0x20, 0x00, 0xC9, 0xF7, 0xEF, 0xF9, 0x00, 0x20, 0xD3, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, +0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x14, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, +0x55, 0xFF, 0x00, 0x28, 0x1E, 0xD0, 0x16, 0x38, 0xC3, 0xB2, 0x00, 0x20, 0x03, 0x2B, 0x13, 0xD9, 0x43, 0x23, 0x01, 0x22, +0xEA, 0x54, 0x07, 0x3B, 0xEB, 0x5C, 0x02, 0x2B, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x8B, 0xF7, 0x32, 0xF8, +0x00, 0x28, 0x0D, 0xD0, 0x37, 0x23, 0xE9, 0x5C, 0x20, 0x00, 0x90, 0xF7, 0x57, 0xFF, 0x00, 0x20, 0x70, 0xBD, 0x20, 0x00, +0x89, 0xF7, 0xFE, 0xFD, 0x02, 0x20, 0xF9, 0xE7, 0x00, 0x20, 0xF7, 0xE7, 0x02, 0x20, 0xF5, 0xE7, 0x64, 0xA2, 0x16, 0x00, +0x10, 0xB5, 0x80, 0x00, 0x0F, 0x4B, 0xC4, 0x58, 0x8E, 0xF7, 0xD4, 0xFC, 0x03, 0x00, 0x01, 0x20, 0x0B, 0x2B, 0x13, 0xD9, +0x11, 0x2B, 0x06, 0xD8, 0x20, 0x00, 0x54, 0x30, 0x00, 0x21, 0x9E, 0xF7, 0x53, 0xFF, 0x00, 0x28, 0x0B, 0xD1, 0x20, 0x00, +0x54, 0x30, 0x01, 0x21, 0x9E, 0xF7, 0x4C, 0xFF, 0x43, 0x42, 0x58, 0x41, 0x40, 0x42, 0x03, 0x23, 0x98, 0x43, 0x05, 0x30, +0x10, 0xBD, 0x03, 0x20, 0xFC, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x02, 0x00, 0x00, 0x29, 0x16, 0xD1, 0x01, 0x23, +0x03, 0x40, 0x58, 0x42, 0x43, 0x41, 0x58, 0x42, 0x20, 0x4B, 0x18, 0x40, 0x20, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x06, 0x23, +0x1A, 0x40, 0x04, 0x2A, 0x02, 0xD0, 0x02, 0x2A, 0x03, 0xD0, 0x70, 0x47, 0x80, 0x04, 0x80, 0x0C, 0xFB, 0xE7, 0x1B, 0x4B, +0x18, 0x40, 0xF8, 0xE7, 0x18, 0x23, 0x19, 0x00, 0x01, 0x40, 0x03, 0x42, 0x21, 0xD0, 0x08, 0x29, 0x0E, 0xD0, 0x60, 0x23, +0x03, 0x40, 0x40, 0x2B, 0x21, 0xD0, 0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x12, 0x4B, 0x18, 0x40, +0x12, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xE2, 0xE7, 0x48, 0x33, 0x03, 0x40, 0x60, 0x2B, 0x0E, 0xD0, 0x40, 0x2B, 0x0E, 0xD0, +0x20, 0x3B, 0x18, 0x00, 0x43, 0x1E, 0x98, 0x41, 0x40, 0x42, 0x0C, 0x4B, 0x18, 0x40, 0x0C, 0x4B, 0x9C, 0x46, 0x60, 0x44, +0xD1, 0xE7, 0x0B, 0x48, 0xCF, 0xE7, 0x0B, 0x48, 0xCD, 0xE7, 0x0B, 0x48, 0xCB, 0xE7, 0x0B, 0x48, 0xC9, 0xE7, 0xC0, 0x46, +0xF0, 0x77, 0xFF, 0xFF, 0x1E, 0xFF, 0x00, 0x00, 0xFF, 0x33, 0x00, 0x00, 0x00, 0xCD, 0xFF, 0xFF, 0x08, 0x33, 0x00, 0x00, +0x00, 0xEF, 0xFF, 0xFF, 0x0C, 0x33, 0x00, 0x00, 0x0E, 0x33, 0x00, 0x00, 0x0C, 0x22, 0x00, 0x00, 0x0C, 0x32, 0x00, 0x00, +0x08, 0x30, 0x00, 0x00, 0x70, 0xB5, 0x05, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x77, 0xF7, 0xA4, 0xFE, 0x03, 0x00, 0x01, 0x28, +0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, 0x40, 0x42, +0x40, 0x00, 0x70, 0xBD, 0x24, 0x0A, 0xA2, 0x00, 0x0F, 0x4B, 0xD6, 0x58, 0x3F, 0x23, 0xF1, 0x5C, 0x68, 0x78, 0xFF, 0xF7, +0x83, 0xFF, 0x70, 0x85, 0xE4, 0xB2, 0x20, 0x00, 0xFF, 0xF7, 0x5A, 0xFF, 0x9E, 0xF7, 0x5C, 0xFF, 0x71, 0x8D, 0x01, 0x22, +0x9E, 0xF7, 0x08, 0xFD, 0x31, 0x8C, 0x01, 0x22, 0x9E, 0xF7, 0x04, 0xFD, 0x01, 0x00, 0x33, 0x8C, 0x00, 0x20, 0x8B, 0x42, +0xE1, 0xD0, 0x20, 0x00, 0xA8, 0xF7, 0xA2, 0xFF, 0x00, 0x20, 0xDC, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, +0x00, 0xB5, 0x05, 0x00, 0x08, 0x00, 0x0E, 0x0A, 0xB2, 0x00, 0x29, 0x4B, 0xD4, 0x58, 0x77, 0xF7, 0x67, 0xFE, 0x00, 0x28, +0x03, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x03, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x78, +0x01, 0x27, 0x3B, 0x40, 0x39, 0x22, 0xA3, 0x54, 0x54, 0x23, 0x98, 0x46, 0xA0, 0x44, 0x69, 0x1C, 0x31, 0x3A, 0x40, 0x46, +0xCE, 0xF7, 0x72, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, +0x8B, 0x43, 0xA3, 0x54, 0x29, 0x78, 0x39, 0x40, 0xF0, 0xB2, 0x9F, 0xF7, 0x2D, 0xF9, 0x09, 0x21, 0x40, 0x46, 0x9E, 0xF7, +0x73, 0xFE, 0x00, 0x28, 0x0D, 0xD1, 0x85, 0xF7, 0x8F, 0xFE, 0x00, 0x28, 0x02, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xE2, 0x54, +0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0xCB, 0xE7, 0x3A, 0x21, 0x40, 0x46, 0x9E, 0xF7, +0x5F, 0xFE, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, 0x04, 0xD0, 0x05, 0x4A, +0x05, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xDD, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, +0x7C, 0x1E, 0x16, 0x00, 0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x0B, 0x0A, +0x98, 0x46, 0x9A, 0x00, 0x32, 0x4B, 0xD4, 0x58, 0x27, 0x00, 0x54, 0x37, 0x41, 0x1C, 0x08, 0x22, 0x38, 0x00, 0xCE, 0xF7, +0x23, 0xF9, 0x57, 0x22, 0xA3, 0x5C, 0x04, 0x21, 0x8B, 0x43, 0xA3, 0x54, 0x02, 0x32, 0xA3, 0x5C, 0x3E, 0x31, 0x8B, 0x43, +0xA3, 0x54, 0x28, 0x00, 0x77, 0xF7, 0xF4, 0xFD, 0x14, 0x28, 0x13, 0xD0, 0x07, 0xD9, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, +0x05, 0xD8, 0x00, 0x20, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x00, 0x28, 0xF9, 0xD0, 0x28, 0x00, 0x77, 0xF7, 0xE4, 0xFD, +0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0x7D, 0xF7, 0xB1, 0xF8, 0xF0, 0xE7, 0x29, 0x00, 0x1D, 0x48, 0x77, 0xF7, 0xBC, 0xF9, +0x32, 0x78, 0x01, 0x23, 0x13, 0x40, 0x3A, 0x22, 0xA3, 0x54, 0x09, 0x21, 0x38, 0x00, 0x9E, 0xF7, 0x07, 0xFE, 0x00, 0x28, +0x11, 0xD1, 0xBC, 0x22, 0x52, 0x00, 0xA3, 0x5C, 0x01, 0x21, 0x0B, 0x43, 0xA3, 0x54, 0x3F, 0x21, 0x38, 0x00, 0x9E, 0xF7, +0xFB, 0xFD, 0x00, 0x28, 0x19, 0xD0, 0x01, 0x22, 0x41, 0x46, 0x28, 0x00, 0x91, 0xF7, 0xE6, 0xF8, 0xCF, 0xE7, 0x3A, 0x21, +0x38, 0x00, 0x9E, 0xF7, 0xEF, 0xFD, 0x02, 0x00, 0x53, 0x1E, 0x9A, 0x41, 0x4F, 0x23, 0xE2, 0x54, 0x00, 0x23, 0x00, 0x28, +0x04, 0xD0, 0x08, 0x4A, 0x08, 0x4B, 0xD3, 0x5C, 0x5B, 0x07, 0xDB, 0x0F, 0x4F, 0x22, 0xA3, 0x54, 0xD9, 0xE7, 0x01, 0x21, +0x28, 0x00, 0x77, 0xF7, 0x45, 0xFD, 0xB6, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x06, 0x00, 0x00, 0x7C, 0x1E, 0x16, 0x00, +0xA2, 0x02, 0x00, 0x00, 0xF0, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x83, 0xB0, 0x04, 0x00, 0x0D, 0x00, 0x0E, 0x0A, +0xB2, 0x00, 0x35, 0x4B, 0xD7, 0x58, 0x02, 0x78, 0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xBB, 0x54, 0x36, 0x23, 0xFB, 0x5C, +0x98, 0x46, 0x33, 0x01, 0x9B, 0x1B, 0x9B, 0x00, 0x2F, 0x4A, 0xD3, 0x18, 0x5B, 0x7B, 0x99, 0x46, 0x08, 0x00, 0x77, 0xF7, +0x7F, 0xFD, 0x02, 0x00, 0x19, 0x28, 0x1B, 0xD8, 0x01, 0x38, 0xC0, 0xB2, 0x14, 0x28, 0x47, 0xD8, 0x02, 0x20, 0x01, 0x2A, +0x47, 0xD1, 0x3C, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x36, 0xD1, 0x7B, 0x8C, 0x5B, 0x07, 0x33, 0xD5, 0xA3, 0x88, 0x62, 0x88, +0x61, 0x78, 0x20, 0x89, 0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x21, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, +0x00, 0x20, 0x32, 0xE0, 0x2E, 0x28, 0x2F, 0xD1, 0x01, 0x23, 0x4A, 0x46, 0x5A, 0x40, 0x13, 0x00, 0x42, 0x46, 0x5A, 0x40, +0x13, 0x00, 0x39, 0x22, 0xBA, 0x5C, 0xDB, 0xB2, 0x9A, 0x42, 0x0D, 0xD1, 0xA3, 0x88, 0x62, 0x88, 0x61, 0x78, 0x20, 0x89, +0x01, 0x90, 0xE0, 0x88, 0x00, 0x90, 0x13, 0x4C, 0x94, 0x20, 0x24, 0x58, 0x28, 0x00, 0xA0, 0x47, 0x00, 0x20, 0x16, 0xE0, +0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x23, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0xA9, 0xFE, 0x00, 0x20, 0x0C, 0xE0, +0x22, 0x78, 0x01, 0x23, 0x13, 0x40, 0xF0, 0xB2, 0x24, 0x22, 0x17, 0x21, 0x9E, 0xF7, 0x9F, 0xFE, 0x00, 0x20, 0x02, 0xE0, +0x00, 0x20, 0x00, 0xE0, 0x02, 0x20, 0x03, 0xB0, 0x0C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xF0, 0xBD, 0x64, 0xA2, 0x16, 0x00, +0xC0, 0xA0, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x22, 0x4B, +0xD6, 0x58, 0x77, 0xF7, 0x19, 0xFD, 0x00, 0x28, 0x3B, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x37, 0xD9, 0x22, 0x78, +0x01, 0x23, 0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x36, 0x23, 0xF3, 0x5C, 0x01, 0x2B, 0x27, 0xD1, 0x23, 0x7A, 0x1B, 0x3A, +0x01, 0x2B, 0x24, 0xD8, 0x27, 0x00, 0x09, 0x37, 0x38, 0x00, 0x79, 0xF7, 0x93, 0xFA, 0x01, 0x00, 0x13, 0x28, 0x16, 0xD9, +0x8B, 0x23, 0x9B, 0x00, 0xF0, 0x18, 0x0A, 0x22, 0x39, 0x00, 0xCE, 0xF7, 0x19, 0xF8, 0x22, 0x7A, 0x53, 0x1E, 0x9A, 0x41, +0xD2, 0xB2, 0xE8, 0xB2, 0x3B, 0x00, 0x61, 0x68, 0xA9, 0xF7, 0x2E, 0xF8, 0x23, 0x7A, 0x5A, 0x1E, 0x93, 0x41, 0x91, 0x22, +0x92, 0x00, 0xB3, 0x54, 0x0B, 0xE0, 0x08, 0x48, 0x79, 0xF7, 0x12, 0xFA, 0x1E, 0x22, 0x00, 0xE0, 0x24, 0x22, 0x39, 0x23, +0xF3, 0x5C, 0xE8, 0xB2, 0x3C, 0x21, 0x9E, 0xF7, 0x48, 0xFE, 0x00, 0x20, 0xF8, 0xBD, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, +0xD8, 0xD4, 0x10, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x04, 0x00, 0x08, 0x00, 0x0D, 0x0A, 0xAA, 0x00, 0x2B, 0x4B, 0xD6, 0x58, +0x77, 0xF7, 0xCA, 0xFC, 0x00, 0x28, 0x20, 0xD0, 0x16, 0x38, 0xC0, 0xB2, 0x03, 0x28, 0x1C, 0xD9, 0x22, 0x78, 0x01, 0x23, +0x13, 0x40, 0x39, 0x22, 0xB3, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x2B, 0x16, 0xD0, 0xA3, 0x78, 0x01, 0x2B, 0x31, 0xD0, +0x02, 0x2B, 0x39, 0xD0, 0x00, 0x20, 0x00, 0x2B, 0x22, 0xD0, 0x01, 0xA9, 0x39, 0x23, 0xF2, 0x5C, 0x3B, 0x3B, 0x13, 0x43, +0x0B, 0x70, 0x20, 0x23, 0x4B, 0x70, 0x88, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xC1, 0xFD, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, +0x85, 0xF7, 0xF8, 0xFC, 0x00, 0x28, 0x03, 0xD0, 0x4F, 0x23, 0x01, 0x22, 0xF2, 0x54, 0xE0, 0xE7, 0x4F, 0x23, 0xF3, 0x5C, +0x00, 0x2B, 0xDC, 0xD1, 0x39, 0x23, 0xF3, 0x5C, 0xE8, 0xB2, 0x1A, 0x22, 0x1F, 0x21, 0x9E, 0xF7, 0x0D, 0xFE, 0xE8, 0xE7, +0xE8, 0xB2, 0xF5, 0xF7, 0x59, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x2A, 0x20, 0x18, 0x40, 0x15, 0x30, 0xD2, 0xE7, +0xE8, 0xB2, 0xF5, 0xF7, 0x79, 0xF9, 0x43, 0x1E, 0x98, 0x41, 0x43, 0x42, 0x15, 0x20, 0x18, 0x40, 0x15, 0x30, 0xC8, 0xE7, +0xE8, 0xB2, 0x03, 0x4B, 0x1B, 0x69, 0x98, 0x47, 0x2A, 0x20, 0xC2, 0xE7, 0x64, 0xA2, 0x16, 0x00, 0x60, 0x92, 0x16, 0x00, +0x70, 0xB5, 0x14, 0x00, 0x13, 0x0A, 0x9B, 0x00, 0x11, 0x4A, 0x9D, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x69, 0xFC, 0x03, 0x00, +0x01, 0x28, 0x0A, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x06, 0xD9, 0x16, 0x3B, 0xDB, 0xB2, 0x03, 0x30, 0x98, 0x42, 0x80, 0x41, +0x40, 0x42, 0x40, 0x00, 0x70, 0xBD, 0x36, 0x23, 0xEB, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF9, 0xD1, 0x91, 0x23, 0x9B, 0x00, +0xEB, 0x5C, 0x00, 0x2B, 0xF4, 0xD0, 0x00, 0x21, 0x20, 0x00, 0x8E, 0xF7, 0xDB, 0xFC, 0x00, 0x20, 0xEE, 0xE7, 0xC0, 0x46, +0x64, 0xA2, 0x16, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x00, 0x90, 0x0F, 0x00, 0x16, 0x00, 0x01, 0x93, 0x0B, 0x78, 0xDC, 0x00, +0xE3, 0x18, 0x32, 0x4C, 0xE4, 0x18, 0x3C, 0x34, 0x23, 0x78, 0x01, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x03, 0xB0, 0xF0, 0xBD, +0x4B, 0x78, 0x00, 0x2B, 0x4B, 0xD1, 0x2C, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x4D, 0xD0, 0x2B, 0x4D, 0x2C, 0x00, 0x3F, 0x34, +0x02, 0xE0, 0x09, 0x35, 0xA5, 0x42, 0x43, 0xD0, 0xAB, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x3B, 0x78, 0xD9, 0x00, 0xC9, 0x18, +0x36, 0x31, 0x23, 0x4B, 0x9C, 0x46, 0x61, 0x44, 0x06, 0x22, 0x28, 0x00, 0xCD, 0xF7, 0x18, 0xFF, 0x00, 0x28, 0xEC, 0xD1, +0x0C, 0x23, 0x03, 0x22, 0x00, 0x21, 0x1F, 0x48, 0x77, 0xF7, 0x3C, 0xF8, 0x04, 0x00, 0x0B, 0x23, 0x03, 0x70, 0x3B, 0x78, +0xD9, 0x00, 0xC9, 0x18, 0x36, 0x31, 0x18, 0x4D, 0x49, 0x19, 0x04, 0x30, 0x06, 0x22, 0xCD, 0xF7, 0x27, 0xFF, 0x01, 0x23, +0x5B, 0x42, 0x63, 0x80, 0x02, 0x33, 0xA3, 0x72, 0x00, 0x26, 0xE6, 0x72, 0x20, 0x00, 0xC8, 0xF7, 0x85, 0xFE, 0x3A, 0x78, +0xD3, 0x00, 0x9B, 0x18, 0xEB, 0x18, 0x3E, 0x33, 0x18, 0x78, 0x85, 0xF7, 0x0F, 0xFA, 0x3A, 0x78, 0xD3, 0x00, 0x9B, 0x18, +0xEB, 0x18, 0x3C, 0x33, 0x1E, 0x70, 0x28, 0x68, 0x0C, 0x38, 0x77, 0xF7, 0x62, 0xF8, 0x2E, 0x60, 0xAD, 0xE7, 0x16, 0x2B, +0xAB, 0xD0, 0x02, 0xE0, 0x7B, 0x78, 0x16, 0x2B, 0xA7, 0xD0, 0x01, 0x9B, 0x32, 0x00, 0x39, 0x00, 0x00, 0x98, 0x04, 0x4C, +0xA0, 0x47, 0xA0, 0xE7, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0x03, 0x11, 0x00, 0x00, 0xED, 0x33, 0x09, 0x00, +0xF0, 0xB5, 0x87, 0xB0, 0x01, 0x90, 0x0D, 0x00, 0x02, 0x92, 0x03, 0x93, 0x0A, 0x78, 0xD3, 0x00, 0x9A, 0x18, 0x29, 0x4B, +0x9B, 0x18, 0x3C, 0x33, 0x1B, 0x78, 0x02, 0x2B, 0x02, 0xD0, 0x00, 0x20, 0x07, 0xB0, 0xF0, 0xBD, 0x25, 0x4C, 0x27, 0x00, +0x3F, 0x37, 0x4E, 0x1C, 0x02, 0xE0, 0x09, 0x34, 0xBC, 0x42, 0x39, 0xD0, 0xA3, 0x79, 0x02, 0x2B, 0xF9, 0xD9, 0x06, 0x22, +0x31, 0x00, 0x20, 0x00, 0xCD, 0xF7, 0xAE, 0xFE, 0x00, 0x28, 0xF2, 0xD1, 0x1B, 0x4A, 0x29, 0x78, 0xCB, 0x00, 0x5B, 0x18, +0xD3, 0x18, 0x3C, 0x33, 0x00, 0x21, 0x19, 0x70, 0x13, 0x7B, 0x9B, 0x07, 0xDF, 0xD5, 0x18, 0x4B, 0x00, 0x24, 0x1A, 0x78, +0x00, 0x2A, 0x05, 0xD0, 0x01, 0x34, 0xE4, 0xB2, 0x09, 0x33, 0x07, 0x2C, 0xF7, 0xD1, 0xD4, 0xE7, 0x06, 0x2C, 0xD2, 0xD8, +0x0F, 0x4B, 0x1A, 0x8B, 0x04, 0xA9, 0x0A, 0x80, 0x5A, 0x8B, 0x4A, 0x80, 0x5B, 0x7F, 0x0B, 0x71, 0x4C, 0x71, 0x0E, 0x4A, +0xD0, 0x23, 0xD3, 0x58, 0x08, 0x00, 0x98, 0x47, 0x00, 0x28, 0xC2, 0xD1, 0xE3, 0x00, 0x1C, 0x19, 0x06, 0x4B, 0x1C, 0x19, +0x3C, 0x34, 0x02, 0x22, 0x22, 0x70, 0xBA, 0xE7, 0x03, 0x9B, 0x02, 0x9A, 0x29, 0x00, 0x01, 0x98, 0x05, 0x4C, 0xA0, 0x47, +0xB3, 0xE7, 0xC0, 0x46, 0x68, 0x9E, 0x16, 0x00, 0x9E, 0x9E, 0x16, 0x00, 0xA4, 0x9E, 0x16, 0x00, 0x28, 0x19, 0x16, 0x00, +0xDD, 0x32, 0x09, 0x00, 0x00, 0x09, 0x70, 0x47, 0x00, 0x28, 0x14, 0xD0, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x03, 0xD0, +0x0D, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x06, 0xD1, 0x0C, 0x4B, 0x0A, 0x4A, 0x99, 0x68, 0x11, 0x60, 0xDA, 0x68, 0x09, 0x4B, +0x1A, 0x60, 0x09, 0x4B, 0x09, 0x4A, 0x9A, 0x60, 0x09, 0x4A, 0xDA, 0x60, 0x70, 0x47, 0x06, 0x4B, 0x03, 0x4A, 0x12, 0x68, +0x9A, 0x60, 0x03, 0x4A, 0x12, 0x68, 0xDA, 0x60, 0xF6, 0xE7, 0xC0, 0x46, 0xB8, 0xE6, 0x10, 0x00, 0xD4, 0xE6, 0x10, 0x00, +0x60, 0x92, 0x16, 0x00, 0x2D, 0x01, 0x10, 0x00, 0x81, 0x01, 0x10, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x01, 0x00, 0x2F, 0x48, +0x79, 0xF7, 0x68, 0xF8, 0x7D, 0xF7, 0xE8, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0xFF, 0xF7, 0xC9, 0xFF, 0x2B, 0x4A, +0x95, 0x23, 0x9B, 0x00, 0xD2, 0x5C, 0x2A, 0x4B, 0x1A, 0x70, 0x2A, 0x4B, 0x1A, 0x68, 0x2A, 0x4B, 0x1A, 0x60, 0xE6, 0x23, +0x5B, 0x00, 0x1B, 0x68, 0x28, 0x48, 0x98, 0x47, 0x28, 0x4B, 0x18, 0x60, 0x01, 0x2C, 0x27, 0xD0, 0x02, 0x23, 0x22, 0x00, +0x9A, 0x43, 0x05, 0xD0, 0x25, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1C, 0x4E, 0x95, 0x25, +0xAD, 0x00, 0x40, 0x23, 0x73, 0x55, 0x1C, 0x4B, 0x20, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, +0x49, 0x00, 0x1A, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x1C, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x1B, 0xD9, 0x02, 0x2C, +0xC8, 0xD1, 0x1A, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xC1, 0xE7, 0x0D, 0x4D, 0x95, 0x24, +0xA4, 0x00, 0x30, 0x23, 0x2B, 0x55, 0x0D, 0x4B, 0x11, 0x4A, 0x1A, 0x60, 0x8C, 0x21, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, +0x49, 0x00, 0x0B, 0x48, 0x98, 0x47, 0x2B, 0x5D, 0x0D, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, +0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xA7, 0xE7, 0xE4, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, +0x54, 0x07, 0x62, 0x40, 0x08, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x18, 0xE7, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, +0xFD, 0x20, 0x22, 0x21, 0x60, 0x92, 0x16, 0x00, 0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x70, 0xB5, 0x04, 0x00, +0x01, 0x00, 0x1A, 0x48, 0x78, 0xF7, 0xEE, 0xFF, 0x7D, 0xF7, 0x6E, 0xFF, 0x01, 0x28, 0x00, 0xD0, 0x70, 0xBD, 0x00, 0x20, +0xFF, 0xF7, 0x4E, 0xFF, 0x15, 0x4E, 0x95, 0x25, 0xAD, 0x00, 0x15, 0x4B, 0x1B, 0x78, 0x73, 0x55, 0x14, 0x4B, 0x1A, 0x68, +0x14, 0x4B, 0x1A, 0x60, 0x14, 0x4B, 0x1B, 0x68, 0x80, 0x21, 0x49, 0x00, 0x19, 0x43, 0xE8, 0x23, 0x5B, 0x00, 0x1B, 0x68, +0x11, 0x48, 0x98, 0x47, 0x73, 0x5D, 0x11, 0x49, 0x2D, 0x22, 0x8B, 0x54, 0x01, 0x2C, 0x08, 0xD9, 0x02, 0x2C, 0xDF, 0xD1, +0x0E, 0x49, 0x0A, 0x88, 0xFF, 0x20, 0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD8, 0xE7, 0x0C, 0x49, 0x0A, 0x88, 0xFF, 0x20, +0x82, 0x43, 0x13, 0x43, 0x0B, 0x80, 0xD1, 0xE7, 0xF8, 0xD4, 0x10, 0x00, 0x7C, 0x1E, 0x16, 0x00, 0xF6, 0xE8, 0x10, 0x00, +0x08, 0xE7, 0x10, 0x00, 0x54, 0x07, 0x62, 0x40, 0x18, 0xE7, 0x10, 0x00, 0x58, 0x00, 0x01, 0x50, 0x60, 0x92, 0x16, 0x00, +0x8E, 0x01, 0x61, 0x40, 0x0C, 0x65, 0x61, 0x40, 0x10, 0xB5, 0x09, 0x28, 0x0B, 0xD9, 0xFF, 0x28, 0x0B, 0xD1, 0x0B, 0x09, +0x1F, 0x29, 0x0D, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0x05, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0xA6, 0xFF, 0x01, 0xE0, 0x00, 0x28, +0x08, 0xD1, 0x10, 0xBD, 0x00, 0x20, 0xFF, 0xF7, 0x25, 0xFF, 0xFA, 0xE7, 0x00, 0x20, 0xFF, 0xF7, 0x9B, 0xFF, 0xF6, 0xE7, +0x0B, 0x09, 0x1F, 0x29, 0xF4, 0xD9, 0x02, 0x3B, 0x01, 0x2B, 0xF0, 0xD8, 0x01, 0x20, 0xFF, 0xF7, 0x17, 0xFF, 0xEC, 0xE7, +0xF8, 0xB5, 0xCE, 0x46, 0x47, 0x46, 0x80, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0x1F, 0x00, 0x13, 0x0A, 0x9B, 0x00, +0x11, 0x4A, 0x9B, 0x58, 0x99, 0x46, 0x0A, 0x88, 0x10, 0x4B, 0xD3, 0x5C, 0x98, 0x46, 0x20, 0x00, 0x77, 0xF7, 0x42, 0xFA, +0x0A, 0x28, 0x0A, 0xD0, 0x3B, 0x00, 0x22, 0x00, 0x29, 0x00, 0x30, 0x00, 0x0B, 0x4C, 0xA0, 0x47, 0x00, 0x20, 0x0C, 0xBC, +0x90, 0x46, 0x99, 0x46, 0xF8, 0xBD, 0x43, 0x46, 0x5B, 0x08, 0x03, 0x2B, 0xF0, 0xD1, 0x07, 0x4B, 0x4A, 0x46, 0xD1, 0x5C, +0x06, 0x3B, 0xD0, 0x5C, 0xFF, 0xF7, 0xB0, 0xFF, 0xE8, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, +0x05, 0x87, 0x0A, 0x00, 0x2A, 0x02, 0x00, 0x00, 0x70, 0xB5, 0x82, 0xB0, 0x14, 0x00, 0x15, 0x0A, 0xAA, 0x00, 0x20, 0x4B, +0xD6, 0x58, 0x20, 0x00, 0x77, 0xF7, 0x16, 0xFA, 0x03, 0x00, 0x01, 0x28, 0x10, 0xD0, 0x00, 0x20, 0x01, 0x2B, 0x05, 0xD9, +0x19, 0x2B, 0x05, 0xD8, 0x15, 0x22, 0x9A, 0x42, 0x40, 0x41, 0x40, 0x00, 0x02, 0xB0, 0x70, 0xBD, 0x58, 0x3B, 0x18, 0x00, +0x43, 0x1E, 0x98, 0x41, 0x40, 0x00, 0xF7, 0xE7, 0x4C, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, 0xF2, 0xD1, 0x4B, 0x33, +0xF3, 0x5C, 0x00, 0x2B, 0x02, 0xD0, 0x4B, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x4F, 0x23, 0xF3, 0x5C, 0x00, 0x20, 0x00, 0x2B, +0xE6, 0xD0, 0x01, 0xA9, 0x36, 0x23, 0xF2, 0x5C, 0x38, 0x3B, 0x13, 0x43, 0x0B, 0x70, 0x1F, 0x23, 0x4B, 0x70, 0x1D, 0x3B, +0x8B, 0x70, 0xE8, 0xB2, 0x9E, 0xF7, 0xFE, 0xFA, 0x20, 0x00, 0x8E, 0xF7, 0xF1, 0xFE, 0x58, 0x21, 0x20, 0x00, 0x77, 0xF7, +0x7D, 0xF9, 0x00, 0x20, 0xD0, 0xE7, 0xC0, 0x46, 0x64, 0xA2, 0x16, 0x00, 0x05, 0x4B, 0x00, 0x20, 0x1A, 0x78, 0x00, 0x2A, +0x04, 0xD0, 0x01, 0x30, 0xC0, 0xB2, 0x09, 0x33, 0x07, 0x28, 0xF7, 0xD1, 0x70, 0x47, 0xC0, 0x46, 0xA4, 0x9E, 0x16, 0x00, +0x70, 0xB5, 0x80, 0x00, 0x28, 0x4B, 0xC2, 0x58, 0x28, 0x49, 0xD5, 0x23, 0x5B, 0x00, 0xC9, 0x5C, 0xCB, 0x00, 0x5B, 0x1A, +0x5B, 0x00, 0x26, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0xC9, 0x0B, 0x0B, 0xD0, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, +0x19, 0x80, 0x20, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x0B, 0x40, 0x23, 0x54, 0x9E, 0x23, +0xD3, 0x5C, 0x5B, 0x00, 0xAE, 0x21, 0x51, 0x5C, 0x5B, 0x18, 0xDB, 0xB2, 0x99, 0x00, 0xCB, 0x18, 0x5B, 0x00, 0x19, 0x49, +0x5C, 0x18, 0x21, 0x88, 0x89, 0xB2, 0x00, 0x29, 0x19, 0xD1, 0x9C, 0x31, 0x50, 0x5C, 0x00, 0x28, 0x01, 0xD1, 0x01, 0x31, +0x50, 0x5C, 0x14, 0x49, 0x5D, 0x18, 0x29, 0x88, 0x78, 0x26, 0xB1, 0x43, 0xC0, 0x00, 0x01, 0x43, 0x29, 0x80, 0x96, 0x21, +0x51, 0x5A, 0xC9, 0x00, 0x06, 0x20, 0x01, 0x43, 0x89, 0xB2, 0x0E, 0x48, 0x18, 0x18, 0x01, 0x80, 0x94, 0x21, 0x51, 0x5A, +0x21, 0x80, 0x0C, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0xAE, 0x21, 0x53, 0x5C, +0x58, 0x42, 0x43, 0x41, 0x53, 0x54, 0x70, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, +0xCE, 0x69, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0x70, 0xB5, 0x35, 0x4B, +0x1C, 0x68, 0x00, 0x2C, 0x14, 0xD0, 0xE3, 0x78, 0x9B, 0x00, 0x33, 0x4A, 0x9D, 0x58, 0xA0, 0x23, 0xEB, 0x5C, 0x02, 0x2B, +0x0E, 0xD0, 0x31, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x05, 0xD0, 0x30, 0x4A, 0x11, 0x68, 0x80, 0x23, 0xDB, 0x03, 0x0B, 0x43, +0x13, 0x60, 0xA0, 0x23, 0x02, 0x22, 0xEA, 0x54, 0x00, 0x20, 0x70, 0xBD, 0x94, 0x23, 0xE8, 0x5A, 0x00, 0x28, 0x07, 0xD0, +0x63, 0x78, 0x00, 0x2B, 0x42, 0xD0, 0x01, 0x2B, 0x43, 0xD0, 0x94, 0x23, 0x00, 0x22, 0xEA, 0x52, 0xE2, 0x78, 0x62, 0x23, +0x53, 0x43, 0x24, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x40, 0x05, 0x40, 0x0F, 0x84, 0xF7, 0x51, 0xFF, 0x1D, 0x4D, +0xE3, 0x78, 0x9B, 0x00, 0x58, 0x59, 0x76, 0xF7, 0xCF, 0xFE, 0xE3, 0x78, 0x9B, 0x00, 0x00, 0x24, 0x5C, 0x51, 0x1C, 0x48, +0xCB, 0xF7, 0x56, 0xFD, 0x1B, 0x48, 0x78, 0xF7, 0x53, 0xFE, 0x14, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x76, 0xF7, 0xC0, 0xFE, +0x2B, 0x68, 0xDC, 0x60, 0x98, 0x68, 0x00, 0x28, 0x05, 0xD0, 0x76, 0xF7, 0xB9, 0xFE, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x22, +0x9A, 0x60, 0x0C, 0x4C, 0x20, 0x68, 0x76, 0xF7, 0xB1, 0xFE, 0x00, 0x23, 0x23, 0x60, 0x0B, 0x4B, 0x1B, 0x78, 0x00, 0x2B, +0xBC, 0xD0, 0x0E, 0x4A, 0x13, 0x68, 0x0E, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x06, 0x4B, 0x00, 0x22, 0x1A, 0x70, 0xB3, 0xE7, +0x80, 0xF7, 0x4A, 0xFE, 0xBB, 0xE7, 0x80, 0xF7, 0xFD, 0xFD, 0xB8, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, +0xDC, 0xE5, 0x10, 0x00, 0x00, 0x04, 0x60, 0x40, 0xFE, 0x64, 0x61, 0x40, 0xFC, 0xE6, 0x10, 0x00, 0x0C, 0xD5, 0x10, 0x00, +0xD0, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, 0x70, 0xB5, 0x13, 0x4B, 0x1C, 0x68, 0xA5, 0x78, 0x00, 0x2D, 0x1D, 0xD1, +0x23, 0x78, 0x03, 0x2B, 0x1C, 0xD0, 0x63, 0x78, 0x00, 0x2B, 0x08, 0xD0, 0x01, 0x2B, 0x0F, 0xD0, 0x0D, 0x4B, 0x9B, 0x6E, +0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x04, 0xE0, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xF2, 0xFB, +0x01, 0x23, 0xA3, 0x70, 0x28, 0x00, 0x70, 0xBD, 0x0E, 0x22, 0x01, 0x00, 0xE0, 0x68, 0xCD, 0xF7, 0xE9, 0xFB, 0xF5, 0xE7, +0x0C, 0x25, 0xF5, 0xE7, 0x0C, 0x25, 0xF3, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xDE, 0x46, +0x57, 0x46, 0x4E, 0x46, 0x45, 0x46, 0xE0, 0xB5, 0x8B, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x14, 0x00, 0x01, 0x93, 0x00, 0x23, +0x08, 0x93, 0x09, 0x93, 0x06, 0x93, 0x06, 0xAA, 0x93, 0x80, 0x82, 0x00, 0xBB, 0x4B, 0xD3, 0x58, 0x00, 0x2B, 0x00, 0xD1, +0x10, 0xE1, 0xAB, 0x00, 0xB8, 0x4A, 0x9F, 0x58, 0x21, 0x00, 0xB8, 0x48, 0x78, 0xF7, 0xCE, 0xFD, 0x00, 0x2C, 0x00, 0xD1, +0x0D, 0xE1, 0x01, 0x2C, 0x00, 0xD1, 0x6D, 0xE2, 0xB4, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x00, 0x23, 0x00, 0x93, 0x98, 0x46, 0x99, 0x46, 0x02, 0x93, 0x00, 0x21, 0x00, 0x26, 0x01, 0x9B, 0x00, 0x2B, 0x63, 0xD0, +0x62, 0x23, 0x6B, 0x43, 0xAC, 0x4A, 0x98, 0x18, 0x02, 0x88, 0x1F, 0x24, 0xA2, 0x43, 0x32, 0x43, 0x02, 0x80, 0xAA, 0x4A, +0x9A, 0x18, 0x10, 0x88, 0xA9, 0x4E, 0x06, 0x40, 0x80, 0x20, 0x40, 0x00, 0x30, 0x43, 0x10, 0x80, 0x10, 0x88, 0x40, 0x04, +0x40, 0x0C, 0x10, 0x80, 0x10, 0x88, 0xA5, 0x4E, 0x30, 0x40, 0x10, 0x80, 0xA4, 0x4A, 0x94, 0x46, 0x9C, 0x44, 0x62, 0x46, +0x16, 0x88, 0xFF, 0x20, 0x86, 0x43, 0xA2, 0x4A, 0x93, 0x46, 0x2D, 0x22, 0x5C, 0x46, 0xA2, 0x5C, 0x32, 0x43, 0x64, 0x46, +0x22, 0x80, 0x9F, 0x4A, 0x9E, 0x18, 0x00, 0x22, 0x94, 0x46, 0x32, 0x80, 0x9D, 0x4A, 0x93, 0x46, 0x9B, 0x44, 0x5A, 0x46, +0x12, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x5C, 0x46, 0x22, 0x80, 0x9A, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x99, 0x4A, 0x9A, 0x18, +0x61, 0x46, 0x11, 0x80, 0x98, 0x4A, 0x9A, 0x18, 0x11, 0x80, 0x98, 0x4A, 0x99, 0x18, 0x02, 0x22, 0xFF, 0x32, 0x0A, 0x80, +0x32, 0x88, 0x40, 0x24, 0xA2, 0x43, 0x22, 0x43, 0x32, 0x80, 0x0A, 0x88, 0x82, 0x43, 0xFE, 0x38, 0x02, 0x43, 0x0A, 0x80, +0x9E, 0x22, 0xBA, 0x5C, 0x14, 0x21, 0x4A, 0x43, 0x8F, 0x49, 0x8C, 0x46, 0x62, 0x44, 0x92, 0xB2, 0x8E, 0x49, 0x59, 0x18, +0x0A, 0x80, 0x8E, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x3F, 0x21, 0x0A, 0x40, 0x8C, 0x49, 0x0A, 0x43, 0x1A, 0x80, +0x08, 0xAE, 0x31, 0x00, 0x06, 0xA8, 0xAF, 0xF7, 0x9D, 0xF9, 0x06, 0xAB, 0x5A, 0x78, 0x12, 0x02, 0x1B, 0x78, 0x13, 0x43, +0x62, 0x27, 0x6F, 0x43, 0x85, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0xDA, 0x78, 0x12, 0x02, 0x9B, 0x78, 0x13, 0x43, +0x82, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x06, 0xAB, 0x5A, 0x79, 0x12, 0x02, 0x1B, 0x79, 0x13, 0x43, 0x7F, 0x4A, 0xBA, 0x18, +0x13, 0x80, 0x72, 0x78, 0x12, 0x02, 0x33, 0x78, 0x13, 0x43, 0x7D, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0xF2, 0x78, 0x12, 0x02, +0xB3, 0x78, 0x13, 0x43, 0x7A, 0x4A, 0xBA, 0x18, 0x13, 0x80, 0x00, 0x22, 0x06, 0x2D, 0x01, 0xD8, 0x6A, 0x1C, 0xD2, 0xB2, +0x08, 0xAB, 0x19, 0x79, 0x03, 0x23, 0x0B, 0x40, 0x92, 0x00, 0x13, 0x43, 0x6E, 0x4A, 0x13, 0x43, 0x6C, 0x4A, 0xBA, 0x18, +0x13, 0x80, 0x72, 0x48, 0x03, 0x68, 0x72, 0x49, 0x0B, 0x40, 0x80, 0x22, 0x52, 0x01, 0x1A, 0x43, 0x02, 0x60, 0x5A, 0x4B, +0xFE, 0x18, 0x33, 0x88, 0x02, 0x9A, 0x14, 0x03, 0x24, 0xB2, 0x0B, 0x40, 0x23, 0x43, 0x9B, 0xB2, 0x33, 0x80, 0x4B, 0x46, +0x00, 0x2B, 0x00, 0xD1, 0xDE, 0xE1, 0x56, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x80, 0x21, 0x09, 0x02, +0x0B, 0x43, 0x13, 0x80, 0x33, 0x88, 0x64, 0x4A, 0x13, 0x40, 0x00, 0x9A, 0xD2, 0x02, 0x13, 0x43, 0x9B, 0xB2, 0x33, 0x80, +0x61, 0x49, 0x0B, 0x68, 0x61, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, 0x4C, 0x4B, 0xFB, 0x18, +0x00, 0x22, 0x1A, 0x80, 0x49, 0x4B, 0xFB, 0x18, 0x1A, 0x88, 0x08, 0x21, 0x8A, 0x43, 0x1A, 0x80, 0x30, 0x88, 0x31, 0x88, +0x33, 0x88, 0x80, 0x0B, 0x01, 0x22, 0x10, 0x40, 0x80, 0x03, 0xC9, 0x0A, 0x0A, 0x40, 0xD2, 0x02, 0x10, 0x43, 0x05, 0x43, +0x58, 0x05, 0x40, 0x0F, 0x00, 0x02, 0x05, 0x43, 0x25, 0x43, 0xAD, 0xB2, 0x35, 0x80, 0x0B, 0xB0, 0x3C, 0xBC, 0x90, 0x46, +0x99, 0x46, 0xA2, 0x46, 0xAB, 0x46, 0xF0, 0xBD, 0x32, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0xE7, 0xE6, 0xB3, 0x78, 0x99, 0x46, 0xF3, 0x78, 0x98, 0x46, 0x33, 0x79, 0x00, 0x93, 0x72, 0x79, 0x02, 0x92, 0x00, 0x2B, +0x10, 0xD1, 0x9D, 0x23, 0x00, 0x22, 0xFA, 0x54, 0x32, 0x78, 0x01, 0x3B, 0xFA, 0x54, 0xF2, 0x88, 0x96, 0x23, 0xFA, 0x52, +0x73, 0x78, 0x07, 0x2B, 0x00, 0xD9, 0x3D, 0xE1, 0x9B, 0x00, 0x3E, 0x49, 0xCB, 0x58, 0x9F, 0x46, 0x31, 0x78, 0x9D, 0x23, +0xF9, 0x54, 0x3C, 0x48, 0x78, 0xF7, 0x9C, 0xFC, 0x9C, 0x23, 0x00, 0x22, 0xFA, 0x54, 0xEA, 0xE7, 0x39, 0x4B, 0x1A, 0x68, +0x39, 0x49, 0x0A, 0x40, 0x1A, 0x60, 0x1A, 0x68, 0x30, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, +0x35, 0x4B, 0x1B, 0x78, 0x00, 0x2B, 0x76, 0xD0, 0x31, 0x49, 0x0B, 0x68, 0x2D, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, +0x13, 0x43, 0x0B, 0x60, 0x6D, 0xE0, 0x2D, 0x4B, 0x1A, 0x68, 0x2D, 0x49, 0x11, 0x40, 0x80, 0x22, 0x92, 0x01, 0x0A, 0x43, +0x1A, 0x60, 0x1A, 0x68, 0x22, 0x49, 0x11, 0x40, 0x80, 0x22, 0x52, 0x01, 0x0A, 0x43, 0x1A, 0x60, 0x27, 0x4B, 0x1B, 0x78, +0x00, 0x2B, 0x5A, 0xD0, 0x23, 0x49, 0x0B, 0x68, 0x1F, 0x4A, 0x1A, 0x40, 0x80, 0x23, 0x1B, 0x02, 0x13, 0x43, 0x0B, 0x60, +0x51, 0xE0, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x18, 0xD5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xF8, 0x64, 0x61, 0x40, +0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0x0C, 0x65, 0x61, 0x40, 0x60, 0x92, 0x16, 0x00, +0x0E, 0x65, 0x61, 0x40, 0x56, 0x65, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, +0x1E, 0x65, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x12, 0x65, 0x61, 0x40, 0x0A, 0x65, 0x61, 0x40, 0x40, 0xFF, 0x00, 0x00, +0x00, 0x65, 0x61, 0x40, 0x02, 0x65, 0x61, 0x40, 0x04, 0x65, 0x61, 0x40, 0x06, 0x65, 0x61, 0x40, 0x08, 0x65, 0x61, 0x40, +0x00, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x28, 0x04, 0x60, 0x40, 0xFF, 0x7F, 0xFF, 0xFF, +0x48, 0xD5, 0x10, 0x00, 0x30, 0xD5, 0x10, 0x00, 0xD0, 0x04, 0x60, 0x40, 0xFF, 0xDF, 0xFF, 0xFF, 0xDC, 0xE5, 0x10, 0x00, +0x94, 0x23, 0xF8, 0x5A, 0x8E, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xF0, 0x21, 0x74, 0xF7, 0x96, 0xFB, 0x8C, 0x4A, 0x13, 0x68, +0x8C, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x9E, 0x23, 0xFA, 0x5C, 0x52, 0x00, 0x10, 0x33, 0xFB, 0x5C, 0xD2, 0x18, 0xD2, 0xB2, +0x62, 0x23, 0x6B, 0x43, 0x87, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x03, 0x93, 0x02, 0x20, 0x07, 0x23, 0x9A, 0x46, 0x04, 0x95, +0x05, 0x96, 0x91, 0x00, 0x89, 0x18, 0x49, 0x00, 0x82, 0x4B, 0xCC, 0x18, 0x23, 0x88, 0x78, 0x25, 0xAB, 0x43, 0x70, 0x3D, +0x2B, 0x43, 0x9B, 0xB2, 0x23, 0x80, 0x03, 0x9B, 0x1B, 0x88, 0x25, 0x88, 0xAB, 0x46, 0x1B, 0x0A, 0x55, 0x46, 0x2B, 0x40, +0x5D, 0x46, 0x56, 0x46, 0xB5, 0x43, 0x2B, 0x43, 0x23, 0x80, 0x79, 0x4B, 0x9C, 0x46, 0x8C, 0x44, 0x63, 0x46, 0x1B, 0x88, +0x77, 0x4C, 0x23, 0x40, 0x64, 0x46, 0x23, 0x80, 0x76, 0x4B, 0xCB, 0x18, 0x00, 0x24, 0x1C, 0x80, 0x75, 0x4B, 0x9C, 0x46, +0x61, 0x44, 0x9E, 0x23, 0xFB, 0x5C, 0x5B, 0x00, 0x01, 0x34, 0x54, 0x40, 0xE4, 0xB2, 0xA4, 0x46, 0x63, 0x44, 0x9C, 0x00, +0xA4, 0x46, 0x63, 0x44, 0x5B, 0x00, 0x6F, 0x4C, 0xA4, 0x46, 0x63, 0x44, 0x6E, 0x4C, 0x23, 0x43, 0x9B, 0xB2, 0x0B, 0x80, +0x0B, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x0B, 0x80, 0x53, 0x42, 0x5A, 0x41, 0xD2, 0xB2, 0x01, 0x38, 0xC0, 0xB2, 0x00, 0x28, +0xB9, 0xD1, 0x04, 0x9D, 0x05, 0x9E, 0x31, 0x00, 0x08, 0x31, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0xA5, 0xF9, 0x00, 0x21, +0x02, 0x26, 0xF2, 0xE5, 0x94, 0x23, 0xF8, 0x5A, 0x56, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0xAA, 0x21, 0x74, 0xF7, 0x26, 0xFB, +0x54, 0x4A, 0x13, 0x68, 0x54, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x8E, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x4F, 0x4B, 0x9C, 0x46, +0x60, 0x44, 0xFF, 0x21, 0x74, 0xF7, 0x18, 0xFB, 0x4D, 0x4A, 0x13, 0x68, 0x4D, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x80, 0xE7, +0x94, 0x23, 0xF8, 0x5A, 0x48, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0x0A, 0xFB, 0x46, 0x4A, 0x13, 0x68, +0x46, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x72, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x41, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x0F, 0x21, +0x74, 0xF7, 0xFC, 0xFA, 0x3F, 0x4A, 0x13, 0x68, 0x3F, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x64, 0xE7, 0x94, 0x23, 0xF8, 0x5A, +0x3A, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x55, 0x21, 0x74, 0xF7, 0xEE, 0xFA, 0x38, 0x4A, 0x13, 0x68, 0x38, 0x49, 0x0B, 0x40, +0x13, 0x60, 0x56, 0xE7, 0x94, 0x23, 0xF8, 0x5A, 0x33, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x00, 0x21, 0x74, 0xF7, 0xE0, 0xFA, +0x31, 0x4A, 0x13, 0x68, 0x31, 0x49, 0x0B, 0x40, 0x13, 0x60, 0x48, 0xE7, 0xB3, 0x78, 0x98, 0x46, 0xF3, 0x78, 0x00, 0x93, +0xB4, 0x79, 0xF1, 0x1D, 0x06, 0x22, 0x06, 0xA8, 0xCD, 0xF7, 0x44, 0xF9, 0x00, 0x22, 0x33, 0x4B, 0x99, 0x46, 0xD5, 0x23, +0x5B, 0x00, 0x9C, 0x46, 0x03, 0x26, 0x17, 0x3B, 0xFF, 0x3B, 0x9B, 0x46, 0x0A, 0xE0, 0x2F, 0x49, 0x8A, 0x46, 0x53, 0x44, +0x19, 0x88, 0x49, 0x04, 0x49, 0x0C, 0x19, 0x80, 0x01, 0x32, 0xD2, 0xB2, 0x04, 0x2A, 0x11, 0xD0, 0x4B, 0x46, 0x61, 0x46, +0x5B, 0x5C, 0xD3, 0x18, 0x33, 0x40, 0xD9, 0x00, 0xCB, 0x1A, 0x5B, 0x00, 0x26, 0x49, 0x58, 0x18, 0x01, 0x88, 0x89, 0xB2, +0x00, 0x29, 0xE6, 0xD1, 0x59, 0x46, 0x79, 0x5A, 0x01, 0x80, 0xE2, 0xE7, 0x02, 0x94, 0x00, 0x23, 0x99, 0x46, 0x21, 0x49, +0x03, 0x26, 0x66, 0xE5, 0x20, 0x4B, 0xFA, 0x18, 0x13, 0x88, 0x5B, 0x04, 0x5B, 0x0C, 0x13, 0x80, 0x43, 0x46, 0xDB, 0x07, +0x0F, 0xD4, 0x11, 0x88, 0x43, 0x46, 0x5B, 0x08, 0x1B, 0x02, 0x1B, 0x48, 0x01, 0x40, 0x0B, 0x43, 0x13, 0x80, 0x43, 0x46, +0x5B, 0x08, 0x28, 0x33, 0x19, 0x00, 0x18, 0x48, 0x78, 0xF7, 0x0A, 0xFB, 0x10, 0xE6, 0x10, 0x88, 0x43, 0x46, 0x5B, 0x08, +0x28, 0x33, 0x1B, 0x02, 0x12, 0x49, 0x01, 0x40, 0x0B, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0xEC, 0xE7, 0x00, 0x00, 0x61, 0x40, +0xD0, 0x04, 0x60, 0x40, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0x64, 0x61, 0x40, 0xCA, 0x69, 0x61, 0x40, 0xCC, 0x69, 0x61, 0x40, +0x07, 0xE0, 0xFF, 0xFF, 0xCE, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x61, 0x40, 0xC8, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, +0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, 0x9A, 0x69, 0x61, 0x40, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x65, 0x61, 0x40, +0xFF, 0x80, 0xFF, 0xFF, 0x3C, 0xD5, 0x10, 0x00, 0x10, 0xB5, 0x07, 0x4B, 0x1C, 0x68, 0xA3, 0x78, 0x00, 0x2B, 0x00, 0xD1, +0x10, 0xBD, 0x00, 0x23, 0x0A, 0x00, 0xE1, 0x68, 0xFF, 0xF7, 0xE2, 0xFC, 0x00, 0x23, 0xA3, 0x70, 0xF6, 0xE7, 0xC0, 0x46, +0xD8, 0xE5, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x82, 0x00, 0x52, 0x4B, 0xD4, 0x58, 0x00, 0x2C, +0x00, 0xD1, 0x98, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, 0x4E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x3A, +0x01, 0x2A, 0x01, 0xD8, 0x00, 0x2B, 0x14, 0xD0, 0x9F, 0xF7, 0xD2, 0xFD, 0x06, 0x00, 0x01, 0x00, 0x28, 0x00, 0xFF, 0xF7, +0xA9, 0xFB, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x68, 0xE0, 0x3F, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0x98, 0x47, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0xEF, 0xFD, 0xA0, 0x23, +0x02, 0x22, 0xE2, 0x54, 0xFF, 0xF7, 0xF4, 0xFB, 0x37, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, +0x5B, 0x00, 0x35, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0xE7, 0xD0, 0x33, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, +0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x2C, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, +0xA0, 0x47, 0x2A, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x27, 0x4A, 0x94, 0x46, +0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, +0x23, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x22, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, +0x93, 0x42, 0x05, 0xD0, 0x19, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x18, 0x4E, 0x00, 0x24, +0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x14, 0x4F, 0x03, 0xE0, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0xA8, 0xD0, 0x33, 0x88, +0xDB, 0x0B, 0xF8, 0xD0, 0x10, 0x4B, 0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, +0xEF, 0xE7, 0x01, 0x21, 0x20, 0x00, 0xCA, 0xF7, 0x8F, 0xFD, 0x02, 0x36, 0x66, 0x60, 0x00, 0x21, 0x28, 0x00, 0xFF, 0xF7, +0x4F, 0xFF, 0x20, 0x00, 0xF4, 0xF7, 0xA6, 0xFA, 0x8E, 0xE7, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, +0xA0, 0x47, 0x87, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, +0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0xF0, 0xB5, 0x83, 0xB0, 0x01, 0x90, 0x0D, 0x00, +0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, 0x07, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x0B, 0x4B, 0xDE, 0x6E, 0x00, 0x23, 0x00, 0x22, +0x21, 0x00, 0xB0, 0x47, 0x00, 0x2C, 0x09, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x06, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, +0x21, 0x00, 0xA8, 0x47, 0x03, 0xB0, 0xF0, 0xBD, 0x01, 0x99, 0x38, 0x00, 0xFF, 0xF7, 0x28, 0xFF, 0xF8, 0xE7, 0xC0, 0x46, +0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x96, 0xB0, 0x2F, 0x4B, 0x1B, 0x68, 0xD9, 0x68, 0xEF, 0xF3, +0x10, 0x83, 0xDB, 0x07, 0x51, 0xD4, 0x72, 0xB6, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0xCF, 0xFF, 0x62, 0xB6, +0x0D, 0x9C, 0x00, 0x26, 0x00, 0x2C, 0x07, 0xD0, 0x0E, 0x9B, 0xE3, 0x1A, 0x64, 0x20, 0x58, 0x43, 0x21, 0x00, 0xCC, 0xF7, +0x75, 0xFB, 0x06, 0x00, 0x13, 0x9D, 0x00, 0x20, 0x00, 0x2D, 0x05, 0xD0, 0x21, 0x48, 0x14, 0x9B, 0x58, 0x43, 0x29, 0x00, +0xCC, 0xF7, 0x6A, 0xFB, 0x11, 0x9A, 0x12, 0x9F, 0x15, 0x99, 0x13, 0x00, 0x3B, 0x43, 0x0B, 0x43, 0x1B, 0xD0, 0x0F, 0x9B, +0x98, 0x46, 0x0E, 0x9B, 0x9C, 0x46, 0x00, 0x23, 0x09, 0x93, 0x08, 0x90, 0x07, 0x93, 0x06, 0x96, 0x14, 0x9B, 0x0B, 0x93, +0x05, 0x93, 0x04, 0x95, 0x03, 0x91, 0x02, 0x97, 0x01, 0x92, 0x10, 0x9B, 0x00, 0x93, 0x43, 0x46, 0x22, 0x00, 0x61, 0x46, +0x11, 0x48, 0x78, 0xF7, 0xA5, 0xF9, 0x16, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x0F, 0x9B, 0x0E, 0x99, 0x00, 0x22, +0x06, 0x92, 0x05, 0x90, 0x04, 0x92, 0x03, 0x96, 0x14, 0x9A, 0x0B, 0x92, 0x02, 0x92, 0x01, 0x95, 0x10, 0x9A, 0x00, 0x92, +0x22, 0x00, 0x08, 0x48, 0x78, 0xF7, 0x90, 0xF9, 0xE9, 0xE7, 0x10, 0x31, 0x24, 0x22, 0x0D, 0xA8, 0xCC, 0xF7, 0x7E, 0xFF, +0xAE, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, 0x10, 0x27, 0x00, 0x00, 0x68, 0xD5, 0x10, 0x00, 0xC8, 0xD5, 0x10, 0x00, +0x70, 0x47, 0x00, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x05, 0x00, 0x0F, 0x00, 0x16, 0x00, 0x1C, 0x00, 0x4B, 0x4B, +0x1B, 0x68, 0x00, 0x2B, 0x05, 0xD0, 0x4A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x00, 0x21, +0x10, 0x20, 0x76, 0xF7, 0x37, 0xF9, 0x44, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x10, 0xD0, 0x42, 0x4B, 0x18, 0x68, 0x10, 0x22, +0x00, 0x21, 0x74, 0xF7, 0xDF, 0xF8, 0x00, 0x2D, 0x0E, 0xD0, 0x01, 0x2D, 0x2C, 0xD0, 0x3E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x1B, 0xE0, 0x3A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x98, 0x47, 0xE8, 0xE7, +0x36, 0x4C, 0x25, 0x68, 0x00, 0x21, 0x0E, 0x20, 0x76, 0xF7, 0x16, 0xF9, 0xE8, 0x60, 0x23, 0x68, 0xDB, 0x68, 0x00, 0x2B, +0x0D, 0xD0, 0x31, 0x4C, 0x23, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x00, 0x21, 0x74, 0xF7, 0xBC, 0xF8, 0x23, 0x68, 0x00, 0x22, +0x5A, 0x70, 0xDE, 0x70, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x2B, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, +0x98, 0x47, 0xEA, 0xE7, 0x26, 0x4D, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x38, 0x20, 0x76, 0xF7, 0xF5, 0xF8, 0x43, 0x46, +0xD8, 0x60, 0x2B, 0x68, 0xDB, 0x68, 0x00, 0x2B, 0x31, 0xD0, 0x20, 0x4D, 0x2B, 0x68, 0xD8, 0x68, 0x38, 0x22, 0x00, 0x21, +0x74, 0xF7, 0x9A, 0xF8, 0x2B, 0x68, 0x98, 0x46, 0x00, 0x21, 0x28, 0x20, 0x76, 0xF7, 0xE2, 0xF8, 0x43, 0x46, 0x98, 0x60, +0x2B, 0x68, 0x9B, 0x68, 0x00, 0x2B, 0x25, 0xD0, 0x16, 0x4D, 0x2B, 0x68, 0x98, 0x68, 0x28, 0x22, 0x00, 0x21, 0x74, 0xF7, +0x87, 0xF8, 0x2B, 0x68, 0xD8, 0x68, 0x0E, 0x22, 0x39, 0x00, 0xCC, 0xF7, 0xF5, 0xFE, 0x2B, 0x68, 0x01, 0x22, 0x5A, 0x70, +0xC8, 0x22, 0x52, 0x01, 0x5A, 0x60, 0xDE, 0x70, 0x0E, 0x48, 0x0F, 0x4A, 0x82, 0x60, 0x5B, 0x68, 0xE4, 0x18, 0x24, 0x01, +0x24, 0x09, 0x44, 0x60, 0xCA, 0xF7, 0xA0, 0xFF, 0xB6, 0xE7, 0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, +0x98, 0x47, 0xC6, 0xE7, 0x04, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD2, 0xE7, 0xC0, 0x46, +0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFC, 0xE6, 0x10, 0x00, 0xD5, 0x01, 0x10, 0x00, 0xF8, 0xB5, 0x04, 0x00, +0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0xF7, 0xB8, 0xFA, 0x05, 0x00, 0x28, 0x00, 0xF8, 0xBD, 0x4B, 0x48, +0x78, 0xF7, 0xCA, 0xF8, 0x4A, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x49, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0xEE, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x76, 0xF7, 0x88, 0xF8, 0x42, 0x4B, 0x18, 0x60, +0x00, 0x28, 0x75, 0xD0, 0x9F, 0xF7, 0xE0, 0xFB, 0x07, 0x00, 0x84, 0xF7, 0x81, 0xF9, 0x40, 0x4A, 0x13, 0x88, 0x40, 0x49, +0x0B, 0x40, 0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3A, 0x4B, 0x1E, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x30, 0x00, +0x74, 0xF7, 0x22, 0xF8, 0x00, 0x23, 0x73, 0x62, 0x39, 0x4A, 0xF2, 0x61, 0x39, 0x4A, 0x32, 0x62, 0x03, 0x22, 0x32, 0x76, +0x38, 0x4A, 0x12, 0x78, 0xB2, 0x75, 0x38, 0x4A, 0x32, 0x61, 0x05, 0x22, 0xF2, 0x75, 0x99, 0x32, 0xB3, 0x54, 0x01, 0x32, +0xB3, 0x54, 0x02, 0x32, 0xB3, 0x54, 0x03, 0x32, 0x28, 0x21, 0xB1, 0x52, 0x1C, 0x3A, 0xB3, 0x52, 0x80, 0xF7, 0x72, 0xF8, +0x05, 0x1E, 0x05, 0xD1, 0x28, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x94, 0x23, 0xF5, 0x52, +0x93, 0x3B, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0x8A, 0xFA, 0x28, 0x4A, 0x13, 0x88, 0x1F, 0x21, 0x0B, 0x40, +0x13, 0x80, 0x77, 0x60, 0x00, 0x23, 0x82, 0x22, 0xB3, 0x52, 0xB3, 0x60, 0x00, 0x22, 0xA6, 0x33, 0xF2, 0x54, 0x20, 0x3B, +0xFA, 0x22, 0xD2, 0x01, 0xF2, 0x52, 0x37, 0x67, 0x20, 0x4B, 0xB3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0xFB, 0x18, 0x1B, 0x01, +0x1B, 0x09, 0xF3, 0x60, 0x30, 0x00, 0xCA, 0xF7, 0x15, 0xFA, 0x05, 0x1E, 0x07, 0xD0, 0x12, 0x4B, 0x9B, 0x6E, 0x00, 0x22, +0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x7F, 0xE7, 0xA0, 0x23, 0x00, 0x22, 0xF2, 0x54, 0x01, 0x32, 0x00, 0x21, +0x00, 0x20, 0x9F, 0xF7, 0xF3, 0xF8, 0x3B, 0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0x20, 0xFF, 0xF7, 0xC3, 0xFE, 0x70, 0xE7, +0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x25, 0x68, 0xE7, 0xD8, 0xE5, 0x10, 0x00, +0x10, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, +0xF1, 0x02, 0x10, 0x00, 0xD1, 0x01, 0x10, 0x00, 0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0xF8, 0x64, 0x61, 0x40, +0x00, 0x80, 0xFF, 0xFF, 0x10, 0xB5, 0x00, 0x29, 0x12, 0xD1, 0x03, 0x78, 0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, +0x2F, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x2E, 0xD1, 0xC1, 0x78, 0xE8, 0x39, 0x4B, 0x42, 0x59, 0x41, 0x03, 0x31, 0x04, 0x39, +0x48, 0x42, 0x48, 0x41, 0xC0, 0xB2, 0x10, 0xBD, 0x03, 0x29, 0x0C, 0xD0, 0x12, 0x4B, 0x5C, 0x5C, 0x00, 0x23, 0xD9, 0xB2, +0xC2, 0x5C, 0xA2, 0x42, 0xF1, 0xD1, 0x01, 0x31, 0xC9, 0xB2, 0x01, 0x33, 0x04, 0x2B, 0xF6, 0xD1, 0xEB, 0xE7, 0x03, 0x78, +0xFF, 0x2B, 0x0A, 0xD1, 0x43, 0x78, 0xC1, 0x2B, 0x09, 0xD1, 0x83, 0x78, 0xFB, 0x2B, 0x08, 0xD1, 0xC3, 0x78, 0xE8, 0x2B, +0xDF, 0xD1, 0x04, 0x21, 0xDD, 0xE7, 0x00, 0x21, 0xDB, 0xE7, 0x01, 0x21, 0xD9, 0xE7, 0x02, 0x21, 0xD7, 0xE7, 0x01, 0x21, +0xD5, 0xE7, 0x02, 0x21, 0xD3, 0xE7, 0xC0, 0x46, 0x1C, 0xE0, 0x10, 0x00, 0xF8, 0xB5, 0x23, 0x4B, 0x1B, 0x68, 0x00, 0x2B, +0x3A, 0xD0, 0xDA, 0x68, 0x53, 0x78, 0x00, 0x2B, 0x10, 0xD1, 0x95, 0x88, 0x00, 0x2D, 0x0C, 0xD0, 0x1E, 0x4F, 0x1F, 0x4E, +0xF1, 0x5C, 0xC4, 0x5C, 0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, +0xF4, 0xD3, 0xF8, 0xBD, 0x03, 0x2B, 0x11, 0xD0, 0x18, 0x49, 0xCD, 0x5C, 0x94, 0x88, 0x00, 0x2C, 0xF7, 0xD0, 0x00, 0x23, +0x13, 0x4E, 0xC1, 0x5C, 0x69, 0x40, 0x71, 0x5C, 0xD7, 0x6A, 0xBC, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xA3, 0x42, +0xF5, 0xD3, 0xEA, 0xE7, 0x95, 0x88, 0x00, 0x2D, 0xE7, 0xD0, 0x00, 0x23, 0x0B, 0x4F, 0x0E, 0x4E, 0xF1, 0x5C, 0xC4, 0x5C, +0x61, 0x40, 0x79, 0x5C, 0xD4, 0x6A, 0xA4, 0x46, 0x61, 0x44, 0xD1, 0x62, 0x01, 0x33, 0xAB, 0x42, 0xF4, 0xD3, 0xD8, 0xE7, +0x08, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xD1, 0xE7, 0xC0, 0x46, 0xD8, 0xE5, 0x10, 0x00, +0xBC, 0xDE, 0x10, 0x00, 0xBC, 0xDA, 0x10, 0x00, 0x1C, 0xE0, 0x10, 0x00, 0xBC, 0xD6, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, +0xF0, 0xB5, 0xD6, 0x46, 0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x82, 0xB0, 0x06, 0x00, 0x74, 0x4B, 0x1B, 0x68, 0xDD, 0x68, +0x54, 0x1E, 0xE4, 0xB2, 0x00, 0x2A, 0x00, 0xD1, 0xDA, 0xE0, 0x71, 0x4F, 0xAB, 0xE0, 0x04, 0x21, 0x08, 0x00, 0x10, 0x40, +0x11, 0x42, 0x2F, 0xD0, 0xE9, 0x69, 0x01, 0x31, 0xE9, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, +0x5B, 0xD1, 0xAB, 0x88, 0xDB, 0x00, 0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD5, 0x23, 0x5B, 0x00, 0x65, 0x4A, +0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x63, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, 0x9A, 0x46, +0x00, 0x2B, 0x06, 0xD1, 0x60, 0x4B, 0x9B, 0x6E, 0x01, 0x93, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, +0x00, 0x2B, 0x53, 0xD0, 0x43, 0x46, 0x59, 0x06, 0x09, 0x0F, 0x5B, 0x48, 0x50, 0x44, 0xFF, 0xF7, 0x67, 0xFF, 0x4B, 0xE0, +0x69, 0x69, 0x01, 0x31, 0x69, 0x61, 0xDB, 0x04, 0x9B, 0x0D, 0x99, 0x46, 0xB8, 0x23, 0x13, 0x42, 0x00, 0xD0, 0x95, 0xE0, +0x00, 0x28, 0xCC, 0xD1, 0xAB, 0x88, 0x4B, 0x45, 0x2B, 0xD0, 0x6B, 0x6A, 0x01, 0x33, 0x6B, 0x62, 0x4C, 0x4A, 0xD5, 0x23, +0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x4A, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x18, 0x88, 0x83, 0xB2, +0x98, 0x46, 0x00, 0x2B, 0x05, 0xD1, 0x47, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x4B, 0x46, +0x00, 0x2B, 0x21, 0xD0, 0x69, 0x78, 0x43, 0x48, 0x40, 0x44, 0xFF, 0xF7, 0xF7, 0xFE, 0x00, 0x28, 0x1A, 0xD1, 0x2B, 0x6B, +0x01, 0x33, 0x2B, 0x63, 0x16, 0xE0, 0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x00, 0x28, 0x11, 0xD1, 0xD0, 0xE7, 0xDB, 0x00, +0xAA, 0x6A, 0x94, 0x46, 0x63, 0x44, 0xAB, 0x62, 0xD0, 0xE7, 0x35, 0x23, 0xEB, 0x5C, 0x01, 0x33, 0xDB, 0xB2, 0x64, 0x2B, +0x54, 0xD8, 0x35, 0x22, 0xAB, 0x54, 0x34, 0x23, 0x00, 0x22, 0xEA, 0x54, 0x2F, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, +0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x2D, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0x00, 0x2B, 0x05, 0xD1, +0x2A, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x25, 0x48, 0xD5, 0x21, 0x49, 0x00, 0x42, 0x5C, +0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x26, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, +0x42, 0x5C, 0x01, 0x32, 0x03, 0x23, 0x13, 0x40, 0x43, 0x54, 0x01, 0x3C, 0xE4, 0xB2, 0xFF, 0x2C, 0x2C, 0xD0, 0x30, 0x00, +0x9E, 0xF7, 0x5A, 0xFF, 0x00, 0x28, 0x27, 0xD0, 0xD5, 0x23, 0x5B, 0x00, 0xFA, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, +0x19, 0x4A, 0x9A, 0x18, 0x10, 0x88, 0x82, 0xB2, 0x18, 0x49, 0x59, 0x18, 0x09, 0x88, 0x89, 0xB2, 0x88, 0x46, 0x17, 0x49, +0x8C, 0x46, 0x63, 0x44, 0x1B, 0x88, 0x9B, 0xB2, 0xC1, 0x07, 0xAE, 0xD4, 0x29, 0x69, 0x01, 0x31, 0x29, 0x61, 0x91, 0x07, +0x00, 0xD4, 0x32, 0xE7, 0xAB, 0x69, 0x01, 0x33, 0xAB, 0x61, 0xAF, 0xE7, 0x35, 0x23, 0x64, 0x22, 0xEA, 0x54, 0xA8, 0xE7, +0x2B, 0x6A, 0x01, 0x33, 0x2B, 0x62, 0x67, 0xE7, 0x02, 0xB0, 0x1C, 0xBC, 0x90, 0x46, 0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, +0xD8, 0xE5, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x9A, 0x69, 0x61, 0x40, 0x28, 0x19, 0x16, 0x00, 0x00, 0x00, 0x61, 0x40, +0x90, 0x69, 0x61, 0x40, 0x92, 0x69, 0x61, 0x40, 0x94, 0x69, 0x61, 0x40, 0x96, 0x69, 0x61, 0x40, 0xF0, 0xB5, 0xD6, 0x46, +0x4F, 0x46, 0x46, 0x46, 0xC0, 0xB5, 0x89, 0x46, 0x82, 0x00, 0x41, 0x4B, 0xD5, 0x58, 0xA6, 0x23, 0xEF, 0x5C, 0x2E, 0x6D, +0x44, 0x3B, 0x58, 0x43, 0x3E, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x3E, 0x4A, 0x82, 0x18, 0x14, 0x88, 0x1B, 0x04, 0x1C, 0x43, +0xA2, 0x46, 0x3C, 0x4B, 0xC3, 0x18, 0x1B, 0x88, 0x9B, 0x05, 0x9B, 0x0D, 0x98, 0x46, 0x3A, 0x4B, 0xC3, 0x18, 0x1C, 0x88, +0x39, 0x4B, 0x9C, 0x46, 0x60, 0x44, 0x01, 0x88, 0x24, 0x04, 0x0C, 0x19, 0x37, 0x4B, 0x9E, 0x42, 0x1C, 0xD8, 0x53, 0x46, +0x4A, 0x46, 0x9B, 0x1A, 0x19, 0x01, 0x09, 0x09, 0x80, 0x22, 0x12, 0x05, 0x91, 0x42, 0x40, 0xD9, 0x4B, 0x46, 0x52, 0x46, +0x9B, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x5B, 0x42, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0x3D, 0xD0, 0x00, 0x2B, 0x07, 0xDB, +0x89, 0x08, 0x00, 0x29, 0x04, 0xDD, 0x89, 0x00, 0x49, 0x44, 0x09, 0x01, 0x0B, 0x09, 0x99, 0x46, 0x53, 0x46, 0xE1, 0x1A, +0x49, 0x44, 0x09, 0x01, 0x09, 0x09, 0xF4, 0x23, 0x5B, 0x00, 0x42, 0x46, 0x9B, 0x1A, 0x32, 0xD4, 0xA9, 0x67, 0x82, 0x22, +0xAB, 0x52, 0x4A, 0x42, 0x03, 0x20, 0x10, 0x40, 0xA6, 0x22, 0xA8, 0x54, 0x72, 0x3A, 0x2A, 0x65, 0xAB, 0x60, 0x34, 0x2E, +0x09, 0xD9, 0xEA, 0x7D, 0x00, 0x2A, 0x06, 0xD0, 0xC8, 0x22, 0x52, 0x00, 0x9A, 0x42, 0x92, 0x41, 0x52, 0x42, 0x05, 0x32, +0xEA, 0x75, 0x69, 0x67, 0x84, 0x22, 0xAB, 0x52, 0xC0, 0x1B, 0x43, 0x1E, 0x98, 0x41, 0xC0, 0xB2, 0x1C, 0xBC, 0x90, 0x46, +0x99, 0x46, 0xA2, 0x46, 0xF0, 0xBD, 0x1B, 0x01, 0x1B, 0x09, 0xA1, 0x22, 0xAA, 0x5C, 0x00, 0x2A, 0xC4, 0xD0, 0xC1, 0xE7, +0x00, 0x2B, 0xC1, 0xDA, 0x0D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xC2, 0xE7, 0x0B, 0x4B, +0x9B, 0x1A, 0x01, 0x31, 0x09, 0x01, 0x09, 0x09, 0xC6, 0xE7, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0x4C, 0x65, 0x61, 0x40, +0x4A, 0x65, 0x61, 0x40, 0x4E, 0x65, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0xFA, 0x64, 0x61, 0x40, 0xE1, 0x04, 0x00, 0x00, +0x28, 0x19, 0x16, 0x00, 0x59, 0x04, 0x00, 0x00, 0xF8, 0xB5, 0x80, 0x00, 0x25, 0x4B, 0xC5, 0x58, 0xA6, 0x23, 0xEE, 0x5C, +0x6C, 0x6F, 0xEB, 0x6E, 0xC8, 0x1A, 0x00, 0x01, 0x00, 0x09, 0x22, 0x49, 0x48, 0x43, 0x22, 0x49, 0xCB, 0xF7, 0x84, 0xFF, +0x1A, 0x30, 0x40, 0x00, 0x02, 0x00, 0x34, 0x3A, 0x52, 0x08, 0x84, 0x23, 0xEB, 0x5A, 0x9B, 0x1A, 0x19, 0xB2, 0x1B, 0x04, +0x27, 0xD5, 0x00, 0x23, 0x1B, 0x4A, 0x8A, 0x18, 0x11, 0xB2, 0x01, 0x34, 0x24, 0x01, 0x24, 0x09, 0x1F, 0x00, 0x01, 0x33, +0xDB, 0xB2, 0x12, 0x04, 0xF4, 0xD4, 0xAC, 0x67, 0x82, 0x22, 0xA9, 0x52, 0x64, 0x42, 0x7F, 0x3A, 0x14, 0x40, 0xA3, 0x32, +0xAC, 0x54, 0x28, 0x65, 0xA9, 0x60, 0x00, 0x2B, 0x0A, 0xD0, 0xEB, 0x7D, 0x00, 0x2B, 0x07, 0xD0, 0xC8, 0x23, 0x5B, 0x00, +0x8B, 0x42, 0x9B, 0x41, 0x5B, 0x42, 0x06, 0x37, 0xDF, 0x19, 0xEF, 0x75, 0x34, 0x1B, 0x66, 0x1E, 0xB4, 0x41, 0xE0, 0xB2, +0xF8, 0xBD, 0xAC, 0x67, 0x82, 0x23, 0xE9, 0x52, 0x64, 0x42, 0x7F, 0x3B, 0x1C, 0x40, 0xA3, 0x33, 0xEC, 0x54, 0x28, 0x65, +0xA9, 0x60, 0xEF, 0xE7, 0x38, 0xE6, 0x10, 0x00, 0xA8, 0x61, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x71, 0x02, 0x00, 0x00, +0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x8A, 0xB0, 0x0E, 0x00, 0x8A, 0x00, 0x52, 0x4B, 0xD5, 0x58, 0x00, 0x2D, 0x00, 0xD1, +0x9B, 0xE0, 0xA6, 0x23, 0x98, 0x46, 0xEB, 0x5C, 0x01, 0x33, 0x03, 0x24, 0x23, 0x40, 0x1F, 0x00, 0x9F, 0xF7, 0xB0, 0xF8, +0x00, 0x90, 0x03, 0x00, 0xA3, 0x43, 0x3B, 0x43, 0x42, 0x46, 0xAA, 0x5C, 0xD2, 0x1A, 0x14, 0x40, 0x04, 0x3B, 0xE4, 0x18, +0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x80, 0x22, 0x12, 0x05, 0x93, 0x42, 0x02, 0xD9, 0x03, 0x1B, +0x1B, 0x01, 0x59, 0xD1, 0x00, 0x23, 0x01, 0x93, 0x01, 0xA9, 0x68, 0x46, 0x9F, 0xF7, 0x9C, 0xF8, 0x01, 0x9B, 0x1A, 0x00, +0x0F, 0x32, 0xFF, 0x32, 0x9C, 0x21, 0x89, 0x00, 0x8A, 0x42, 0x57, 0xD8, 0x01, 0x92, 0x00, 0x9A, 0x13, 0x1B, 0x1B, 0x01, +0x1B, 0x09, 0x38, 0x49, 0x8B, 0x42, 0x05, 0xD8, 0xA2, 0x42, 0x61, 0xD1, 0xAB, 0x68, 0x01, 0x9A, 0x93, 0x42, 0x5D, 0xD9, +0x02, 0xA8, 0x34, 0x4B, 0x02, 0x93, 0x44, 0x60, 0xAB, 0x68, 0x83, 0x60, 0x06, 0x76, 0x06, 0x61, 0x31, 0x4B, 0xC3, 0x60, +0xAB, 0x7D, 0x03, 0x75, 0x01, 0x33, 0x43, 0x75, 0x00, 0x23, 0x83, 0x75, 0xB0, 0x22, 0xAA, 0x5C, 0xC2, 0x75, 0x83, 0x76, +0xC3, 0x76, 0x01, 0x33, 0x43, 0x76, 0xCA, 0xF7, 0xD7, 0xFE, 0xA9, 0x22, 0xAB, 0x5C, 0x01, 0x33, 0xAB, 0x54, 0xAA, 0x23, +0xEB, 0x5C, 0x00, 0x2B, 0x31, 0xD1, 0x9F, 0x23, 0xEB, 0x5C, 0x01, 0x2B, 0x3B, 0xD1, 0xAB, 0x6F, 0x9B, 0xB2, 0x62, 0x21, +0x4E, 0x43, 0x22, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0xAB, 0x6F, 0x1B, 0x0C, 0x20, 0x4A, 0xB2, 0x18, 0x13, 0x80, 0x20, 0x4B, +0x9C, 0x46, 0x66, 0x44, 0x2B, 0x6D, 0x01, 0x33, 0x5B, 0x08, 0x01, 0x33, 0x5B, 0x08, 0x1D, 0x4A, 0x13, 0x43, 0x9B, 0xB2, +0x33, 0x80, 0x22, 0xE0, 0x04, 0x34, 0x24, 0x01, 0x24, 0x09, 0x23, 0x1A, 0x1B, 0x01, 0x1B, 0x09, 0x93, 0x42, 0x9D, 0xD9, +0x03, 0x1B, 0x1B, 0x01, 0x9A, 0xD0, 0xF3, 0xE7, 0x64, 0x3B, 0xFF, 0x3B, 0x01, 0x93, 0x00, 0x9B, 0x01, 0x33, 0x1B, 0x01, +0x1B, 0x09, 0x00, 0x93, 0x9F, 0xE7, 0x9E, 0x23, 0xE8, 0x5C, 0xCB, 0xF7, 0x21, 0xF8, 0x0F, 0x4B, 0x01, 0x22, 0x1A, 0x60, +0xAA, 0x23, 0x00, 0x22, 0xEA, 0x54, 0xC2, 0xE7, 0x0C, 0x48, 0x77, 0xF7, 0xF1, 0xFC, 0x0A, 0xB0, 0x04, 0xBC, 0x90, 0x46, +0xF0, 0xBD, 0xC0, 0x46, 0x38, 0xE6, 0x10, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0x39, 0xCB, 0x10, 0x00, 0xDE, 0x05, 0x00, 0x00, +0xFA, 0x64, 0x61, 0x40, 0xFC, 0x64, 0x61, 0x40, 0x10, 0x65, 0x61, 0x40, 0x00, 0x80, 0xFF, 0xFF, 0x18, 0x00, 0x60, 0x40, +0x28, 0xD6, 0x10, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x82, 0xB0, 0x05, 0x00, 0x0E, 0x00, 0x82, 0x00, 0x9D, 0x4B, +0xD4, 0x58, 0x00, 0x2C, 0x00, 0xD1, 0x2B, 0xE1, 0x9B, 0x4B, 0x1B, 0x68, 0xDF, 0x68, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, +0x05, 0xD1, 0x99, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, +0xDB, 0xB2, 0xA3, 0x54, 0x09, 0x3A, 0xA2, 0x5C, 0x02, 0x2A, 0x01, 0xD1, 0x00, 0x2B, 0x51, 0xD0, 0x9E, 0xF7, 0xDE, 0xFF, +0x01, 0x90, 0x01, 0x22, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x20, 0xFD, 0x62, 0x23, 0x6B, 0x43, 0x8C, 0x4A, 0x94, 0x46, +0x63, 0x44, 0x1B, 0x88, 0xDB, 0x0B, 0x00, 0xD1, 0xAC, 0xE0, 0x31, 0x00, 0x28, 0x00, 0xFF, 0xF7, 0x15, 0xFE, 0xB4, 0x23, +0xE0, 0x54, 0xA0, 0x23, 0xE3, 0x5C, 0x02, 0x2B, 0x00, 0xD1, 0xEA, 0xE0, 0x01, 0x21, 0x28, 0x00, 0xFF, 0xF7, 0xBA, 0xF9, +0x82, 0x23, 0xE3, 0x5E, 0xA3, 0x60, 0x81, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x0C, 0xD0, 0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, +0x00, 0xD1, 0x9D, 0xE0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x93, 0xE0, 0x7A, 0x4B, 0x00, 0x22, 0x1A, 0x60, +0x34, 0x23, 0xFB, 0x5C, 0x00, 0x2B, 0x00, 0xD1, 0x90, 0xE0, 0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xBE, 0xE0, +0xAA, 0x33, 0xE3, 0x5C, 0x00, 0x2B, 0x00, 0xD0, 0xD6, 0xE0, 0xA6, 0x33, 0xE2, 0x5C, 0x01, 0x32, 0xA3, 0x3B, 0x13, 0x40, +0x9E, 0x22, 0xA1, 0x5C, 0x9C, 0x3A, 0x6E, 0x48, 0xCA, 0xF7, 0x56, 0xFF, 0xAA, 0x23, 0x01, 0x22, 0xE2, 0x54, 0xC7, 0xE0, +0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0xBE, 0xFF, 0xA0, 0x23, 0x02, 0x22, 0xE2, 0x54, 0x0A, 0x33, 0xE3, 0x5C, 0x00, 0x2B, +0x49, 0xD1, 0xFE, 0xF7, 0xBF, 0xFD, 0x65, 0x4A, 0xD5, 0x23, 0x5B, 0x00, 0xD2, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, +0x62, 0x4A, 0x9A, 0x18, 0x12, 0x88, 0xD2, 0x0B, 0x00, 0xD1, 0xAD, 0xE0, 0x60, 0x4A, 0x94, 0x46, 0x63, 0x44, 0x1A, 0x88, +0xD2, 0x0A, 0xAA, 0x42, 0x07, 0xD0, 0x19, 0x88, 0xC9, 0x0A, 0x56, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x28, 0x00, +0xA0, 0x47, 0x57, 0x4C, 0xD5, 0x20, 0x40, 0x00, 0x22, 0x5C, 0xD3, 0x00, 0x9B, 0x1A, 0x5B, 0x00, 0x54, 0x4A, 0x94, 0x46, +0x63, 0x44, 0x1A, 0x88, 0x52, 0x04, 0x52, 0x0C, 0x1A, 0x80, 0x21, 0x5C, 0x01, 0x31, 0x03, 0x23, 0x19, 0x40, 0x21, 0x54, +0x50, 0x4B, 0x1A, 0x68, 0xCB, 0x00, 0x5B, 0x1A, 0x5B, 0x00, 0x4F, 0x49, 0x8C, 0x46, 0x63, 0x44, 0x52, 0x04, 0x52, 0x0C, +0x93, 0x42, 0x05, 0xD0, 0x43, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x45, 0x4E, 0x00, 0x24, +0xD5, 0x23, 0x5B, 0x00, 0x98, 0x46, 0x3E, 0x4F, 0x0A, 0xE0, 0x28, 0x00, 0xCA, 0xF7, 0x30, 0xFF, 0xAA, 0x23, 0x00, 0x22, +0xE2, 0x54, 0xAE, 0xE7, 0x01, 0x34, 0x0E, 0x36, 0x04, 0x2C, 0x67, 0xD0, 0x33, 0x88, 0xDB, 0x0B, 0xF8, 0xD0, 0x3A, 0x4B, +0x42, 0x46, 0x98, 0x5C, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xFD, 0x6E, 0xA8, 0x47, 0xEF, 0xE7, 0x31, 0x00, 0x28, 0x00, +0xFF, 0xF7, 0x04, 0xFE, 0xB4, 0x23, 0xE0, 0x54, 0x51, 0xE7, 0x29, 0x00, 0x01, 0x98, 0xFF, 0xF7, 0x53, 0xFE, 0x66, 0xE7, +0xB4, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x2E, 0xD1, 0xAA, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x47, 0xD1, 0xA9, 0x33, 0xE3, 0x5C, +0x00, 0x2B, 0x43, 0xD1, 0x01, 0x21, 0x20, 0x00, 0xC9, 0xF7, 0x3A, 0xFF, 0x01, 0x99, 0x61, 0x60, 0x86, 0x23, 0xFA, 0x22, +0xD2, 0x01, 0xE2, 0x52, 0x21, 0x67, 0x20, 0x33, 0xE3, 0x5C, 0xDB, 0x02, 0xE0, 0x22, 0x92, 0x01, 0x13, 0x40, 0x26, 0x4A, +0x13, 0x43, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x61, 0x44, 0x0F, 0x01, 0x3F, 0x09, 0xE7, 0x60, 0x20, 0x00, +0xC9, 0xF7, 0x7C, 0xFD, 0x00, 0x28, 0x23, 0xD0, 0x15, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x1C, 0xE0, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xD9, 0xFE, 0x00, 0x23, 0xAA, 0x22, 0xA3, 0x54, 0x75, 0x3A, 0xBB, 0x54, +0xC6, 0xE7, 0x9E, 0x23, 0xE0, 0x5C, 0xCA, 0xF7, 0xCF, 0xFE, 0xAA, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x01, 0x3B, 0xE1, 0x5C, +0x12, 0x48, 0x77, 0xF7, 0xA1, 0xFB, 0x05, 0xE0, 0x06, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, +0x02, 0xB0, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, 0x38, 0xE6, 0x10, 0x00, 0xD8, 0xE5, 0x10, 0x00, 0x28, 0x19, 0x16, 0x00, +0x4E, 0x65, 0x61, 0x40, 0xC8, 0xE6, 0x10, 0x00, 0x7D, 0x03, 0x10, 0x00, 0x20, 0xA3, 0x16, 0x00, 0x90, 0x69, 0x61, 0x40, +0x92, 0x69, 0x61, 0x40, 0x2C, 0x04, 0x60, 0x40, 0x90, 0x69, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x34, 0xD6, 0x10, 0x00, +0x10, 0xB5, 0x82, 0x00, 0x0C, 0x4B, 0xD4, 0x58, 0x00, 0x2C, 0x0E, 0xD0, 0xA9, 0x23, 0xE3, 0x5C, 0x00, 0x2B, 0x05, 0xD1, +0x09, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xA9, 0x22, 0xA3, 0x5C, 0x01, 0x3B, 0xA3, 0x54, +0x10, 0xBD, 0x04, 0x4B, 0xDC, 0x6E, 0x00, 0x23, 0x00, 0x22, 0x00, 0x21, 0xA0, 0x47, 0xF7, 0xE7, 0x38, 0xE6, 0x10, 0x00, +0x28, 0x19, 0x16, 0x00, 0xF0, 0xB5, 0xC6, 0x46, 0x00, 0xB5, 0x06, 0x00, 0x0D, 0x00, 0x14, 0x00, 0xCF, 0xB2, 0x06, 0x2F, +0x08, 0xD9, 0xFF, 0x20, 0x08, 0x40, 0x10, 0x4B, 0xDB, 0x6E, 0x98, 0x46, 0x00, 0x23, 0x00, 0x22, 0x21, 0x00, 0xC0, 0x47, +0x00, 0x2C, 0x0A, 0xD0, 0x04, 0x2C, 0x0F, 0xD0, 0xFF, 0x20, 0x28, 0x40, 0x09, 0x4B, 0xDD, 0x6E, 0x00, 0x23, 0x00, 0x22, +0x21, 0x00, 0xA8, 0x47, 0x03, 0xE0, 0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0x61, 0xFE, 0x04, 0xBC, 0x90, 0x46, 0xF0, 0xBD, +0x31, 0x00, 0x38, 0x00, 0xFF, 0xF7, 0xB6, 0xFF, 0xF7, 0xE7, 0xC0, 0x46, 0x28, 0x19, 0x16, 0x00, 0xF8, 0xB5, 0x05, 0x00, +0x51, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x02, 0xD0, 0xFE, 0xF7, 0x0E, 0xFD, 0xF8, 0xBD, 0x4F, 0x48, 0x77, 0xF7, 0x22, 0xFB, +0x4E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x07, 0xD0, 0x4D, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, +0x12, 0x20, 0xEF, 0xE7, 0x00, 0x21, 0xF8, 0x20, 0x75, 0xF7, 0xE0, 0xFA, 0x46, 0x4B, 0x18, 0x60, 0x00, 0x28, 0x00, 0xD1, +0x7C, 0xE0, 0x9E, 0xF7, 0x37, 0xFE, 0x06, 0x00, 0x83, 0xF7, 0xD8, 0xFB, 0x43, 0x4A, 0x13, 0x88, 0x43, 0x49, 0x0B, 0x40, +0x00, 0x02, 0x03, 0x43, 0x9B, 0xB2, 0x13, 0x80, 0x3D, 0x4B, 0x1C, 0x68, 0xF8, 0x22, 0x00, 0x21, 0x20, 0x00, 0x73, 0xF7, +0x79, 0xFA, 0x00, 0x23, 0x63, 0x62, 0x3D, 0x4A, 0xE2, 0x61, 0x3D, 0x4A, 0x22, 0x62, 0x03, 0x22, 0x22, 0x76, 0x3C, 0x4A, +0x12, 0x78, 0xA2, 0x75, 0x3B, 0x4A, 0x22, 0x61, 0x05, 0x22, 0xE2, 0x75, 0x99, 0x32, 0xA3, 0x54, 0x01, 0x32, 0x01, 0x21, +0xA1, 0x54, 0x6B, 0x3A, 0x22, 0x65, 0x6D, 0x32, 0xA3, 0x54, 0x7F, 0xF7, 0xA9, 0xFA, 0x07, 0x1E, 0x3D, 0xD0, 0x3A, 0x89, +0x94, 0x23, 0xE2, 0x52, 0x93, 0x3B, 0x01, 0x22, 0x29, 0x00, 0x00, 0x20, 0xFE, 0xF7, 0xE8, 0xFC, 0x33, 0x00, 0x00, 0x22, +0x29, 0x00, 0x01, 0x20, 0xFF, 0xF7, 0x50, 0xF9, 0x9E, 0xF7, 0xF8, 0xFD, 0x60, 0x60, 0x00, 0x23, 0x82, 0x22, 0xA3, 0x52, +0xA3, 0x60, 0x04, 0x32, 0xFA, 0x21, 0xC9, 0x01, 0xA1, 0x52, 0xE6, 0x66, 0x26, 0x67, 0x63, 0x67, 0xA3, 0x67, 0x00, 0x22, +0xA6, 0x33, 0xE2, 0x54, 0x23, 0x4B, 0xA3, 0x82, 0xFA, 0x23, 0x1B, 0x02, 0x9C, 0x46, 0x66, 0x44, 0x36, 0x01, 0x36, 0x09, +0xE6, 0x60, 0x20, 0x00, 0xC9, 0xF7, 0x6C, 0xFC, 0x00, 0x28, 0x15, 0xD1, 0xA0, 0x23, 0x00, 0x22, 0xE2, 0x54, 0x1C, 0x49, +0xA1, 0x32, 0xFF, 0x32, 0x8B, 0x5A, 0x01, 0x24, 0x23, 0x43, 0x8B, 0x52, 0xA0, 0x3A, 0xFF, 0x3A, 0x18, 0x4B, 0x1A, 0x60, +0x78, 0xE7, 0x0E, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0xBA, 0xE7, 0x0A, 0x4B, 0x9B, 0x6E, +0x00, 0x22, 0x00, 0x21, 0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x69, 0xE7, 0x06, 0x4B, 0x9B, 0x6E, 0x00, 0x22, 0x00, 0x21, +0x00, 0x20, 0x98, 0x47, 0x12, 0x20, 0x61, 0xE7, 0xD8, 0xE5, 0x10, 0x00, 0x4C, 0xD6, 0x10, 0x00, 0x38, 0xE6, 0x10, 0x00, +0x28, 0x19, 0x16, 0x00, 0xFE, 0x64, 0x61, 0x40, 0xFF, 0xF8, 0xFF, 0xFF, 0xA1, 0x04, 0x10, 0x00, 0xD3, 0x01, 0x10, 0x00, +0x7C, 0x91, 0x0D, 0x00, 0x6A, 0x04, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x20, 0xA3, 0x16, 0x00, 0xC8, 0xE6, 0x10, 0x00, +0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x0A, 0x48, 0x77, 0xF7, 0x68, 0xFA, 0xA1, 0x78, 0x4A, 0x10, 0x01, 0x23, 0x1A, 0x40, +0x07, 0x48, 0x02, 0x70, 0x0B, 0x40, 0xA3, 0x70, 0x20, 0x00, 0xFF, 0xF7, 0x85, 0xF9, 0x01, 0x00, 0x28, 0x00, 0xFA, 0xF7, +0x8B, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x60, 0xD6, 0x10, 0x00, 0xDC, 0xE5, 0x10, 0x00, 0x70, 0xB5, 0x05, 0x00, +0x0C, 0x00, 0x06, 0x48, 0x77, 0xF7, 0x4C, 0xFA, 0x28, 0x00, 0xFF, 0xF7, 0x1B, 0xFF, 0x01, 0x00, 0x20, 0x00, 0xFA, 0xF7, +0x77, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xC0, 0x46, 0x68, 0xD6, 0x10, 0x00, 0x10, 0xB5, 0xFF, 0xF7, 0x51, 0xF8, 0x00, 0x20, +0x10, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x0E, 0x4B, 0x1B, 0x68, 0x00, 0x2B, 0x17, 0xD0, 0xDC, 0x68, 0x18, 0x23, 0x0D, 0x22, +0x00, 0x21, 0x0B, 0x48, 0x75, 0xF7, 0x2A, 0xF9, 0xFF, 0x23, 0x03, 0x70, 0xA3, 0x88, 0x43, 0x80, 0x00, 0x23, 0x03, 0x71, +0x43, 0x71, 0x23, 0x69, 0x83, 0x60, 0x63, 0x69, 0xC3, 0x60, 0xE3, 0x69, 0x03, 0x61, 0xE3, 0x6A, 0x43, 0x61, 0xC6, 0xF7, +0x79, 0xFF, 0x10, 0xBD, 0xD8, 0xE5, 0x10, 0x00, 0x03, 0x11, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x00, 0x0D, 0x00, 0x01, 0x78, +0x0A, 0x48, 0x77, 0xF7, 0x11, 0xFA, 0x23, 0x78, 0x00, 0x2B, 0x07, 0xD0, 0x01, 0x2B, 0x08, 0xD0, 0x00, 0x21, 0x28, 0x00, +0xFA, 0xF7, 0x3A, 0xF9, 0x00, 0x20, 0x70, 0xBD, 0xFE, 0xF7, 0x6E, 0xFB, 0xF6, 0xE7, 0xFF, 0xF7, 0xC7, 0xFF, 0xFE, 0xF7, +0x69, 0xFB, 0xF1, 0xE7, 0x70, 0xD6, 0x10, 0x00, 0x45, 0x54, 0x45, 0x52, 0x52, 0x3A, 0x0A, 0x00, 0x77, 0x61, 0x6B, 0x65, +0x75, 0x70, 0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x5F, 0x75, 0x70, +0x5F, 0x68, 0x6F, 0x73, 0x74, 0x0A, 0x00, 0x00, 0x75, 0x61, 0x72, 0x74, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x0A, 0x00, 0x00, +0x70, 0x5F, 0x73, 0x5F, 0x70, 0x00, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x5F, 0x63, 0x68, 0x5F, 0x75, 0x70, 0x64, 0x61, +0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, +0xE6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xF6, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x1A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x42, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x66, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x8E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xBA, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xE6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x0C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x32, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x5C, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0x82, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA2, 0x1C, 0x10, 0x00, 0xC4, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x16, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x3E, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x62, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x8A, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0xB6, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0xE2, 0x1B, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x08, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x2E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x58, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x7E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0x9E, 0x1C, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, 0xA8, 0x1A, 0x10, 0x00, +0xA8, 0x1A, 0x10, 0x00, 0xC0, 0x1C, 0x10, 0x00, 0x30, 0x78, 0x34, 0x30, 0x33, 0x34, 0x33, 0x30, 0x30, 0x34, 0x3A, 0x25, +0x78, 0x2C, 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x43, 0x54, 0x53, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x20, 0x0A, 0x00, +0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, +0x78, 0x1D, 0x10, 0x00, 0x52, 0x1E, 0x10, 0x00, 0xE4, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, +0xE2, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x78, 0x1D, 0x10, 0x00, 0x6D, 0x64, 0x6C, 0x6C, 0x5F, 0x72, 0x65, 0x63, +0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x62, 0x64, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, +0x78, 0x0A, 0x00, 0x00, 0x77, 0x69, 0x66, 0x69, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, 0x2C, +0x25, 0x78, 0x0A, 0x00, 0x66, 0x6C, 0x61, 0x73, 0x68, 0x6D, 0x61, 0x63, 0x5F, 0x61, 0x64, 0x64, 0x72, 0x3A, 0x25, 0x78, +0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x43, 0x52, 0x5F, 0x50, 0x57, 0x52, 0x5F, 0x52, 0x45, 0x51, +0x0A, 0x00, 0x00, 0x00, 0x50, 0x57, 0x52, 0x5F, 0x43, 0x54, 0x52, 0x4C, 0x5F, 0x52, 0x45, 0x51, 0x0A, 0x00, 0x00, 0x00, +0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x6D, 0x61, 0x78, 0x5F, 0x70, 0x77, 0x72, 0x0A, 0x00, 0x61, 0x66, 0x68, 0x74, +0x6F, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x74, 0x78, 0x5F, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, +0x72, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x72, 0x73, 0x73, 0x69, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, +0x73, 0x6D, 0x75, 0x74, 0x65, 0x0A, 0x00, 0x00, 0x72, 0x78, 0x5F, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x3A, 0x25, +0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, +0x64, 0x75, 0x20, 0x65, 0x6E, 0x6F, 0x75, 0x67, 0x68, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x77, 0x69, 0x66, 0x69, 0x20, 0x63, +0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x69, 0x6F, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x75, 0x6D, 0x72, 0x65, 0x0A, 0x00, 0x00, 0x00, +0x55, 0x4E, 0x44, 0x45, 0x46, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x0A, 0x00, 0x00, +0x55, 0x4E, 0x4B, 0x4E, 0x4F, 0x57, 0x20, 0x56, 0x45, 0x4E, 0x44, 0x4F, 0x52, 0x5F, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0x25, +0x78, 0x0A, 0x00, 0x00, 0x69, 0x6E, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, +0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x78, 0x5C, 0x10, 0x00, +0x38, 0x5C, 0x10, 0x00, 0x70, 0x5C, 0x10, 0x00, 0x76, 0x65, 0x72, 0x3A, 0x25, 0x73, 0x0A, 0x00, 0x6C, 0x6D, 0x74, 0x3A, +0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x3A, 0x25, 0x78, 0x00, 0x00, 0x00, +0x76, 0x73, 0x5F, 0x61, 0x70, 0x63, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x6A, 0x65, 0x63, 0x74, 0x32, 0x3A, +0x25, 0x78, 0x00, 0x00, 0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x86, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, +0x92, 0x73, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0xC6, 0x72, 0x10, 0x00, 0x8C, 0x73, 0x10, 0x00, 0xC0, 0x72, 0x10, 0x00, +0x6E, 0x6F, 0x61, 0x6C, 0x63, 0x62, 0x75, 0x66, 0x0A, 0x00, 0x00, 0x00, 0x62, 0x62, 0x5F, 0x74, 0x78, 0x5F, 0x74, 0x6F, +0x6E, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x6F, 0x70, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x6D, 0x73, 0x73, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x6D, 0x73, 0x73, 0x65, 0x72, 0x72, 0x0A, 0x00, 0x46, 0x4C, 0x55, 0x53, 0x48, 0x3A, 0x25, 0x78, +0x0A, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x4B, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x25, 0x78, 0x20, 0x00, 0x6F, 0x70, 0x63, 0x3A, +0x25, 0x78, 0x0A, 0x00, 0x69, 0x20, 0x3D, 0x20, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x69, 0x3A, 0x25, 0x78, +0x0A, 0x00, 0x00, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x1E, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xBE, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, +0xFC, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xDA, 0x89, 0x10, 0x00, 0xDA, 0x89, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0x4C, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xE8, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, 0xF4, 0x8A, 0x10, 0x00, +0xF4, 0x8A, 0x10, 0x00, 0x62, 0x8A, 0x10, 0x00, 0x55, 0x50, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, +0x25, 0x78, 0x0A, 0x00, 0x6F, 0x70, 0x6C, 0x6C, 0x63, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x72, +0x78, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x6C, 0x6C, 0x63, 0x74, 0x6D, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, +0x61, 0x70, 0x63, 0x66, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x61, 0x74, 0x65, 0x6E, 0x63, 0x79, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x5F, 0x72, 0x65, 0x73, 0x65, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x45, 0x52, 0x52, 0x3A, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x2C, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, +0x52, 0x54, 0x5F, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, +0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x41, 0x53, 0x53, 0x45, +0x52, 0x54, 0x5F, 0x45, 0x52, 0x52, 0x7A, 0x28, 0x25, 0x73, 0x29, 0x2C, 0x20, 0x69, 0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, +0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x41, 0x53, 0x53, 0x45, 0x52, 0x54, 0x5F, 0x50, +0x41, 0x52, 0x41, 0x4D, 0x7A, 0x28, 0x30, 0x78, 0x25, 0x58, 0x2C, 0x20, 0x30, 0x78, 0x25, 0x58, 0x29, 0x2C, 0x20, 0x69, +0x6E, 0x20, 0x25, 0x78, 0x20, 0x61, 0x74, 0x20, 0x6C, 0x69, 0x6E, 0x65, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, +0x70, 0x61, 0x67, 0x65, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x20, 0x25, +0x78, 0x0D, 0x0A, 0x00, 0x64, 0x65, 0x6C, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x6F, 0x70, 0x3A, 0x30, 0x78, 0x25, 0x78, 0x20, 0x30, 0x78, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x73, 0x63, 0x61, 0x6E, +0x5F, 0x65, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x63, 0x68, 0x65, 0x72, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, +0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x3A, 0x25, 0x78, 0x0A, 0x00, +0x74, 0x65, 0x73, 0x74, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x5F, 0x65, 0x78, 0x69, 0x74, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, +0x74, 0x73, 0x74, 0x5F, 0x65, 0x6E, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x74, 0x73, +0x74, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x65, 0x64, 0x72, 0x5F, +0x70, 0x6B, 0x74, 0x3D, 0x25, 0x78, 0x00, 0x00, 0x66, 0x72, 0x65, 0x71, 0x25, 0x78, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, +0xC0, 0xB8, 0x10, 0x00, 0xB4, 0xB9, 0x10, 0x00, 0x94, 0xBA, 0x10, 0x00, 0xF2, 0xB8, 0x10, 0x00, 0xB0, 0xBA, 0x10, 0x00, +0xCC, 0xBA, 0x10, 0x00, 0xE8, 0xBA, 0x10, 0x00, 0x04, 0xBB, 0x10, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, +0x73, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, +0x34, 0x64, 0x2C, 0x20, 0x6F, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x6F, 0x6C, 0x65, 0x3A, 0x25, 0x34, 0x64, +0x2C, 0x20, 0x70, 0x6E, 0x3A, 0x25, 0x34, 0x64, 0x20, 0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, +0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, +0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x70, 0x6F, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x73, 0x6F, 0x3A, 0x25, +0x34, 0x64, 0x2C, 0x20, 0x68, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, 0x63, 0x65, 0x3A, 0x25, 0x34, 0x64, 0x2C, 0x20, +0x62, 0x63, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x3A, 0x25, 0x37, 0x64, 0x2C, 0x20, 0x70, 0x65, 0x72, 0x3A, +0x25, 0x64, 0x2E, 0x25, 0x64, 0x2C, 0x20, 0x62, 0x65, 0x72, 0x3A, 0x25, 0x64, 0x2E, 0x25, 0x64, 0x0D, 0x0A, 0x00, 0x00, +0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x62, 0x75, 0x72, 0x73, 0x74, 0x5F, 0x74, 0x78, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, +0x0A, 0x00, 0x00, 0x00, 0x72, 0x78, 0x61, 0x62, 0x6F, 0x72, 0x74, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x73, 0x63, 0x68, 0x5F, +0x70, 0x72, 0x6F, 0x67, 0x5F, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, +0x6C, 0x64, 0x5F, 0x62, 0x62, 0x5F, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0A, 0x00, +0x74, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x72, 0x78, 0x5F, 0x74, 0x73, 0x74, 0x0A, 0x00, 0x62, 0x62, 0x5F, 0x74, +0x73, 0x74, 0x5F, 0x73, 0x74, 0x6F, 0x70, 0x3A, 0x25, 0x78, 0x0A, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x02, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC7, 0x03, 0x00, 0x00, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, +0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, +0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, +0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, +0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, +0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, +0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, +0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, +0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, +0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, +0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, +0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, +0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, +0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, +0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, +0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, +0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, +0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, +0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, +0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, +0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, +0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, +0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, +0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, +0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, +0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, +0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, +0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, +0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, +0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, +0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, +0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, +0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, +0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, +0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, +0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, +0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, +0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, +0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, +0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, +0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, +0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, +0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, +0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, +0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, +0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, +0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, +0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, +0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, +0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, +0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, +0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFF, 0xC1, 0xFB, 0xE8, +0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, +0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, +0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, +0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, +0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, +0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, +0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, +0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, +0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, +0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, +0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, +0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, +0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, +0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, 0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, +0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, 0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, +0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, 0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, +0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, 0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, +0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, 0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, +0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, 0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, +0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, 0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, +0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, 0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, +0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, 0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, +0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, 0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, +0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, 0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, +0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, 0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, +0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, 0xE7, 0xB3, 0x51, 0x89, 0x63, +0xAB, 0x23, 0x23, 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, 0x0C, +0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, 0x2A, 0x50, 0xEA, 0xE9, 0x0E, +0x9C, 0x4B, 0x5E, 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, 0xF3, +0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, 0x28, 0xD4, 0xF2, 0x9B, 0xA4, +0xFD, 0x64, 0x65, 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, 0x15, +0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, 0x7F, 0xF0, 0x3E, 0x3A, 0x13, +0xA4, 0xDC, 0xE2, 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, 0x14, +0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, 0x79, 0x7C, 0x17, 0xAC, 0xED, +0x06, 0xAD, 0xAF, 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, 0x3F, +0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, 0x80, 0x10, 0x43, 0x4E, 0x35, +0xEC, 0x65, 0x27, 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, 0x3C, +0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, 0x8A, 0x84, 0x39, 0xF4, 0x36, +0x0B, 0xF7, 0xF0, 0x1F, 0xBC, 0x8F, 0xCE, 0x04, 0x29, 0xB7, 0x78, 0x3E, 0x1B, 0x95, 0x38, 0xB6, 0x3A, 0x32, 0x22, 0x40, +0x88, 0x21, 0xA7, 0x1A, 0xF6, 0xB2, 0x13, 0x85, 0x5A, 0x7E, 0x93, 0xB4, 0x9F, 0xAC, 0xCC, 0x80, 0x31, 0xC5, 0xD2, 0x5F, +0x34, 0xAE, 0x69, 0x1E, 0xDF, 0x05, 0x6B, 0xBB, 0x41, 0xEB, 0xAB, 0x02, 0xA5, 0x9E, 0xEE, 0xC0, 0xB9, 0xE4, 0x75, 0x45, +0xC2, 0x1C, 0x7A, 0x9B, 0x85, 0x7B, 0xF8, 0x0F, 0xDE, 0x47, 0x67, 0x82, 0x94, 0x5B, 0x3C, 0x9F, 0x8D, 0x4A, 0x1C, 0x5B, +0x1D, 0x19, 0x11, 0x20, 0xC4, 0x90, 0x53, 0x0D, 0x7B, 0xD9, 0x89, 0x42, 0x2D, 0xBF, 0x49, 0xDA, 0x4F, 0x56, 0x66, 0xC0, +0x98, 0x62, 0xE9, 0x2F, 0x1A, 0xD7, 0x34, 0x8F, 0xEF, 0x82, 0xB5, 0xDD, 0xA0, 0xF5, 0x55, 0x81, 0x52, 0x4F, 0x77, 0xE0, +0x5C, 0xF2, 0xBA, 0x22, 0x61, 0x0E, 0xBD, 0xCD, 0xC2, 0x3D, 0xFC, 0x07, 0xEF, 0xA3, 0x33, 0x41, 0xCA, 0x2D, 0x9E, 0xCF, +0x46, 0x25, 0x8E, 0xAD, 0x8E, 0x8C, 0x08, 0x10, 0x62, 0xC8, 0xA9, 0x86, 0xBD, 0xEC, 0x44, 0xA1, 0x96, 0xDF, 0x24, 0xED, +0x27, 0x2B, 0x33, 0x60, 0x4C, 0xB1, 0xF4, 0x17, 0x8D, 0x6B, 0x9A, 0xC7, 0x77, 0xC1, 0xDA, 0x6E, 0xD0, 0xFA, 0xAA, 0x40, +0xA9, 0xA7, 0x3B, 0x70, 0x2E, 0x79, 0x5D, 0x91, 0x30, 0x87, 0xDE, 0x66, 0xE1, 0x1E, 0xFE, 0x83, 0xF7, 0xD1, 0x99, 0x20, +0xE5, 0x16, 0xCF, 0x67, 0xA3, 0x12, 0xC7, 0x56, 0x47, 0x46, 0x04, 0x08, 0x31, 0xE4, 0x54, 0xC3, 0x5E, 0x76, 0xA2, 0x50, +0xCB, 0x6F, 0x92, 0xF6, 0x93, 0x95, 0x19, 0x30, 0xA6, 0x58, 0xFA, 0x8B, 0xC6, 0x35, 0xCD, 0xE3, 0xBB, 0x60, 0x6D, 0x37, +0x68, 0x7D, 0x55, 0xA0, 0xD4, 0xD3, 0x1D, 0x38, 0x97, 0xBC, 0xAE, 0x48, 0x98, 0x43, 0x6F, 0xB3, 0x70, 0x0F, 0xFF, 0xC1, +0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, +0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, +0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, +0x04, 0x05, 0x05, 0x06, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, +0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, +0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, +0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, +0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, +0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, +0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, +0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, +0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, +0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08, 0x00, 0x10, 0x20, 0x30, +0x40, 0x50, 0x60, 0x70, 0x00, 0x00, 0x01, 0x50, 0x00, 0x03, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x50, +0x00, 0x02, 0x07, 0x03, 0x0C, 0x04, 0x0D, 0x05, 0x26, 0x06, 0x37, 0x07, 0x2C, 0x08, 0x3D, 0x09, 0x00, 0x00, 0x02, 0x01, +0x05, 0x00, 0x01, 0x07, 0x00, 0x01, 0x00, 0x00, 0x01, 0x07, 0x00, 0x01, 0x0C, 0x00, 0x03, 0x0D, 0x00, 0x03, 0x06, 0x01, +0x01, 0x07, 0x01, 0x01, 0x0C, 0x01, 0x03, 0x0D, 0x01, 0x03, 0x00, 0x00, 0x00, 0x27, 0x35, 0x00, 0x2B, 0x00, 0x31, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x22, 0x10, 0x00, 0xFF, 0xF0, 0xAA, 0xFF, 0xFF, 0x00, 0x0F, 0x55, +0x80, 0x01, 0x00, 0x00, 0xF6, 0xFC, 0xFE, 0x00, 0x03, 0x06, 0x09, 0x0A, 0xF9, 0xFC, 0xFF, 0x02, 0x05, 0x07, 0x09, 0x0C, +0x0F, 0x11, 0x15, 0x17, 0x50, 0x00, 0x00, 0x00, 0xE4, 0x57, 0x00, 0x00, 0x50, 0xC3, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, +0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x24, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x25, +0x00, 0x80, 0xDE, 0xA9, 0x91, 0x06, 0x7B, 0x00, 0x04, 0x10, 0x04, 0x00, 0x04, 0x00, 0x00, 0x26, 0x00, 0x80, 0xDE, 0xA9, +0x65, 0x06, 0x7C, 0x00, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x48, +0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0x7F, 0x24, 0x17, 0x42, 0x40, 0x40, 0x8D, 0x08, 0x7B, 0xB0, 0x14, 0x10, 0x04, 0x00, +0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, +0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, +0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, +0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, 0x04, 0x10, 0x04, 0x00, +0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, 0x3C, 0xE7, 0x1C, 0x24, +0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, 0x17, 0x42, 0x40, 0x40, +0xFD, 0x08, 0x7A, 0xB0, 0x14, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x84, 0x27, 0x00, 0x80, 0xDE, 0xA9, 0x91, 0x46, 0x7B, 0x03, +0x04, 0x10, 0x04, 0x00, 0x0C, 0x21, 0x04, 0x26, 0x00, 0x80, 0xDE, 0xA9, 0x81, 0x06, 0x7B, 0x03, 0x04, 0xF0, 0x03, 0x00, +0x3C, 0xE7, 0x1C, 0x24, 0x09, 0x80, 0xDE, 0xA9, 0x69, 0x06, 0x7C, 0x4B, 0x04, 0x10, 0x04, 0x00, 0xF8, 0xFF, 0xFF, 0x27, +0x17, 0x42, 0x40, 0x40, 0xFD, 0x08, 0x7A, 0xB0, 0xD0, 0x9E, 0x21, 0x00, 0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, +0x1C, 0x1C, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x41, 0xD4, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x61, +0xD6, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x65, 0xD7, 0x9E, 0x21, 0x00, 0x70, 0x70, 0xFB, 0x75, 0xD7, 0x9E, 0x21, 0x00, +0x70, 0x70, 0xFB, 0xFD, 0xD7, 0x9E, 0x21, 0x00, 0xF0, 0xF0, 0xFB, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, +0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, +0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, +0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xD7, 0x9D, 0x21, 0x00, 0xF0, 0xF0, 0x87, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0B, 0x00, 0x00, 0x04, 0x00, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0xFF, 0xF9, 0x01, 0x08, +0x00, 0x00, 0x00, 0x00, 0xAC, 0x2B, 0x16, 0x00, 0x04, 0x00, 0x00, 0x00, 0x28, 0x21, 0x16, 0x00, 0xA8, 0x61, 0x00, 0x00, +0xB8, 0x88, 0x00, 0x00, 0x74, 0x40, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, +0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, +0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, +0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, +0x60, 0x07, 0x8D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, +0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, +0x6B, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, +0x6C, 0x00, 0x0F, 0xDB, 0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, +0x60, 0xD7, 0x0C, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, +0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, +0x58, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, +0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, +0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, +0x80, 0x80, 0x80, 0x80, 0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, +0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0xED, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, +0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0xCD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, +0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x79, +0x80, 0x80, 0x80, 0x80, 0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, +0x34, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x5B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6B, 0x3E, 0x55, 0x00, +0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x07, 0x8D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0xDB, +0x60, 0x07, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xD7, 0x0C, 0x78, +0x80, 0x80, 0x80, 0x80, 0x22, 0x3E, 0x55, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, +0x22, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x58, 0x3E, 0x55, 0x00, +0x6D, 0x0C, 0x2F, 0xDB, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xD8, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0xDB, +0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0xEB, 0x3E, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, +0x80, 0x80, 0x80, 0x80, 0x6B, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, +0xEB, 0x3F, 0x55, 0x00, 0x6D, 0x0C, 0x2F, 0x1B, 0x60, 0x9F, 0x0D, 0x68, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, +0x6C, 0x00, 0x00, 0x03, 0x60, 0x07, 0xAC, 0xE9, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x00, 0x03, +0x60, 0x07, 0x0C, 0xE8, 0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0x20, 0x03, 0x60, 0xD7, 0x0C, 0xE8, +0x80, 0x80, 0x80, 0x80, 0x00, 0x94, 0x7F, 0x00, 0x6C, 0x00, 0xE0, 0x03, 0x60, 0x9F, 0x0D, 0xE8, 0x80, 0x80, 0x80, 0x80, +0x00, 0xBE, 0x7F, 0x00, 0x6C, 0x00, 0x0F, 0x1B, 0x60, 0xE7, 0x8C, 0x69, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, +0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, +0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, +0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x2F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, +0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x87, 0xEC, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, +0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0xAD, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, +0x60, 0x07, 0x0D, 0x79, 0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x07, 0x0D, 0x78, +0x80, 0x80, 0x80, 0x80, 0x00, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0x6F, 0x1B, 0x60, 0x17, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, +0x12, 0x3E, 0x55, 0x00, 0xFC, 0x00, 0xEF, 0x5B, 0x60, 0x1F, 0x0D, 0x78, 0x80, 0x80, 0x80, 0x80, 0x6D, 0x3E, 0x55, 0x00, +0xFC, 0x00, 0xEF, 0x9B, 0x60, 0x9F, 0x0D, 0x68, 0x03, 0xC7, 0x8E, 0x00, 0x07, 0xC7, 0x8E, 0x00, 0x0B, 0xC7, 0x8E, 0x00, +0x0F, 0xC7, 0x8E, 0x00, 0x13, 0xC7, 0x8E, 0x00, 0x17, 0xC7, 0x8E, 0x00, 0x1B, 0xC7, 0x8E, 0x00, 0x1F, 0xC7, 0x8E, 0x00, +0x23, 0xC7, 0x8E, 0x00, 0x27, 0xC7, 0x8E, 0x00, 0x2B, 0xC7, 0x8E, 0x00, 0x2F, 0xC7, 0x8E, 0x00, 0x33, 0xC7, 0x8E, 0x00, +0x37, 0xC7, 0x8E, 0x00, 0x3B, 0xC7, 0x8E, 0x00, 0x3F, 0xC7, 0x8E, 0x00, 0x06, 0x81, 0x88, 0x00, 0x0A, 0x81, 0x88, 0x00, +0x0C, 0xC1, 0x88, 0x00, 0x14, 0xC1, 0x90, 0x00, 0x14, 0x41, 0x91, 0x00, 0x15, 0xC1, 0x91, 0x00, 0x23, 0xC1, 0x91, 0x00, +0x3F, 0xC1, 0x91, 0x00, 0x3F, 0xC1, 0x92, 0x00, 0x3F, 0x01, 0x94, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, +0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x3F, 0xC1, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x2D, 0x20, 0x53, 0x65, 0x70, 0x20, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3A, 0x33, 0x38, 0x3A, +0x33, 0x39, 0x20, 0x2D, 0x20, 0x67, 0x69, 0x74, 0x20, 0x30, 0x61, 0x61, 0x62, 0x66, 0x62, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +}; + +struct firmware_info{ + char fw_name[30]; + char* fw_array; + int fw_size; +}; + +struct firmware_info firmware[]={ + {"fmacfw.bin", fmacfw, sizeof(fmacfw)}, + {"fw_adid_u03.bin", fw_adid_u03, sizeof(fw_adid_u03)}, + {"fw_patch_table_u03.bin", fw_patch_table_u03, sizeof(fw_patch_table_u03)}, + {"fw_patch_u03.bin", fw_patch_u03, sizeof(fw_patch_u03)} +}; + +int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf){ + int firmware_number = 0; + int index = 0; + int fw_size = 0; + + firmware_number = sizeof(firmware)/sizeof(struct firmware_info); + printk("%s search:%s \r\n", __func__ , fw_name); + + for(index = 0; index < firmware_number; index++){ + if(!strcmp(firmware[index].fw_name, fw_name)){ + fw_size = firmware[index].fw_size; + printk("%s find %s len:%d\r\n", __func__, fw_name, fw_size); + *fw_buf = (u32*)firmware[index].fw_array; + return fw_size; + } + } + + printk("%s %s not found \r\n", __func__, fw_name); + + return 0; +}
\ No newline at end of file diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.h b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.h new file mode 100644 index 000000000000..dcf38e9ba302 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.h @@ -0,0 +1,3 @@ +int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf); + + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_txq_prealloc.c b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_txq_prealloc.c new file mode 100644 index 000000000000..9514c416b5d6 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_txq_prealloc.c @@ -0,0 +1,62 @@ +#include <linux/slab.h> +#include "aicsdio_txrxif.h" +#include "aic_bsp_driver.h" + +struct prealloc_txq{ + int prealloced; + void *txq; + size_t size; +}; + +struct prealloc_txq prealloc_txq; +#define MAX_TXQ_SIZE 100 * 1024 + +void *aicwf_prealloc_txq_alloc(size_t size) +{ + + BUG_ON(size > MAX_TXQ_SIZE); + + //check prealloc_txq.size + if((int)prealloc_txq.size != (int)size) + { + AICWFDBG(LOGINFO, "%s size is diff will to be kzalloc \r\n", __func__); + + if(prealloc_txq.txq != NULL) + { + AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); + kfree(prealloc_txq.txq); + prealloc_txq.txq = NULL; + } + + prealloc_txq.size = size; + prealloc_txq.prealloced = 0; + } + + //check prealloc or not + if(!prealloc_txq.prealloced) + { + prealloc_txq.txq = kzalloc(size, GFP_KERNEL); + if(!prealloc_txq.txq){ + AICWFDBG(LOGERROR, "%s txq kzalloc fail \r\n", __func__); + }else{ + AICWFDBG(LOGINFO, "%s txq kzalloc successful \r\n", __func__); + prealloc_txq.prealloced = 1; + } + }else{ + AICWFDBG(LOGINFO, "%s txq not need to kzalloc \r\n", __func__); + } + + return prealloc_txq.txq; +} +void aicwf_prealloc_txq_free(void) +{ + if(prealloc_txq.txq != NULL) + { + AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__); + kfree(prealloc_txq.txq); + prealloc_txq.txq = NULL; + } +} + +EXPORT_SYMBOL(aicwf_prealloc_txq_alloc); + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_txq_prealloc.h b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_txq_prealloc.h new file mode 100644 index 000000000000..ce4ee07473b3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicwf_txq_prealloc.h @@ -0,0 +1,4 @@ + + +void aicwf_prealloc_txq_free(void); + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/md5.c b/drivers/net/wireless/aic8800/aic8800_bsp/md5.c new file mode 100644 index 000000000000..3d7b65375adb --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/md5.c @@ -0,0 +1,161 @@ +#include <linux/memory.h> +#include "md5.h" + +unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +void MD5Init(MD5_CTX *context) +{ + context->count[0] = 0; + context->count[1] = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; +} +void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) +{ + unsigned int i = 0,index = 0,partlen = 0; + index = (context->count[0] >> 3) & 0x3F; + partlen = 64 - index; + context->count[0] += inputlen << 3; + if(context->count[0] < (inputlen << 3)) + context->count[1]++; + context->count[1] += inputlen >> 29; + + if(inputlen >= partlen) + { + memcpy(&context->buffer[index],input,partlen); + MD5Transform(context->state,context->buffer); + for(i = partlen;i+64 <= inputlen;i+=64) + MD5Transform(context->state,&input[i]); + index = 0; + } + else + { + i = 0; + } + memcpy(&context->buffer[index],&input[i],inputlen-i); +} +void MD5Final(MD5_CTX *context,unsigned char digest[16]) +{ + unsigned int index = 0,padlen = 0; + unsigned char bits[8]; + index = (context->count[0] >> 3) & 0x3F; + padlen = (index < 56)?(56-index):(120-index); + MD5Encode(bits,context->count,8); + MD5Update(context,PADDING,padlen); + MD5Update(context,bits,8); + MD5Encode(digest,context->state,16); +} +void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) +{ + unsigned int i = 0,j = 0; + while(j < len) + { + output[j] = input[i] & 0xFF; + output[j+1] = (input[i] >> 8) & 0xFF; + output[j+2] = (input[i] >> 16) & 0xFF; + output[j+3] = (input[i] >> 24) & 0xFF; + i++; + j+=4; + } +} +void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) +{ + unsigned int i = 0,j = 0; + while(j < len) + { + output[i] = (input[j]) | + (input[j+1] << 8) | + (input[j+2] << 16) | + (input[j+3] << 24); + i++; + j+=4; + } +} +void MD5Transform(unsigned int state[4],unsigned char block[64]) +{ + unsigned int a = state[0]; + unsigned int b = state[1]; + unsigned int c = state[2]; + unsigned int d = state[3]; + unsigned int x[64]; + MD5Decode(x,block,64); + FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ + FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ + II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/md5.h b/drivers/net/wireless/aic8800/aic8800_bsp/md5.h new file mode 100644 index 000000000000..6ed5c0f8e886 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/md5.h @@ -0,0 +1,48 @@ +#ifndef MD5_H +#define MD5_H + +typedef struct +{ + unsigned int count[2]; + unsigned int state[4]; + unsigned char buffer[64]; +}MD5_CTX; + + +#define F(x,y,z) ((x & y) | (~x & z)) +#define G(x,y,z) ((x & z) | (y & ~z)) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y ^ (x | ~z)) +#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) +#define FF(a,b,c,d,x,s,ac) \ + { \ + a += F(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +#define GG(a,b,c,d,x,s,ac) \ + { \ + a += G(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +#define HH(a,b,c,d,x,s,ac) \ + { \ + a += H(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +#define II(a,b,c,d,x,s,ac) \ + { \ + a += I(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +void MD5Init(MD5_CTX *context); +void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); +void MD5Final(MD5_CTX *context,unsigned char digest[16]); +void MD5Transform(unsigned int state[4],unsigned char block[64]); +void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); +void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/rwnx_version_gen.h b/drivers/net/wireless/aic8800/aic8800_bsp/rwnx_version_gen.h new file mode 100644 index 000000000000..e2d038e8802e --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/rwnx_version_gen.h @@ -0,0 +1,4 @@ +#define RWNX_VERS_REV "241c091M (master)" +#define RWNX_VERS_MOD "6.4.3.0" +#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" +#define RELEASE_DATE "2023_1212_15dcf017" diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/.gitignore b/drivers/net/wireless/aic8800/aic8800_btlpm/.gitignore new file mode 100644 index 000000000000..c3c2d151e157 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/.gitignore @@ -0,0 +1,10 @@ +*.o +*.ko +*.order +*.symvers +*.o.d +*.o.cmd +*.ko.cmd +*.mod +*.mod.c +*.mod.cmd diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig b/drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig new file mode 100644 index 000000000000..ff7aaa649f83 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig @@ -0,0 +1,5 @@ +config AIC8800_BTLPM_SUPPORT + tristate "AIC8800 bluetooth Support" + help + This is support for aic bluetooh driver. + diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/Makefile b/drivers/net/wireless/aic8800/aic8800_btlpm/Makefile new file mode 100644 index 000000000000..34037406b54a --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/Makefile @@ -0,0 +1,96 @@ +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 = y +CONFIG_AUTO_PM ?= n + +aic8800_btlpm-y := \ + aic_bluetooth_main.o \ + rfkill.o \ + +ifeq ($(CONFIG_PLATFORM_UBUNTU), n) + aic8800_btlpm-$(CONFIG_SUPPORT_LPM) += lpm.o +endif + +ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) + +ccflags-$(CONFIG_AUTO_PM) += -DCONFIG_AUTO_PM + +ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) +KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel +ARCH ?= arm +CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3229/Android10/SDK/kernel/ +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android10/SDK/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/ +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux#-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- +#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/kernel +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- + +ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP +ccflags-y += -DANDROID_PLATFORM +endif + +ifeq ($(CONFIG_PLATFORM_ROCKCHIP2), y) +ARCH = arm64 +KDIR = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel +CROSS_COMPILE = /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +ccflags-$(CONFIG_PLATFORM_ROCKCHIP2) += -DCONFIG_PLATFORM_ROCKCHIP2 +ccflags-y += -DANDROID_PLATFORM +endif + +ifeq ($(CONFIG_PLATFORM_ALLWINNER), y) +ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER +KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9/ +ARCH ?= arm64 +CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android- +ccflags-y += -DANDROID_PLATFORM +endif + +ifeq ($(CONFIG_PLATFORM_AMLOGIC), y) +ccflags-$(CONFIG_PLATFORM_NANOPI) += -DCONFIG_PLATFORM_NANOPI +ccflags-y += -DANDROID_PLATFORM +endif + +ifeq ($(CONFIG_PLATFORM_UBUNTU), y) +KDIR ?= /lib/modules/$(shell uname -r)/build +PWD ?= $(shell pwd) +KVER ?= $(shell uname -r) +MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/ +ARCH ?= x86_64 +CROSS_COMPILE ?= +endif + + +all: modules +modules: + make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules + +install: + mkdir -p $(MODDESTDIR) + install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR) + /sbin/depmod -a ${KVER} + +uninstall: + rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko + /sbin/depmod -a ${KVER} + +clean: + rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk + + diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c b/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c new file mode 100644 index 000000000000..52d768d83da8 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c @@ -0,0 +1,1167 @@ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#define DEBUG + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/notifier.h> +#include <linux/proc_fs.h> +#include <linux/spinlock.h> +#include <linux/timer.h> +#include <linux/uaccess.h> +#include <linux/version.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> + +#include <linux/irq.h> +#include <linux/param.h> +#include <linux/bitops.h> +#include <linux/termios.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> +#include <linux/of_platform.h> +#include <linux/pm_wakeirq.h> + +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> +#include <linux/serial_core.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) +#include <linux/wakelock.h> +#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 <code>NOTIFY_DONE</code>. + */ +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 + * <code>HOST_WAKE</code> 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 <code>errno</code> 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 <code>BT_WAKE</code> GPIO pin value via the proc interface. + * When this function returns, <code>page</code> 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 <code>BT_WAKE</code> 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 + * <code>errno</code> 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 <code>BT_HOST_WAKE</code> GPIO pin value via the proc interface. + * When this function returns, <code>page</code> 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, <code>page</code> 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, <code>page</code> 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 + * <code>errno</code> 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 <code>errno</code> is set + * appropriately. + */ +static int __init bluesleep_init(void) +{ + int retval; + struct proc_dir_entry *ent; + + BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); + + retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe); + if (retval) + return retval; + +#if !BT_BLUEDROID_SUPPORT + bluesleep_hdev = NULL; +#endif + + bluetooth_dir = proc_mkdir("bluetooth", NULL); + if (bluetooth_dir == NULL) { + BT_ERR("Unable to create /proc/bluetooth directory"); + return -ENOMEM; + } + + sleep_dir = proc_mkdir("sleep", bluetooth_dir); + if (sleep_dir == NULL) { + BT_ERR("Unable to create /proc/%s directory", PROC_DIR); + return -ENOMEM; + } +#if 0 + /* Creating read/write "btwake" entry */ + ent = create_proc_entry("btwake", 0, sleep_dir); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + ent->read_proc = bluepower_read_proc_btwake; + ent->write_proc = bluepower_write_proc_btwake; + + /* read only proc entries */ + if (create_proc_read_entry("hostwake", 0, sleep_dir, + bluepower_read_proc_hostwake, NULL) == NULL) { + BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + + /* read/write proc entries */ + ent = create_proc_entry("proto", 0666, sleep_dir); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + ent->read_proc = bluesleep_read_proc_proto; + ent->write_proc = bluesleep_write_proc_proto; + + /* read only proc entries */ + if (create_proc_read_entry("asleep", 0, + sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { + BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } +#endif +#if BT_BLUEDROID_SUPPORT + /* read/write proc entries */ + ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + + ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } +#endif + + flags = 0; /* clear all status bits */ + + /* Initialize spinlock. */ + spin_lock_init(&rw_lock); + + /* Initialize timer */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) + timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); +#else + init_timer(&rx_timer); + rx_timer.function = bluesleep_rx_timer_expire; + rx_timer.data = 0; +#endif + + /* initialize host wake tasklet */ + tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); + +#if !BT_BLUEDROID_SUPPORT + hci_register_notifier(&hci_event_nblock); +#endif + + return 0; + +fail: +#if BT_BLUEDROID_SUPPORT + remove_proc_entry("btwrite", sleep_dir); + remove_proc_entry("lpm", sleep_dir); +#endif +#if 0 + remove_proc_entry("asleep", sleep_dir); + remove_proc_entry("proto", sleep_dir); + remove_proc_entry("hostwake", sleep_dir); + remove_proc_entry("btwake", sleep_dir); +#endif + remove_proc_entry("sleep", bluetooth_dir); + remove_proc_entry("bluetooth", 0); + return retval; +} + +/** + * Cleans up the module. + */ +static void __exit bluesleep_exit(void) +{ +#if !BT_BLUEDROID_SUPPORT + hci_unregister_notifier(&hci_event_nblock); +#endif + platform_driver_unregister(&bluesleep_driver); + +#if BT_BLUEDROID_SUPPORT + remove_proc_entry("btwrite", sleep_dir); + remove_proc_entry("lpm", sleep_dir); +#endif +#if 0 + remove_proc_entry("asleep", sleep_dir); + remove_proc_entry("proto", sleep_dir); + remove_proc_entry("hostwake", sleep_dir); + remove_proc_entry("btwake", sleep_dir); +#endif + remove_proc_entry("sleep", bluetooth_dir); + remove_proc_entry("bluetooth", 0); +} + +module_init(bluesleep_init); +module_exit(bluesleep_exit); + +MODULE_DESCRIPTION("Bluetooth Sleep Mode Driver ver %s " VERSION); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/aic_bluetooth_main.c b/drivers/net/wireless/aic8800/aic8800_btlpm/aic_bluetooth_main.c new file mode 100644 index 000000000000..122d867f0ed6 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/aic_bluetooth_main.c @@ -0,0 +1,88 @@ +#include <linux/module.h> +#include <linux/inetdevice.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/platform_device.h> +#include "lpm.h" +#include "rfkill.h" + +#define DRV_CONFIG_FW_NAME "fw.bin" +#define DRV_DESCRIPTION "AIC BLUETOOTH" +#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi" +#define DRV_AUTHOR "AICSemi" +#define DRV_VERS_MOD "1.0" + +static struct platform_device *aicbt_pdev; + +static struct platform_driver aicbt_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "aic_bt", + }, + //.probe = aicbt_probe, + //.remove = aicbt_remove, +}; + +static int __init aic_bluetooth_mod_init(void) +{ + int ret; + printk("%s\n", __func__); + ret = platform_driver_register(&aicbt_driver); + if (ret) { + pr_err("register platform driver failed: %d\n", ret); + return ret; + } + + aicbt_pdev = platform_device_alloc("aic-bt", -1); + ret = platform_device_add(aicbt_pdev); + if (ret) { + pr_err("register platform device failed: %d\n", ret); + goto err0; + } + + ret = rfkill_bluetooth_init(aicbt_pdev); + if (ret) { + pr_err("rfkill init fail\n"); + goto err1; + } +#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) + ret = bluesleep_init(aicbt_pdev); + if (ret) { + pr_err("bluesleep init fail\n"); + goto err2; + } +#endif + + return 0; + +#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) +err2: +#endif + rfkill_bluetooth_remove(aicbt_pdev); +err1: + platform_device_del(aicbt_pdev); +err0: + platform_driver_unregister(&aicbt_driver); + return ret; +} + +static void __exit aic_bluetooth_mod_exit(void) +{ + printk("%s\n", __func__); +#if defined(ANDROID_PLATFORM) && !defined(CONFIG_PLATFORM_ROCKCHIP) && !defined(CONFIG_PLATFORM_ROCKCHIP2) + bluesleep_exit(aicbt_pdev); +#endif + rfkill_bluetooth_remove(aicbt_pdev); + platform_device_del(aicbt_pdev); + platform_driver_unregister(&aicbt_driver); +} + +module_init(aic_bluetooth_mod_init); +module_exit(aic_bluetooth_mod_exit); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_VERSION(DRV_VERS_MOD); +MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/aic_bsp_export.h b/drivers/net/wireless/aic8800/aic8800_btlpm/aic_bsp_export.h new file mode 100644 index 000000000000..88f6b565cd5f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/aic_bsp_export.h @@ -0,0 +1,19 @@ +#ifndef __AIC_BSP_EXPORT_H +#define __AIC_BSP_EXPORT_H + +#define AIC_BLUETOOTH 0 +#define AIC_WIFI 1 +#define AIC_PWR_OFF 0 +#define AIC_PWR_ON 1 + +struct aicbsp_feature_t { + bool band_5g_support; + uint32_t sdio_clock; + uint8_t sdio_phase; + uint8_t irqf; +}; + +int aicbsp_set_subsys(int, int); +int aicbsp_get_feature(struct aicbsp_feature_t *feature); + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/lpm.c b/drivers/net/wireless/aic8800/aic8800_btlpm/lpm.c new file mode 100644 index 000000000000..6e9b71564f19 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/lpm.c @@ -0,0 +1,1111 @@ +/* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + */ + +#define DEBUG + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/notifier.h> +#include <linux/proc_fs.h> +#include <linux/spinlock.h> +#include <linux/timer.h> +#include <linux/uaccess.h> +#include <linux/version.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> + +#include <linux/irq.h> +#include <linux/param.h> +#include <linux/bitops.h> +#include <linux/termios.h> +#include <linux/gpio.h> +#include <linux/of_gpio.h> +#include <linux/of_platform.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +#include <linux/pm_wakeirq.h> +#endif +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> +#include <linux/serial_core.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) +#include <linux/wakelock.h> +#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 <code>NOTIFY_DONE</code>. + */ +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 + * <code>HOST_WAKE</code> 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 <code>errno</code> 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 <code>BT_WAKE</code> GPIO pin value via the proc interface. + * When this function returns, <code>page</code> 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 <code>BT_WAKE</code> 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 + * <code>errno</code> 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 <code>BT_HOST_WAKE</code> GPIO pin value via the proc interface. + * When this function returns, <code>page</code> 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, <code>page</code> 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, <code>page</code> 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 + * <code>errno</code> 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 <code>errno</code> is set + * appropriately. + */ +int bluesleep_init(struct platform_device *pdev) +{ + int retval; + struct proc_dir_entry *ent; + + BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); + +#if 1 + retval = bluesleep_probe(pdev); + if (retval) + return retval; +#endif + +#if !BT_BLUEDROID_SUPPORT + bluesleep_hdev = NULL; +#endif + + bluetooth_dir = proc_mkdir("bluetooth", NULL); + if (bluetooth_dir == NULL) { + BT_ERR("Unable to create /proc/bluetooth directory"); + return -ENOMEM; + } + + sleep_dir = proc_mkdir("sleep", bluetooth_dir); + if (sleep_dir == NULL) { + BT_ERR("Unable to create /proc/%s directory", PROC_DIR); + return -ENOMEM; + } +#if 0 + /* Creating read/write "btwake" entry */ + ent = create_proc_entry("btwake", 0, sleep_dir); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/btwake entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + ent->read_proc = bluepower_read_proc_btwake; + ent->write_proc = bluepower_write_proc_btwake; + + /* read only proc entries */ + if (create_proc_read_entry("hostwake", 0, sleep_dir, + bluepower_read_proc_hostwake, NULL) == NULL) { + BT_ERR("Unable to create /proc/%s/hostwake entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + + /* read/write proc entries */ + ent = create_proc_entry("proto", 0666, sleep_dir); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/proto entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + ent->read_proc = bluesleep_read_proc_proto; + ent->write_proc = bluesleep_write_proc_proto; + + /* read only proc entries */ + if (create_proc_read_entry("asleep", 0, + sleep_dir, bluesleep_read_proc_asleep, NULL) == NULL) { + BT_ERR("Unable to create /proc/%s/asleep entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } +#endif +#if BT_BLUEDROID_SUPPORT + /* read/write proc entries */ + ent = proc_create("lpm", 0660, sleep_dir, &lpm_fops); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/lpm entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } + + ent = proc_create("btwrite", 0660, sleep_dir, &btwrite_fops); + if (ent == NULL) { + BT_ERR("Unable to create /proc/%s/btwrite entry", PROC_DIR); + retval = -ENOMEM; + goto fail; + } +#endif + + flags = 0; /* clear all status bits */ + + /* Initialize spinlock. */ + spin_lock_init(&rw_lock); + + /* Initialize timer */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) + timer_setup(&rx_timer, bluesleep_rx_timer_expire, 0); +#else + init_timer(&rx_timer); + rx_timer.function = bluesleep_rx_timer_expire; + rx_timer.data = 0; +#endif + + /* initialize host wake tasklet */ + tasklet_init(&hostwake_task, bluesleep_hostwake_task, 0); + +#if !BT_BLUEDROID_SUPPORT + hci_register_notifier(&hci_event_nblock); +#endif + + return 0; + +fail: +#if BT_BLUEDROID_SUPPORT + remove_proc_entry("btwrite", sleep_dir); + remove_proc_entry("lpm", sleep_dir); +#endif +#if 0 + remove_proc_entry("asleep", sleep_dir); + remove_proc_entry("proto", sleep_dir); + remove_proc_entry("hostwake", sleep_dir); + remove_proc_entry("btwake", sleep_dir); +#endif + remove_proc_entry("sleep", bluetooth_dir); + remove_proc_entry("bluetooth", 0); + return retval; +} + +/** + * Cleans up the module. + */ +int bluesleep_exit(struct platform_device *dev) +{ +#if !BT_BLUEDROID_SUPPORT + hci_unregister_notifier(&hci_event_nblock); +#endif + +#if BT_BLUEDROID_SUPPORT + remove_proc_entry("btwrite", sleep_dir); + remove_proc_entry("lpm", sleep_dir); +#endif +#if 0 + remove_proc_entry("asleep", sleep_dir); + remove_proc_entry("proto", sleep_dir); + remove_proc_entry("hostwake", sleep_dir); + remove_proc_entry("btwake", sleep_dir); +#endif + remove_proc_entry("sleep", bluetooth_dir); + remove_proc_entry("bluetooth", 0); + bluesleep_remove(dev); + return 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/lpm.h b/drivers/net/wireless/aic8800/aic8800_btlpm/lpm.h new file mode 100644 index 000000000000..0ff9dca14c0b --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/lpm.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015 Spreadtrum Communications Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LPM_H +#define __LPM_H + +int bluesleep_init(struct platform_device *pdev); +int bluesleep_exit(struct platform_device *dev); + +#endif + diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.c b/drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.c new file mode 100644 index 000000000000..5caf3f83a03a --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.c @@ -0,0 +1,81 @@ +/* + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rfkill.h> +#include <linux/gpio.h> +#include <linux/ioport.h> +#include <linux/clk.h> +#include <linux/of_gpio.h> +#include <linux/version.h> +#include "aic_bsp_export.h" + +static struct rfkill *bt_rfk; +static const char bt_name[] = "bluetooth"; + +static int bluetooth_set_power(void *data, bool blocked) +{ + pr_info("%s: start_block=%d\n", __func__, blocked); + if (!blocked) { + aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON); + } else { + aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF); + } + + pr_info("%s: end_block=%d\n", __func__, blocked); + return 0; +} + +static struct rfkill_ops rfkill_bluetooth_ops = { + .set_block = bluetooth_set_power, +}; + +int rfkill_bluetooth_init(struct platform_device *pdev) +{ + + int rc = 0; + + pr_info("-->%s\n", __func__); + bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, + &rfkill_bluetooth_ops, NULL); + if (!bt_rfk) { + rc = -ENOMEM; + goto err_rfkill_alloc; + } + /* userspace cannot take exclusive control */ + rfkill_init_sw_state(bt_rfk, true); + rc = rfkill_register(bt_rfk); + if (rc) + goto err_rfkill_reg; + + pr_info("<--%s\n", __func__); + + return 0; + +err_rfkill_reg: + rfkill_destroy(bt_rfk); +err_rfkill_alloc: + return rc; +} + +int rfkill_bluetooth_remove(struct platform_device *dev) +{ + pr_info("-->%s\n", __func__); + rfkill_unregister(bt_rfk); + rfkill_destroy(bt_rfk); + pr_info("<--%s\n", __func__); + return 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.h b/drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.h new file mode 100644 index 000000000000..ce0d5761a960 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.h @@ -0,0 +1,17 @@ +/* + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __RFKILL_H__ +#define __RFKILL_H__ + +int rfkill_bluetooth_init(struct platform_device *pdev); +int rfkill_bluetooth_remove(struct platform_device *pdev); + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/.gitignore b/drivers/net/wireless/aic8800/aic8800_fdrv/.gitignore new file mode 100644 index 000000000000..c3c2d151e157 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/.gitignore @@ -0,0 +1,10 @@ +*.o +*.ko +*.order +*.symvers +*.o.d +*.o.cmd +*.ko.cmd +*.mod +*.mod.c +*.mod.cmd diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig b/drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig new file mode 100644 index 000000000000..c26f2b4af23c --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig @@ -0,0 +1,5 @@ +config AIC8800_WLAN_SUPPORT + tristate "AIC8800 wlan Support" + help + This is support for aic wifi driver. + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile b/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile new file mode 100644 index 000000000000..6ea0e3d7e24b --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile @@ -0,0 +1,383 @@ +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 + +# 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_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_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 + +# 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_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_RESV_MEM_SUPPORT) += -DCONFIG_RESV_MEM_SUPPORT +ccflags-$(CONFIG_GKI) += -DCONFIG_GKI +ccflags-$(CONFIG_TEMP_COMP) += -DCONFIG_TEMP_COMP + + +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 + +# 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 + +ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src) + +ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y) +#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi- +#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/ +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel +#ARCH ?= arm +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- +#KDIR ?= /home/yaya/E/Rockchip/3566/Android/kernel +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/ +#ARCH ?= arm64 +#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- +#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel +KDIR ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/kernel +#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel +ARCH ?= arm64 +CROSS_COMPILE ?= ~/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- +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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.c new file mode 100644 index 000000000000..dd038e39f3fe --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.c @@ -0,0 +1,1569 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2017 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#define _AIC_BR_EXT_C_ + +#ifdef __KERNEL__ + #include <linux/if_arp.h> + #include <net/ip.h> + #include <net/ipx.h> + #include <linux/atalk.h> + #include <linux/udp.h> + #include <linux/if_pppox.h> + #include "rwnx_defs.h" +#endif + +#ifdef CL_IPV6_PASS + #ifdef __KERNEL__ + #include <linux/ipv6.h> + #include <linux/icmpv6.h> + #include <net/ndisc.h> + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)) + #include <net/ip6_checksum.h> + #else + #include <net/checksum.h> + #endif + #endif +#endif + +#ifdef CONFIG_BR_SUPPORT + +/* #define BR_SUPPORT_DEBUG */ + +#define NAT25_IPV4 01 +#define NAT25_IPV6 02 +#define NAT25_IPX 03 +#define NAT25_APPLE 04 +#define NAT25_PPPOE 05 + +#define RTL_RELAY_TAG_LEN (ETH_ALEN) +#define TAG_HDR_LEN 4 + +#define MAGIC_CODE 0x8186 +#define MAGIC_CODE_LEN 2 +#define WAIT_TIME_PPPOE 5 /* waiting time for pppoe server in sec */ + +/*----------------------------------------------------------------- + How database records network address: + 0 1 2 3 4 5 6 7 8 9 10 + |----|----|----|----|----|----|----|----|----|----|----| + IPv4 |type| | IP addr | + IPX |type| Net addr | Node addr | + IPX |type| Net addr |Sckt addr| + Apple |type| Network |node| + PPPoE |type| SID | AC MAC | +-----------------------------------------------------------------*/ + + +/* Find a tag in pppoe frame and return the pointer */ +static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type) +{ + unsigned char *cur_ptr, *start_ptr; + unsigned short tagLen, tagType; + + start_ptr = cur_ptr = (unsigned char *)ph->tag; + while ((cur_ptr - start_ptr) < ntohs(ph->length)) { + /* prevent un-alignment access */ + tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]); + tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]); + if (tagType == type) + return cur_ptr; + cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen; + } + return 0; +} + + +static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag) +{ + struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); + int data_len; + + data_len = tag->tag_len + TAG_HDR_LEN; + if (skb_tailroom(skb) < data_len) { + printk("skb_tailroom() failed in add SID tag!\n"); + return -1; + } + + skb_put(skb, data_len); + /* have a room for new tag */ + memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length)); + ph->length = htons(ntohs(ph->length) + data_len); + memcpy((unsigned char *)ph->tag, tag, data_len); + return data_len; +} + +static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len) +{ + int tail_len; + unsigned long end, tail; + + if ((src + len) > skb_tail_pointer(skb) || skb->len < len) + return -1; + + tail = (unsigned long)skb_tail_pointer(skb); + end = (unsigned long)src + len; + if (tail < end) + return -1; + + tail_len = (int)(tail - end); + if (tail_len > 0) + memmove(src, src + len, tail_len); + + skb_trim(skb, skb->len - len); + return 0; +} + +static __inline__ unsigned long __nat25_timeout(struct rwnx_vif *vif) +{ + unsigned long timeout; + + timeout = jiffies - NAT25_AGEING_TIME * HZ; + + return timeout; +} + + +static __inline__ int __nat25_has_expired(struct rwnx_vif *vif, + struct nat25_network_db_entry *fdb) +{ + if (time_before_eq(fdb->ageing_timer, __nat25_timeout(vif))) + return 1; + + return 0; +} + + +static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr, + unsigned int *ipAddr) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPV4; + memcpy(networkAddr + 7, (unsigned char *)ipAddr, 4); +} + + +static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr, + unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPX; + memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); + memcpy(networkAddr + 5, ipxNodeAddr, 6); +} + + +static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr, + unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPX; + memcpy(networkAddr + 1, (unsigned char *)ipxNetAddr, 4); + memcpy(networkAddr + 5, (unsigned char *)ipxSocketAddr, 2); +} + + +static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr, + unsigned short *network, unsigned char *node) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_APPLE; + memcpy(networkAddr + 1, (unsigned char *)network, 2); + networkAddr[3] = *node; +} + + +static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr, + unsigned char *ac_mac, unsigned short *sid) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_PPPOE; + memcpy(networkAddr + 1, (unsigned char *)sid, 2); + memcpy(networkAddr + 3, (unsigned char *)ac_mac, 6); +} + + +#ifdef CL_IPV6_PASS +static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr, + unsigned int *ipAddr) +{ + memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN); + + networkAddr[0] = NAT25_IPV6; + memcpy(networkAddr + 1, (unsigned char *)ipAddr, 16); +} + + +static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b) +{ + while (len > 0) { + if (*data == tag && *(data + 1) == len8b && len >= len8b * 8) + return data + 2; + + len -= (*(data + 1)) * 8; + data += (*(data + 1)) * 8; + } + return NULL; +} + + +static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac) +{ + struct icmp6hdr *icmphdr = (struct icmp6hdr *)data; + unsigned char *mac; + + if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { + if (len >= 8) { + mac = scan_tlv(&data[8], len - 8, 1, 1); + if (mac) { + printk("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) { + if (len >= 16) { + mac = scan_tlv(&data[16], len - 16, 1, 1); + if (mac) { + printk("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { + if (len >= 24) { + mac = scan_tlv(&data[24], len - 24, 1, 1); + if (mac) { + printk("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) { + if (len >= 24) { + mac = scan_tlv(&data[24], len - 24, 2, 1); + if (mac) { + printk("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + memcpy(mac, replace_mac, 6); + return 1; + } + } + } else if (icmphdr->icmp6_type == NDISC_REDIRECT) { + if (len >= 40) { + mac = scan_tlv(&data[40], len - 40, 2, 1); + if (mac) { + printk("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]); + memcpy(mac, replace_mac, 6); + return 1; + } + } + } + return 0; +} + +#ifdef SUPPORT_RX_UNI2MCAST +static void convert_ipv6_mac_to_mc(struct sk_buff *skb) +{ + struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); + unsigned char *dst_mac = skb->data; + + /* dst_mac[0] = 0xff; */ + /* dst_mac[1] = 0xff; */ + /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/ + dst_mac[0] = 0x33; + dst_mac[1] = 0x33; + memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4); +#if defined(__LINUX_2_6__) + /*modified by qinjunjie,warning:should not remove next line*/ + skb->pkt_type = PACKET_MULTICAST; +#endif +} +#endif /* CL_IPV6_PASS */ +#endif /* SUPPORT_RX_UNI2MCAST */ + + +static __inline__ int __nat25_network_hash(unsigned char *networkAddr) +{ + if (networkAddr[0] == NAT25_IPV4) { + unsigned long x; + + x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; + + return x & (NAT25_HASH_SIZE - 1); + } else if (networkAddr[0] == NAT25_IPX) { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ + networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10]; + + return x & (NAT25_HASH_SIZE - 1); + } else if (networkAddr[0] == NAT25_APPLE) { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3]; + + return x & (NAT25_HASH_SIZE - 1); + } else if (networkAddr[0] == NAT25_PPPOE) { + unsigned long x; + + x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8]; + + return x & (NAT25_HASH_SIZE - 1); + } +#ifdef CL_IPV6_PASS + else if (networkAddr[0] == NAT25_IPV6) { + unsigned long x; + + x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ + networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^ + networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^ + networkAddr[16]; + + return x & (NAT25_HASH_SIZE - 1); + } +#endif + else { + unsigned long x = 0; + int i; + + for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++) + x ^= networkAddr[i]; + + return x & (NAT25_HASH_SIZE - 1); + } +} + + +static __inline__ void __network_hash_link(struct rwnx_vif *vif, + struct nat25_network_db_entry *ent, int hash) +{ + /* Caller must _enter_critical_bh already! */ + /* _irqL irqL; */ + /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ + + ent->next_hash = vif->nethash[hash]; + if (ent->next_hash != NULL) + ent->next_hash->pprev_hash = &ent->next_hash; + vif->nethash[hash] = ent; + ent->pprev_hash = &vif->nethash[hash]; + + /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ +} + + +static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent) +{ + /* Caller must _enter_critical_bh already! */ + /* _irqL irqL; */ + /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ + + *(ent->pprev_hash) = ent->next_hash; + if (ent->next_hash != NULL) + ent->next_hash->pprev_hash = ent->pprev_hash; + ent->next_hash = NULL; + ent->pprev_hash = NULL; + + /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ +} + + +static int __nat25_db_network_lookup_and_replace(struct rwnx_vif *vif, + struct sk_buff *skb, unsigned char *networkAddr) +{ + struct nat25_network_db_entry *db; + spin_lock_bh(&vif->br_ext_lock); + + db = vif->nethash[__nat25_network_hash(networkAddr)]; + while (db != NULL) { + if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { + if (!__nat25_has_expired(vif, db)) { + /* replace the destination mac address */ + memcpy(skb->data, db->macAddr, ETH_ALEN); + atomic_inc(&db->use_count); + +#ifdef CL_IPV6_PASS + printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10], + db->networkAddr[11], + db->networkAddr[12], + db->networkAddr[13], + db->networkAddr[14], + db->networkAddr[15], + db->networkAddr[16]); +#else + printk("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10]); +#endif + } + spin_unlock_bh(&vif->br_ext_lock); + return 1; + } + + db = db->next_hash; + } + + spin_unlock_bh(&vif->br_ext_lock); + return 0; +} + + +static void __nat25_db_network_insert(struct rwnx_vif *vif, + unsigned char *macAddr, unsigned char *networkAddr) +{ + struct nat25_network_db_entry *db; + int hash; + spin_lock_bh(&vif->br_ext_lock); + + hash = __nat25_network_hash(networkAddr); + db = vif->nethash[hash]; + + while (db != NULL) { + if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { + memcpy(db->macAddr, macAddr, ETH_ALEN); + db->ageing_timer = jiffies; + spin_unlock_bh(&vif->br_ext_lock); + return; + } + + db = db->next_hash; + } + + db = (struct nat25_network_db_entry *)kmalloc(sizeof(*db), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (db == NULL) { + spin_unlock_bh(&vif->br_ext_lock); + return; + } + + memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN); + memcpy(db->macAddr, macAddr, ETH_ALEN); + atomic_set(&db->use_count, 1); + db->ageing_timer = jiffies; + + __network_hash_link(vif, db, hash); + + spin_unlock_bh(&vif->br_ext_lock); +} + + +static void __nat25_db_print(struct rwnx_vif *vif) +{ + spin_lock_bh(&vif->br_ext_lock); + +#ifdef BR_SUPPORT_DEBUG + static int counter = 0; + int i, j; + struct nat25_network_db_entry *db; + + counter++; + if ((counter % 16) != 0) + return; + + for (i = 0, j = 0; i < NAT25_HASH_SIZE; i++) { + db = vif->nethash[i]; + + while (db != NULL) { +#ifdef CL_IPV6_PASS + printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + j, + i, + atomic_read(&db->use_count), + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10], + db->networkAddr[11], + db->networkAddr[12], + db->networkAddr[13], + db->networkAddr[14], + db->networkAddr[15], + db->networkAddr[16]); +#else + printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + j, + i, + atomic_read(&db->use_count), + db->macAddr[0], + db->macAddr[1], + db->macAddr[2], + db->macAddr[3], + db->macAddr[4], + db->macAddr[5], + db->networkAddr[0], + db->networkAddr[1], + db->networkAddr[2], + db->networkAddr[3], + db->networkAddr[4], + db->networkAddr[5], + db->networkAddr[6], + db->networkAddr[7], + db->networkAddr[8], + db->networkAddr[9], + db->networkAddr[10]); +#endif + j++; + + db = db->next_hash; + } + } +#endif + + spin_unlock_bh(&vif->br_ext_lock); +} + + + + +/* + * NAT2.5 interface + */ + +void nat25_db_cleanup(struct rwnx_vif *vif) +{ + int i; + spin_lock_bh(&vif->br_ext_lock); + + for (i = 0; i < NAT25_HASH_SIZE; i++) { + struct nat25_network_db_entry *f; + f = vif->nethash[i]; + while (f != NULL) { + struct nat25_network_db_entry *g; + + g = f->next_hash; + if (vif->scdb_entry == f) { + memset(vif->scdb_mac, 0, ETH_ALEN); + memset(vif->scdb_ip, 0, 4); + vif->scdb_entry = NULL; + } + __network_hash_unlink(f); + kfree(f); + + f = g; + } + } + + spin_unlock_bh(&vif->br_ext_lock); +} + + +void nat25_db_expire(struct rwnx_vif *vif) +{ + int i; + spin_lock_bh(&vif->br_ext_lock); + + /* if(!priv->ethBrExtInfo.nat25_disable) */ + { + for (i = 0; i < NAT25_HASH_SIZE; i++) { + struct nat25_network_db_entry *f; + f = vif->nethash[i]; + + while (f != NULL) { + struct nat25_network_db_entry *g; + g = f->next_hash; + + if (__nat25_has_expired(vif, f)) { + if (atomic_dec_and_test(&f->use_count)) { +#ifdef BR_SUPPORT_DEBUG +#ifdef CL_IPV6_PASS + panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x\n", + i, + f->macAddr[0], + f->macAddr[1], + f->macAddr[2], + f->macAddr[3], + f->macAddr[4], + f->macAddr[5], + f->networkAddr[0], + f->networkAddr[1], + f->networkAddr[2], + f->networkAddr[3], + f->networkAddr[4], + f->networkAddr[5], + f->networkAddr[6], + f->networkAddr[7], + f->networkAddr[8], + f->networkAddr[9], + f->networkAddr[10], + f->networkAddr[11], + f->networkAddr[12], + f->networkAddr[13], + f->networkAddr[14], + f->networkAddr[15], + f->networkAddr[16]); +#else + + panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + i, + f->macAddr[0], + f->macAddr[1], + f->macAddr[2], + f->macAddr[3], + f->macAddr[4], + f->macAddr[5], + f->networkAddr[0], + f->networkAddr[1], + f->networkAddr[2], + f->networkAddr[3], + f->networkAddr[4], + f->networkAddr[5], + f->networkAddr[6], + f->networkAddr[7], + f->networkAddr[8], + f->networkAddr[9], + f->networkAddr[10]); +#endif +#endif + if (vif->scdb_entry == f) { + memset(vif->scdb_mac, 0, ETH_ALEN); + memset(vif->scdb_ip, 0, 4); + vif->scdb_entry = NULL; + } + __network_hash_unlink(f); + kfree(f); + } + } + + f = g; + } + } + } + + spin_unlock_bh(&vif->br_ext_lock); +} + + +#ifdef SUPPORT_TX_MCAST2UNI +static int checkIPMcAndReplace(struct rwnx_vif *vif, struct sk_buff *skb, unsigned int *dst_ip) +{ + struct stat_info *pstat; + struct list_head *phead, *plist; + int i; + + phead = &vif->asoc_list; + plist = phead->next; + + while (plist != phead) { + pstat = list_entry(plist, struct stat_info, asoc_list); + plist = plist->next; + + if (pstat->ipmc_num == 0) + continue; + + for (i = 0; i < MAX_IP_MC_ENTRY; i++) { + if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip) + 1, 3)) { + memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN); + return 1; + } + } + } + return 0; +} +#endif + +int nat25_db_handle(struct rwnx_vif *vif, struct sk_buff *skb, int method) +{ + unsigned short protocol; + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; + + if (skb == NULL) + return -1; + + if ((method <= NAT25_MIN) || (method >= NAT25_MAX)) + return -1; + + protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + + /*---------------------------------------------------*/ + /* Handle IP frame */ + /*---------------------------------------------------*/ + if (protocol == __constant_htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if (((unsigned char *)(iph) + (iph->ihl << 2)) >= (skb->data + ETH_HLEN + skb->len)) { + printk("NAT25: malformed IP packet !\n"); + return -1; + } + + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: { + /* some muticast with source IP is all zero, maybe other case is illegal */ + /* in class A, B, C, host address is all zero or all one is illegal */ + if (iph->saddr == 0) + return 0; + printk("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); + __nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr); + /* record source IP address and , source mac address into db */ + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(vif); + } + return 0; + + case NAT25_LOOKUP: { + printk("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr); +#ifdef SUPPORT_TX_MCAST2UNI + if (vif->pshare->rf_ft_var.mc2u_disable || + ((((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) + == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) && + !checkIPMcAndReplace(vif, skb, &iph->daddr)) || + (OPMODE & WIFI_ADHOC_STATE))) +#endif + { + __nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr); + + if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { + if (*((unsigned char *)&iph->daddr + 3) == 0xff) { + /* L2 is unicast but L3 is broadcast, make L2 bacome broadcast */ + printk("NAT25: Set DA as boardcast\n"); + memset(skb->data, 0xff, ETH_ALEN); + } else { + /* forward unknow IP packet to upper TCP/IP */ + printk("NAT25: Replace DA with BR's MAC\n"); + if ((*(u32 *)vif->br_mac) == 0 && (*(u16 *)(vif->br_mac + 4)) == 0) { + void netdev_br_init(struct net_device *netdev); + printk("Re-init netdev_br_init() due to br_mac==0!\n"); + netdev_br_init(vif->ndev); + } + memcpy(skb->data, vif->br_mac, ETH_ALEN); + } + } + } + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle ARP frame */ + /*---------------------------------------------------*/ + else if (protocol == __constant_htons(ETH_P_ARP)) { + struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN); + unsigned char *arp_ptr = (unsigned char *)(arp + 1); + unsigned int *sender, *target; + + if (arp->ar_pro != __constant_htons(ETH_P_IP)) { + printk("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro)); + return -1; + } + + switch (method) { + case NAT25_CHECK: + return 0; /* skb_copy for all ARP frame */ + + case NAT25_INSERT: { + printk("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0], + arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]); + + /* change to ARP sender mac address to wlan STA address */ + memcpy(arp_ptr, vif->ndev->dev_addr, ETH_ALEN); + + arp_ptr += arp->ar_hln; + sender = (unsigned int *)arp_ptr; + + __nat25_generate_ipv4_network_addr(networkAddr, sender); + + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(vif); + } + return 0; + + case NAT25_LOOKUP: { + printk("NAT25: Lookup ARP\n"); + + arp_ptr += arp->ar_hln; + sender = (unsigned int *)arp_ptr; + arp_ptr += (arp->ar_hln + arp->ar_pln); + target = (unsigned int *)arp_ptr; + + __nat25_generate_ipv4_network_addr(networkAddr, target); + + __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); + + /* change to ARP target mac address to Lookup result */ + arp_ptr = (unsigned char *)(arp + 1); + arp_ptr += (arp->ar_hln + arp->ar_pln); + memcpy(arp_ptr, skb->data, ETH_ALEN); + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle IPX and Apple Talk frame */ + /*---------------------------------------------------*/ + else if ((protocol == __constant_htons(ETH_P_IPX)) || + (protocol == __constant_htons(ETH_P_ATALK)) || + (protocol == __constant_htons(ETH_P_AARP))) { + unsigned char ipx_header[2] = {0xFF, 0xFF}; + struct ipxhdr *ipx = NULL; + struct elapaarp *ea = NULL; + struct ddpehdr *ddp = NULL; + unsigned char *framePtr = skb->data + ETH_HLEN; + + if (protocol == __constant_htons(ETH_P_IPX)) { + printk("NAT25: Protocol=IPX (Ethernet II)\n"); + ipx = (struct ipxhdr *)framePtr; + } else { /* if(protocol <= __constant_htons(ETH_FRAME_LEN)) */ + if (!memcmp(ipx_header, framePtr, 2)) { + printk("NAT25: Protocol=IPX (Ethernet 802.3)\n"); + ipx = (struct ipxhdr *)framePtr; + } else { + unsigned char ipx_8022_type = 0xE0; + unsigned char snap_8022_type = 0xAA; + + if (*framePtr == snap_8022_type) { + unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; /* IPX SNAP ID */ + unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; /* Apple Talk AARP SNAP ID */ + unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; /* Apple Talk DDP SNAP ID */ + + framePtr += 3; /* eliminate the 802.2 header */ + + if (!memcmp(ipx_snap_id, framePtr, 5)) { + framePtr += 5; /* eliminate the SNAP header */ + + printk("NAT25: Protocol=IPX (Ethernet SNAP)\n"); + ipx = (struct ipxhdr *)framePtr; + } else if (!memcmp(aarp_snap_id, framePtr, 5)) { + framePtr += 5; /* eliminate the SNAP header */ + + ea = (struct elapaarp *)framePtr; + } else if (!memcmp(ddp_snap_id, framePtr, 5)) { + framePtr += 5; /* eliminate the SNAP header */ + + ddp = (struct ddpehdr *)framePtr; + } else { + printk("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0], + framePtr[1], framePtr[2], framePtr[3], framePtr[4]); + return -1; + } + } else if (*framePtr == ipx_8022_type) { + framePtr += 3; /* eliminate the 802.2 header */ + + if (!memcmp(ipx_header, framePtr, 2)) { + printk("NAT25: Protocol=IPX (Ethernet 802.2)\n"); + ipx = (struct ipxhdr *)framePtr; + } else + return -1; + } + } + } + + /* IPX */ + if (ipx != NULL) { + switch (method) { + case NAT25_CHECK: + if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { + printk("NAT25: Check IPX skb_copy\n"); + return 0; + } + return -1; + + case NAT25_INSERT: { + printk("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n", + ipx->ipx_dest.net, + ipx->ipx_dest.node[0], + ipx->ipx_dest.node[1], + ipx->ipx_dest.node[2], + ipx->ipx_dest.node[3], + ipx->ipx_dest.node[4], + ipx->ipx_dest.node[5], + ipx->ipx_dest.sock, + ipx->ipx_source.net, + ipx->ipx_source.node[0], + ipx->ipx_source.node[1], + ipx->ipx_source.node[2], + ipx->ipx_source.node[3], + ipx->ipx_source.node[4], + ipx->ipx_source.node[5], + ipx->ipx_source.sock); + + if (!memcmp(skb->data + ETH_ALEN, ipx->ipx_source.node, ETH_ALEN)) { + printk("NAT25: Use IPX Net, and Socket as network addr\n"); + + __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock); + + /* change IPX source node addr to wlan STA address */ + memcpy(ipx->ipx_source.node, vif->ndev->dev_addr, ETH_ALEN); + } else + __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node); + + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(vif); + } + return 0; + + case NAT25_LOOKUP: { + if (!memcmp(vif->ndev->dev_addr, ipx->ipx_dest.node, ETH_ALEN)) { + printk("NAT25: Lookup IPX, Modify Destination IPX Node addr\n"); + + __nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock); + + __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); + + /* replace IPX destination node addr with Lookup destination MAC addr */ + memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN); + } else { + __nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node); + + __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); + } + } + return 0; + + default: + return -1; + } + } + + /* AARP */ + else if (ea != NULL) { + /* Sanity check fields. */ + if (ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN) { + printk("NAT25: Appletalk AARP Sanity check fail!\n"); + return -1; + } + + switch (method) { + case NAT25_CHECK: + return 0; + + case NAT25_INSERT: { + /* change to AARP source mac address to wlan STA address */ + memcpy(ea->hw_src, vif->ndev->dev_addr, ETH_ALEN); + + printk("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n", + ea->pa_src_net, + ea->pa_src_node, + ea->pa_dst_net, + ea->pa_dst_node); + + __nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node); + + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(vif); + } + return 0; + + case NAT25_LOOKUP: { + printk("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n", + ea->pa_src_net, + ea->pa_src_node, + ea->pa_dst_net, + ea->pa_dst_node); + + __nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node); + + __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); + + /* change to AARP destination mac address to Lookup result */ + memcpy(ea->hw_dst, skb->data, ETH_ALEN); + } + return 0; + + default: + return -1; + } + } + + /* DDP */ + else if (ddp != NULL) { + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: { + printk("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n", + ddp->deh_snet, + ddp->deh_snode, + ddp->deh_dnet, + ddp->deh_dnode); + + __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode); + + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(vif); + } + return 0; + + case NAT25_LOOKUP: { + printk("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n", + ddp->deh_snet, + ddp->deh_snode, + ddp->deh_dnet, + ddp->deh_dnode); + + __nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode); + + __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); + } + return 0; + + default: + return -1; + } + } + + return -1; + } + + /*---------------------------------------------------*/ + /* Handle PPPoE frame */ + /*---------------------------------------------------*/ + else if ((protocol == __constant_htons(ETH_P_PPP_DISC)) || + (protocol == __constant_htons(ETH_P_PPP_SES))) { + struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN); + unsigned short *pMagic; + + switch (method) { + case NAT25_CHECK: + if (ph->sid == 0) + return 0; + return 1; + + case NAT25_INSERT: + if (ph->sid == 0) { /* Discovery phase according to tag */ + if (ph->code == PADI_CODE || ph->code == PADR_CODE) { + if (vif->ethBrExtInfo.addPPPoETag) { + struct pppoe_tag *tag, *pOldTag; + unsigned char tag_buf[40]; + int old_tag_len = 0; + + tag = (struct pppoe_tag *)tag_buf; + pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); + if (pOldTag) { /* if SID existed, copy old value and delete it */ + old_tag_len = ntohs(pOldTag->tag_len); + if (old_tag_len + TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN > sizeof(tag_buf)) { + printk("SID tag length too long!\n"); + return -1; + } + + memcpy(tag->tag_data + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN, + pOldTag->tag_data, old_tag_len); + + if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN + old_tag_len) < 0) { + printk("call skb_pull_and_merge() failed in PADI/R packet!\n"); + return -1; + } + ph->length = htons(ntohs(ph->length) - TAG_HDR_LEN - old_tag_len); + } + + tag->tag_type = PTT_RELAY_SID; + tag->tag_len = htons(MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN + old_tag_len); + + /* insert the magic_code+client mac in relay tag */ + pMagic = (unsigned short *)tag->tag_data; + *pMagic = htons(MAGIC_CODE); + memcpy(tag->tag_data + MAGIC_CODE_LEN, skb->data + ETH_ALEN, ETH_ALEN); + + /* Add relay tag */ + if (__nat25_add_pppoe_tag(skb, tag) < 0) + return -1; + + printk("NAT25: Insert PPPoE, forward %s packet\n", + (ph->code == PADI_CODE ? "PADI" : "PADR")); + } else { /* not add relay tag */ + if (vif->pppoe_connection_in_progress && + memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) { + printk("Discard PPPoE packet due to another PPPoE connection is in progress!\n"); + return -2; + } + + if (vif->pppoe_connection_in_progress == 0) + memcpy(vif->pppoe_addr, skb->data + ETH_ALEN, ETH_ALEN); + + vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; + } + } else + return -1; + } else { /* session phase */ + printk("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name); + + __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid)); + + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + + __nat25_db_print(vif); + + if (!vif->ethBrExtInfo.addPPPoETag && + vif->pppoe_connection_in_progress && + !memcmp(skb->data + ETH_ALEN, vif->pppoe_addr, ETH_ALEN)) + vif->pppoe_connection_in_progress = 0; + } + return 0; + + case NAT25_LOOKUP: + if (ph->code == PADO_CODE || ph->code == PADS_CODE) { + if (vif->ethBrExtInfo.addPPPoETag) { + struct pppoe_tag *tag; + unsigned char *ptr; + unsigned short tagType, tagLen; + int offset = 0; + + ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID)); + if (ptr == 0) { + printk("Fail to find PTT_RELAY_SID in FADO!\n"); + return -1; + } + + tag = (struct pppoe_tag *)ptr; + tagType = (unsigned short)((ptr[0] << 8) + ptr[1]); + tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]); + + if ((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN))) { + printk("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen); + return -1; + } + + pMagic = (unsigned short *)tag->tag_data; + if (ntohs(*pMagic) != MAGIC_CODE) { + printk("Can't find MAGIC_CODE in %s packet!\n", + (ph->code == PADO_CODE ? "PADO" : "PADS")); + return -1; + } + + memcpy(skb->data, tag->tag_data + MAGIC_CODE_LEN, ETH_ALEN); + + if (tagLen > MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN) + offset = TAG_HDR_LEN; + + if (skb_pull_and_merge(skb, ptr + offset, TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset) < 0) { + printk("call skb_pull_and_merge() failed in PADO packet!\n"); + return -1; + } + ph->length = htons(ntohs(ph->length) - (TAG_HDR_LEN + MAGIC_CODE_LEN + RTL_RELAY_TAG_LEN - offset)); + if (offset > 0) + tag->tag_len = htons(tagLen - MAGIC_CODE_LEN - RTL_RELAY_TAG_LEN); + + printk("NAT25: Lookup PPPoE, forward %s Packet from %s\n", + (ph->code == PADO_CODE ? "PADO" : "PADS"), skb->dev->name); + } else { /* not add relay tag */ + if (!vif->pppoe_connection_in_progress) { + printk("Discard PPPoE packet due to no connection in progresss!\n"); + return -1; + } + memcpy(skb->data, vif->pppoe_addr, ETH_ALEN); + vif->pppoe_connection_in_progress = WAIT_TIME_PPPOE; + } + } else { + if (ph->sid != 0) { + printk("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name); + __nat25_generate_pppoe_network_addr(networkAddr, skb->data + ETH_ALEN, &(ph->sid)); + + __nat25_db_network_lookup_and_replace(vif, skb, networkAddr); + + __nat25_db_print(vif); + } else + return -1; + + } + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle EAP frame */ + /*---------------------------------------------------*/ + else if (protocol == __constant_htons(0x888e)) { + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle C-Media proprietary frame */ + /*---------------------------------------------------*/ + else if ((protocol == __constant_htons(0xe2ae)) || + (protocol == __constant_htons(0xe2af))) { + switch (method) { + case NAT25_CHECK: + return -1; + + case NAT25_INSERT: + return 0; + + case NAT25_LOOKUP: + return 0; + + default: + return -1; + } + } + + /*---------------------------------------------------*/ + /* Handle IPV6 frame */ + /*---------------------------------------------------*/ +#ifdef CL_IPV6_PASS + else if (protocol == __constant_htons(ETH_P_IPV6)) { + struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN); + + if (sizeof(*iph) >= (skb->len - ETH_HLEN)) { + printk("NAT25: malformed IPv6 packet !\n"); + return -1; + } + + switch (method) { + case NAT25_CHECK: + if (skb->data[0] & 1) + return 0; + return -1; + + case NAT25_INSERT: { + printk("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," + " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", + iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], + iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], + iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], + iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); + + if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) { + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr); + __nat25_db_network_insert(vif, skb->data + ETH_ALEN, networkAddr); + __nat25_db_print(vif); + + if (iph->nexthdr == IPPROTO_ICMPV6 && + skb->len > (ETH_HLEN + sizeof(*iph) + 4)) { + if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), + skb->len - ETH_HLEN - sizeof(*iph), vif->ndev->dev_addr)) { + struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph)); + hdr->icmp6_cksum = 0; + hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr, + iph->payload_len, + IPPROTO_ICMPV6, + csum_partial((__u8 *)hdr, iph->payload_len, 0)); + } + } + } + } + return 0; + + case NAT25_LOOKUP: + printk("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x," + " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", + iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3], + iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7], + iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3], + iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]); + + + __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr); + if (!__nat25_db_network_lookup_and_replace(vif, skb, networkAddr)) { +#ifdef SUPPORT_RX_UNI2MCAST + if (iph->daddr.s6_addr[0] == 0xff) + convert_ipv6_mac_to_mc(skb); +#endif + } + return 0; + + default: + return -1; + } + } +#endif /* CL_IPV6_PASS */ + + return -1; +} + + +int nat25_handle_frame(struct rwnx_vif *vif, struct sk_buff *skb) +{ + //printk("%s : vif_type=%d \n",__func__,RWNX_VIF_TYPE(vif)); +#ifdef BR_SUPPORT_DEBUG + if ((!vif->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1))) { + printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n", + skb->data[0], + skb->data[1], + skb->data[2], + skb->data[3], + skb->data[4], + skb->data[5], + skb->data[6], + skb->data[7], + skb->data[8], + skb->data[9], + skb->data[10], + skb->data[11]); + } +#endif + + if (!(skb->data[0] & 1)) { + int is_vlan_tag = 0, i, retval = 0; + unsigned short vlan_hdr = 0; + + if (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_8021Q)) { + is_vlan_tag = 1; + vlan_hdr = *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)); + for (i = 0; i < 6; i++) + *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + ETH_ALEN * 2 - 2 - i * 2)); + skb_pull(skb, 4); + } + + if (!vif->ethBrExtInfo.nat25_disable) { + unsigned long irqL; + spin_lock_bh(&vif->br_ext_lock); + /* + * This function look up the destination network address from + * the NAT2.5 database. Return value = -1 means that the + * corresponding network protocol is NOT support. + */ + if (!vif->ethBrExtInfo.nat25sc_disable && + (*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && + !memcmp(vif->scdb_ip, skb->data + ETH_HLEN + 16, 4)) { + memcpy(skb->data, vif->scdb_mac, ETH_ALEN); + + spin_unlock_bh(&vif->br_ext_lock); + } else { + spin_unlock_bh(&vif->br_ext_lock); + + retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); + } + } else { + if (((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_IP)) && + !memcmp(vif->br_ip, skb->data + ETH_HLEN + 16, 4)) || + ((*((unsigned short *)(skb->data + ETH_ALEN * 2)) == __constant_htons(ETH_P_ARP)) && + !memcmp(vif->br_ip, skb->data + ETH_HLEN + 24, 4))) { + /* for traffic to upper TCP/IP */ + retval = nat25_db_handle(vif, skb, NAT25_LOOKUP); + } + } + + if (is_vlan_tag) { + skb_push(skb, 4); + for (i = 0; i < 6; i++) + *((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2)); + *((unsigned short *)(skb->data + ETH_ALEN * 2)) = __constant_htons(ETH_P_8021Q); + *((unsigned short *)(skb->data + ETH_ALEN * 2 + 2)) = vlan_hdr; + } + + if (retval == -1) { + /* DEBUG_ERR("NAT25: Lookup fail!\n"); */ + return -1; + } + } + + return 0; +} + +#if 0 +void mac_clone(_adapter *priv, unsigned char *addr) +{ + struct sockaddr sa; + + memcpy(sa.sa_data, addr, ETH_ALEN); + RTW_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + rtl8192cd_set_hwaddr(priv->dev, &sa); +} + + +int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb) +{ + if (priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed) { + if (!(skb->data[ETH_ALEN] & 1)) { /* check any other particular MAC add */ + if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) && + ((priv->dev->br_port) && + memcmp(skb->data + ETH_ALEN, priv->br_mac, ETH_ALEN))) { + mac_clone(priv, skb->data + ETH_ALEN); + priv->macclone_completed = 1; + } + } + } + + return 0; +} +#endif /* 0 */ + +#define SERVER_PORT 67 +#define CLIENT_PORT 68 +#define DHCP_MAGIC 0x63825363 +#define BROADCAST_FLAG 0x8000 + +struct dhcpMessage { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + u_int32_t ciaddr; + u_int32_t yiaddr; + u_int32_t siaddr; + u_int32_t giaddr; + u_int8_t chaddr[16]; + u_int8_t sname[64]; + u_int8_t file[128]; + u_int32_t cookie; + u_int8_t options[308]; /* 312 - cookie */ +}; + +void dhcp_flag_bcast(struct rwnx_vif *vif, struct sk_buff *skb) +{ + if (skb == NULL) + return; + //print_hex_dump(KERN_ERR, "SKB DUMP: SKB->DATA== ", DUMP_PREFIX_NONE, 32, 1, skb->data, 64,false); + if (!vif->ethBrExtInfo.dhcp_bcst_disable) { + unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN)); + printk("%s protocol: %04x\n", __func__, protocol); + + if (protocol == __constant_htons(ETH_P_IP)) { /* IP */ + struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN); + + if (iph->protocol == IPPROTO_UDP) { /* UDP */ + struct udphdr *udph = (struct udphdr *)((u8 *)iph + (iph->ihl << 2)); + + if ((udph->source == __constant_htons(CLIENT_PORT)) + && (udph->dest == __constant_htons(SERVER_PORT))) { /* DHCP request */ + struct dhcpMessage *dhcph = + (struct dhcpMessage *)((u8 *)udph + sizeof(struct udphdr)); + + if (dhcph->cookie == __constant_htonl(DHCP_MAGIC)) { /* match magic word */ + if (!(dhcph->flags & htons(BROADCAST_FLAG))) { /* if not broadcast */ + register int sum = 0; + + printk("DHCP: change flag of DHCP request to broadcast.\n"); + + #if 1 + /* or BROADCAST flag */ + dhcph->flags |= htons(BROADCAST_FLAG); + /* recalculate checksum */ + sum = ~(udph->check) & 0xffff; + sum += dhcph->flags; + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + udph->check = ~sum; + #endif + } + } + } + } + } + } +} + + +void *scdb_findEntry(struct rwnx_vif *vif, unsigned char *macAddr, + unsigned char *ipAddr) +{ + printk("%s()\n",__func__); + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; + struct nat25_network_db_entry *db; + int hash; + /* _irqL irqL; */ + /* _enter_critical_bh(&priv->br_ext_lock, &irqL); */ + + __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr); + hash = __nat25_network_hash(networkAddr); + db = vif->nethash[hash]; + while (db != NULL) { + if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) { + /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ + return (void *)db; + } + + db = db->next_hash; + } + + /* _exit_critical_bh(&priv->br_ext_lock, &irqL); */ + return NULL; +} + +#endif /* CONFIG_BR_SUPPORT */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.h new file mode 100644 index 000000000000..71ebeb293b8e --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2017 Realtek Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + *****************************************************************************/ +#ifndef _AIC_BR_EXT_H_ +#define _AIC_BR_EXT_H_ + +#define CL_IPV6_PASS 1 +#define MACADDRLEN 6 +#define WLAN_ETHHDR_LEN 14 + +#define NAT25_HASH_BITS 4 +#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS) +#define NAT25_AGEING_TIME 300 + +#define NDEV_FMT "%s" +#define NDEV_ARG(ndev) ndev->name +#define ADPT_FMT "%s" +//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL) +#define FUNC_NDEV_FMT "%s(%s)" +#define FUNC_NDEV_ARG(ndev) __func__, ndev->name +#define FUNC_ADPT_FMT "%s(%s)" +//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL) +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5] + + +#ifdef CL_IPV6_PASS + #define MAX_NETWORK_ADDR_LEN 17 +#else + #define MAX_NETWORK_ADDR_LEN 11 +#endif + +struct nat25_network_db_entry { + struct nat25_network_db_entry *next_hash; + struct nat25_network_db_entry **pprev_hash; + atomic_t use_count; + unsigned char macAddr[6]; + unsigned long ageing_timer; + unsigned char networkAddr[MAX_NETWORK_ADDR_LEN]; +}; + +enum NAT25_METHOD { + NAT25_MIN, + NAT25_CHECK, + NAT25_INSERT, + NAT25_LOOKUP, + NAT25_PARSE, + NAT25_MAX +}; + +struct br_ext_info { + unsigned int nat25_disable; + unsigned int macclone_enable; + unsigned int dhcp_bcst_disable; + int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */ + unsigned char nat25_dmzMac[MACADDRLEN]; + unsigned int nat25sc_disable; +}; + +void nat25_db_cleanup(struct rwnx_vif *vif); + +#endif /* _AIC_BR_EXT_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_bsp_export.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_bsp_export.h new file mode 100644 index 000000000000..bd806fad5935 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_bsp_export.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c new file mode 100644 index 000000000000..0cc6d5a392b5 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c @@ -0,0 +1,909 @@ +#include "aic_vendor.h" +#include "rwnx_defs.h" +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/inetdevice.h> +#include <linux/rtnetlink.h> +#include <net/netlink.h> +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.h new file mode 100644 index 000000000000..0e1e3e0c7708 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.h @@ -0,0 +1,346 @@ +#ifndef _AIC_VENDOR_H +#define _AIC_VENDOR_H + +#include <linux/types.h> + +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800d80.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800d80.c new file mode 100644 index 000000000000..72eeb93ce319 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800d80.c @@ -0,0 +1,64 @@ +#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_ofst2x_req(rwnx_hw))) { + return -1; + } + + if (testmode == 0) { + 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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800d80.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800d80.h new file mode 100644 index 000000000000..df3e9d963a7d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800d80.h @@ -0,0 +1,9 @@ +#ifndef _AICWF_COMPAT_8800D80_H_ +#define _AICWF_COMPAT_8800D80_H_ +#include <linux/types.h> + +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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800dc.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800dc.c new file mode 100644 index 000000000000..f817fc0428df --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800dc.c @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800dc.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800dc.h new file mode 100644 index 000000000000..249703b68389 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_compat_8800dc.h @@ -0,0 +1,15 @@ +#include <linux/types.h> +#include "aic_bsp_export.h" + +#ifdef CONFIG_DPD +int aicwf_fdrv_dpd_result_apply_8800dc(struct rwnx_hw * rwnx_hw, rf_misc_ram_lite_t * dpd_res); +#ifndef CONFIG_FORCE_DPD_CALIB +int aicwf_fdrv_dpd_result_load_8800dc(struct rwnx_hw *rwnx_hw, rf_misc_ram_lite_t *dpd_res); +#endif +#endif +int aicwf_fdrv_misc_ram_init_8800dc(struct rwnx_hw *rwnx_hw); +int aicwf_set_rf_config_8800dc(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm); +int rwnx_plat_userconfig_load_8800dc(struct rwnx_hw *rwnx_hw); +int rwnx_plat_userconfig_load_8800dw(struct rwnx_hw *rwnx_hw); + + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_debug.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_debug.h new file mode 100644 index 000000000000..25a5766567eb --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_debug.h @@ -0,0 +1,56 @@ + + +#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ + + + +/* message levels */ +#define LOGERROR 0x0001 +#define LOGINFO 0x0002 +#define LOGTRACE 0x0004 +#define LOGDEBUG 0x0008 +#define LOGDATA 0x0010 +#define LOGIRQ 0x0020 +#define LOGSDPWRC 0x0040 +#define LOGWAKELOCK 0x0080 +#define LOGRXPOLL 0x0100 + +extern int aicwf_dbg_level; +void rwnx_data_dump(char* tag, void* data, unsigned long len); + +#define AICWF_LOG "AICWFDBG(" + +#define AICWFDBG(level, args, arg...) \ +do { \ + if (aicwf_dbg_level & level) { \ + printk(AICWF_LOG#level")\t" args, ##arg); \ + } \ +} while (0) + +#define RWNX_DBG(fmt, ...) \ +do { \ + if (aicwf_dbg_level & LOGTRACE) { \ + printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \ + } \ +} while (0) + + + +#if 0 +#define RWNX_DBG(fmt, ...) \ + do { \ + if (aicwf_dbg_level & LOGTRACE) { \ + printk(AICWF_LOG"LOGTRACE"")\t" fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define AICWFDBG(args, level) \ +do { \ + if (aicwf_dbg_level & level) { \ + printk(AICWF_LOG"(%s)\t" ,#level); \ + printf args; \ + } \ +} while (0) +#endif + + + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_rx_prealloc.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_rx_prealloc.c new file mode 100644 index 000000000000..59502b89a318 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_rx_prealloc.c @@ -0,0 +1,97 @@ +#include <linux/version.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include "aicwf_rx_prealloc.h" + +#ifdef CONFIG_PREALLOC_RX_SKB +struct aicwf_rx_buff_list aic_rx_buff_list; + +int aic_rxbuff_num_max = 30; + +int aic_rxbuff_size = (64 * 512); + +struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock) +{ + unsigned long flags; + struct rx_buff *rxbuff = NULL; + + spin_lock_irqsave(lock, flags); + if (list_empty(&aic_rx_buff_list.rxbuff_list)) { + spin_unlock_irqrestore(lock, flags); + printk("%s %d, rxbuff list is empty\n", __func__, __LINE__); + return NULL; + } else { + rxbuff = list_first_entry(&aic_rx_buff_list.rxbuff_list, + struct rx_buff, queue); + list_del_init(&rxbuff->queue); + atomic_dec(&aic_rx_buff_list.rxbuff_list_len); + } + spin_unlock_irqrestore(lock, flags); + //printk("len:%d\n", aic_rx_buff_list.rxbuff_list_len); + memset(rxbuff->data, 0, aic_rxbuff_size); + rxbuff->len = 0; + rxbuff->start = NULL; + rxbuff->read = NULL; + rxbuff->end = NULL; + + return rxbuff; +} + +void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); + atomic_inc(&aic_rx_buff_list.rxbuff_list_len); + spin_unlock_irqrestore(lock, flags); +} + +int aicwf_prealloc_init() +{ + struct rx_buff *rxbuff; + int i = 0; + + printk("%s enter\n", __func__); + INIT_LIST_HEAD(&aic_rx_buff_list.rxbuff_list); + + for (i = 0 ; i < aic_rxbuff_num_max ; i++) { + rxbuff = kzalloc(sizeof(struct rx_buff), GFP_KERNEL); + if (rxbuff) { + rxbuff->data = kzalloc(aic_rxbuff_size, GFP_KERNEL); + if (rxbuff->data == NULL) { + printk("failed to alloc rxbuff data\n"); + kfree(rxbuff); + continue; + } + rxbuff->len = 0; + rxbuff->start = NULL; + rxbuff->read = NULL; + rxbuff->end = NULL; + list_add_tail(&rxbuff->queue, &aic_rx_buff_list.rxbuff_list); + atomic_inc(&aic_rx_buff_list.rxbuff_list_len); + } + } + + printk("pre alloc rxbuff list len: %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); + return 0; +} + +void aicwf_prealloc_exit() +{ + struct rx_buff *rxbuff; + struct rx_buff *pos; + + printk("%s enter\n", __func__); + + printk("free pre alloc rxbuff list %d\n", (int)atomic_read(&aic_rx_buff_list.rxbuff_list_len)); + list_for_each_entry_safe(rxbuff, pos, &aic_rx_buff_list.rxbuff_list, queue) { + list_del_init(&rxbuff->queue); + kfree(rxbuff->data); + kfree(rxbuff); + } +} +#endif + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_rx_prealloc.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_rx_prealloc.h new file mode 100644 index 000000000000..64a494aeef16 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_rx_prealloc.h @@ -0,0 +1,24 @@ +#ifndef _AICWF_RX_PREALLOC_H_ +#define _AICWF_RX_PREALLOC_H_ + +#ifdef CONFIG_PREALLOC_RX_SKB +struct rx_buff { + struct list_head queue; + unsigned char *data; + u32 len; + uint8_t *start; + uint8_t *end; + uint8_t *read; +}; + +struct aicwf_rx_buff_list { + struct list_head rxbuff_list; + atomic_t rxbuff_list_len; +}; + +struct rx_buff *aicwf_prealloc_rxbuff_alloc(spinlock_t *lock); +void aicwf_prealloc_rxbuff_free(struct rx_buff *rxbuff, spinlock_t *lock); +int aicwf_prealloc_init(void); +void aicwf_prealloc_exit(void); +#endif +#endif /* _AICWF_RX_PREALLOC_H_ */
\ No newline at end of file diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c new file mode 100644 index 000000000000..53c9710dd690 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c @@ -0,0 +1,2509 @@ +/** + * aicwf_sdmmc.c + * + * SDIO function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <linux/mmc/sdio.h> +#include <linux/mmc/sdio_ids.h> +#include <linux/mmc/sdio_func.h> +#include <linux/mmc/card.h> +#include <linux/mmc/host.h> +#include <linux/semaphore.h> +#include <linux/debugfs.h> +#include <linux/kthread.h> +#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 <linux/pm_wakeirq.h> +#else +#include <linux/pm_wakeup.h> +#endif +#include "rwnx_wakelock.h" + +#ifdef CONFIG_INGENIC_T20 +#include "mach/jzmmc.h" +#endif /* CONFIG_INGENIC_T20 */ +#ifdef CONFIG_PLATFORM_ROCKCHIP +#include <linux/rfkill-wlan.h> +#endif +#ifdef CONFIG_PLATFORM_ROCKCHIP2 +#include <linux/rfkill-wlan.h> +#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 <linux/proc_fs.h> +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); + + +int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) +{ + int ret; + sdio_claim_host(sdiodev->func); + *val = sdio_readb(sdiodev->func, regaddr, &ret); + sdio_release_host(sdiodev->func); + return ret; +} + +int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) +{ + int ret; + sdio_claim_host(sdiodev->func); + sdio_writeb(sdiodev->func, val, regaddr, &ret); + sdio_release_host(sdiodev->func); + return ret; +} + +int aicwf_sdio_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 <linux/wakelock.h> +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 <linux/wakelock.h> +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 + wake_lock_init(&irq_wakelock, WAKE_LOCK_SUSPEND, "wifisleep"); +#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 + wake_lock_destroy(&irq_wakelock); +#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 + + #ifdef CONFIG_WIFI_SUSPEND_FOR_LINUX + rwnx_set_wifi_suspend('0'); + #endif//CONFIG_WIFI_SUSPEND_FOR_LINUX + + +// 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(); + + 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; + + 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); + } + } + } + + 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; + + 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; + } else { + ret = 0; + } + + 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) +{ + 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; + + 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); + + 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, 17, 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 <linux/sched.h> +#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; + } + + if (sdiodev->chipid == PRODUCT_ID_AIC8801 || sdiodev->chipid == PRODUCT_ID_AIC8800DC || + sdiodev->chipid == PRODUCT_ID_AIC8800DW) { + #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 + 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 + + 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__); + rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, 1); + aicwf_sdio_pwr_stctl(g_rwnx_plat->sdiodev, SDIO_SLEEP_ST); + ret = aicwf_sdio_writeb(g_rwnx_plat->sdiodev, SDIOWIFI_WAKEUP_REG, 2); + if (ret < 0) { + sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); + } + } +} + +static ssize_t rwnx_wifi_suspend_write_proc(struct file *file, + const char __user *buffer, + size_t count, loff_t *pos){ + char onoff; + + if (count < 1) + return -EINVAL; + + if (copy_from_user(&onoff, buffer, 1)) + return -EFAULT; + + rwnx_set_wifi_suspend(onoff); + + return count; +} + +static const struct file_operations wifi_suspend_fops = { + .owner = THIS_MODULE, + .write = rwnx_wifi_suspend_write_proc, +}; + +void rwnx_init_wifi_suspend_node(void){ + struct proc_dir_entry *ent; + + wifi_suspend_node = proc_mkdir("wifi_suspend", NULL); + if (wifi_suspend_node == NULL) { + printk("Unable to create /proc/wifi_suspend directory"); + } + + ent = proc_create("suspend", 0660, wifi_suspend_node, &wifi_suspend_fops); + if (ent == NULL) { + printk("Unable to create /proc/wifi_suspend/suspend"); + } +} + +void rwnx_deinit_wifi_suspend_node(void){ + remove_proc_entry("suspend", wifi_suspend_node); + remove_proc_entry("wifi_suspend", 0); +} +#endif//CONFIG_WIFI_SUSPEND_FOR_LINUX + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h new file mode 100644 index 000000000000..19ec8472d58b --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h @@ -0,0 +1,175 @@ +/** + * aicwf_sdio.h + * + * SDIO function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#ifndef _AICWF_SDMMC_H_ +#define _AICWF_SDMMC_H_ + +#ifdef AICWF_SDIO_SUPPORT +#include <linux/skbuff.h> +#include <linux/if_ether.h> +#include <linux/ieee80211.h> +#include <linux/semaphore.h> +#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 + +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; + + #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); +int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); +int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev); +#ifdef CONFIG_PREALLOC_RX_SKB +int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct rx_buff *rxbbuf, u32 size); +#else +int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size); +#endif +int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); +void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); +void aicwf_sdio_release(struct aic_sdio_dev *sdiodev); +void aicwf_sdio_exit(void); +void aicwf_sdio_register(void); +int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt); +int sdio_bustx_thread(void *data); +int sdio_busrx_thread(void *data); +#ifdef CONFIG_OOB +//new oob feature +int sdio_busirq_thread(void *data); +#endif //CONFIG_OOB +int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt); +int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv, u8 txnow); +void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv); +void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv); +extern void aicwf_hostif_ready(void); +extern void aicwf_hostif_fail(void); +#ifdef CONFIG_PLATFORM_AMLOGIC +extern void extern_wifi_set_enable(int is_on); +extern void sdio_reinit(void); +#endif /*CONFIG_PLATFORM_AMLOGIC*/ +uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size); + +#endif /* AICWF_SDIO_SUPPORT */ + +#endif /*_AICWF_SDMMC_H_*/ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_tcp_ack.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_tcp_ack.c new file mode 100644 index 000000000000..6d766bc75c10 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_tcp_ack.c @@ -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); + 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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_tcp_ack.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_tcp_ack.h new file mode 100644 index 000000000000..ff7f11d9103d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_tcp_ack.h @@ -0,0 +1,111 @@ +#ifndef _AICWF_TCP_ACK_H_ +#define _AICWF_TCP_ACK_H_ + +#include <uapi/linux/if_ether.h> +#include <uapi/linux/tcp.h> +#include <uapi/linux/ip.h> +#include <uapi/linux/in.h> +#include <linux/moduleparam.h> +#include <net/tcp.h> +#include <linux/timer.h> + + +#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;*/ + /* marlin 2 */ + /*unsigned int fifo_id; + struct sprdwl_msg_list *msglist;*/ + /* marlin 3 */ + /*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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c new file mode 100644 index 000000000000..47613d7c6cca --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c @@ -0,0 +1,885 @@ +/** + * aicwf_bus.c + * + * bus function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#include <linux/kthread.h> +#include <linux/netdevice.h> +#include <linux/printk.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/semaphore.h> +#include <linux/debugfs.h> +#include <linux/atomic.h> +#include <linux/vmalloc.h> +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.h new file mode 100644 index 000000000000..2a06442799b2 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.h @@ -0,0 +1,262 @@ +/** + * aicwf_txrxif.h + * + * bus function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#ifndef _AICWF_TXRXIF_H_ +#define _AICWF_TXRXIF_H_ + +#include <linux/skbuff.h> +#include <linux/sched.h> +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c new file mode 100644 index 000000000000..9344217c2256 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c @@ -0,0 +1,957 @@ +/** + * aicwf_usb.c + * + * USB function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#include <linux/usb.h> +#include <linux/kthread.h> +#include "aicwf_txrxif.h" +#include "aicwf_usb.h" +#include "rwnx_tx.h" +#include "rwnx_defs.h" +#include "usb_host.h" +#include "rwnx_platform.h" + +void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state) +{ + struct rwnx_vif *rwnx_vif; + list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { + if (!rwnx_vif->up) + continue; + if (!rwnx_vif->ndev) + continue; + if (state) + netif_stop_queue(rwnx_vif->ndev); + else + netif_wake_queue(rwnx_vif->ndev); + } +} + +static struct aicwf_usb_buf *aicwf_usb_tx_dequeue(struct aic_usb_dev *usb_dev, + struct list_head *q, int *counter, spinlock_t *qlock) +{ + unsigned long flags; + struct aicwf_usb_buf *usb_buf; + + spin_lock_irqsave(qlock, flags); + if (list_empty(q)) { + usb_buf = NULL; + } else { + usb_buf = list_first_entry(q, struct aicwf_usb_buf, list); + list_del_init(&usb_buf->list); + if (counter) + (*counter)--; + } + spin_unlock_irqrestore(qlock, flags); + return usb_buf; +} + +static void aicwf_usb_tx_queue(struct aic_usb_dev *usb_dev, + struct list_head *q, struct aicwf_usb_buf *usb_buf, int *counter, + spinlock_t *qlock) +{ + unsigned long flags; + + spin_lock_irqsave(qlock, flags); + list_add_tail(&usb_buf->list, q); + (*counter)++; + spin_unlock_irqrestore(qlock, flags); +} + +static struct aicwf_usb_buf *aicwf_usb_rx_buf_get(struct aic_usb_dev *usb_dev) +{ + unsigned long flags; + struct aicwf_usb_buf *usb_buf; + + spin_lock_irqsave(&usb_dev->rx_free_lock, flags); + if (list_empty(&usb_dev->rx_free_list)) { + usb_buf = NULL; + } else { + usb_buf = list_first_entry(&usb_dev->rx_free_list, struct aicwf_usb_buf, list); + list_del_init(&usb_buf->list); + } + spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); + return usb_buf; +} + +static void aicwf_usb_rx_buf_put(struct aic_usb_dev *usb_dev, struct aicwf_usb_buf *usb_buf) +{ + unsigned long flags; + + spin_lock_irqsave(&usb_dev->rx_free_lock, flags); + list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); + spin_unlock_irqrestore(&usb_dev->rx_free_lock, flags); +} + +static void aicwf_usb_tx_complete(struct urb *urb) +{ + unsigned long flags; + struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; + struct aic_usb_dev *usb_dev = usb_buf->usbdev; + struct sk_buff *skb; + u8 *buf; + + if (usb_buf->cfm == false) { + skb = usb_buf->skb; + } else { + buf = (u8 *)usb_buf->skb; + } + + if (usb_buf->cfm == false) { + dev_kfree_skb_any(skb); + } else { + kfree(buf); + } + usb_buf->skb = NULL; + + aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, + &usb_dev->tx_free_count, &usb_dev->tx_free_lock); + + spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); + if (usb_dev->tx_free_count > AICWF_USB_TX_HIGH_WATER) { + if (usb_dev->tbusy) { + usb_dev->tbusy = false; + aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, false); + } + } + spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); + } + +static void aicwf_usb_rx_complete(struct urb *urb) +{ + struct aicwf_usb_buf *usb_buf = (struct aicwf_usb_buf *) urb->context; + struct aic_usb_dev *usb_dev = usb_buf->usbdev; + struct aicwf_rx_priv *rx_priv = usb_dev->rx_priv; + struct sk_buff *skb = NULL; + unsigned long flags = 0; + + skb = usb_buf->skb; + usb_buf->skb = NULL; + + if (urb->actual_length > urb->transfer_buffer_length) { + aicwf_dev_skb_free(skb); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + schedule_work(&usb_dev->rx_urb_work); + return; + } + + if (urb->status != 0 || !urb->actual_length) { + aicwf_dev_skb_free(skb); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + schedule_work(&usb_dev->rx_urb_work); + return; + } + + if (usb_dev->state == USB_UP_ST) { + skb_put(skb, urb->actual_length); + + spin_lock_irqsave(&rx_priv->rxqlock, flags); + if (!aicwf_rxframe_enqueue(usb_dev->dev, &rx_priv->rxq, skb)) { + spin_unlock_irqrestore(&rx_priv->rxqlock, flags); + usb_err("rx_priv->rxq is over flow!!!\n"); + aicwf_dev_skb_free(skb); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + return; + } + spin_unlock_irqrestore(&rx_priv->rxqlock, flags); + atomic_inc(&rx_priv->rx_cnt); + complete(&rx_priv->usbdev->bus_if->busrx_trgg); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + + schedule_work(&usb_dev->rx_urb_work); + } else { + aicwf_dev_skb_free(skb); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + } +} + +static int aicwf_usb_submit_rx_urb(struct aic_usb_dev *usb_dev, + struct aicwf_usb_buf *usb_buf) +{ + struct sk_buff *skb; + int ret; + + if (!usb_buf || !usb_dev) + return -1; + + if (usb_dev->state != USB_UP_ST) { + usb_err("usb state is not up!\n"); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + return -1; + } + + skb = __dev_alloc_skb(AICWF_USB_MAX_PKT_SIZE, GFP_KERNEL); + if (!skb) { + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + return -1; + } + + usb_buf->skb = skb; + + usb_fill_bulk_urb(usb_buf->urb, + usb_dev->udev, + usb_dev->bulk_in_pipe, + skb->data, skb_tailroom(skb), aicwf_usb_rx_complete, usb_buf); + + usb_buf->usbdev = usb_dev; + + usb_anchor_urb(usb_buf->urb, &usb_dev->rx_submitted); + ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); + if (ret) { + usb_err("usb submit rx urb fail:%d\n", ret); + usb_unanchor_urb(usb_buf->urb); + aicwf_dev_skb_free(usb_buf->skb); + usb_buf->skb = NULL; + aicwf_usb_rx_buf_put(usb_dev, usb_buf); + + msleep(100); + } + return 0; +} + +static void aicwf_usb_rx_submit_all_urb(struct aic_usb_dev *usb_dev) +{ + struct aicwf_usb_buf *usb_buf; + + if (usb_dev->state != USB_UP_ST) { + usb_err("bus is not up=%d\n", usb_dev->state); + return; + } + + while ((usb_buf = aicwf_usb_rx_buf_get(usb_dev)) != NULL) { + if (aicwf_usb_submit_rx_urb(usb_dev, usb_buf)) { + usb_err("usb rx refill fail\n"); + if (usb_dev->state != USB_UP_ST) + return; + } + } +} + +static void aicwf_usb_rx_prepare(struct aic_usb_dev *usb_dev) +{ + aicwf_usb_rx_submit_all_urb(usb_dev); +} + +static void aicwf_usb_tx_prepare(struct aic_usb_dev *usb_dev) +{ + struct aicwf_usb_buf *usb_buf; + + while (!list_empty(&usb_dev->tx_post_list)) { + usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, + &usb_dev->tx_post_count, &usb_dev->tx_post_lock); + if (usb_buf->skb) { + dev_kfree_skb(usb_buf->skb); + usb_buf->skb = NULL; + } + aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, + &usb_dev->tx_free_count, &usb_dev->tx_free_lock); + } +} +static void aicwf_usb_tx_process(struct aic_usb_dev *usb_dev) +{ + struct aicwf_usb_buf *usb_buf; + int ret = 0; + u8 *data = NULL; + + while (!list_empty(&usb_dev->tx_post_list)) { + if (usb_dev->state != USB_UP_ST) { + usb_err("usb state is not up!\n"); + return; + } + + usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_post_list, + &usb_dev->tx_post_count, &usb_dev->tx_post_lock); + if (!usb_buf) { + usb_err("can not get usb_buf from tx_post_list!\n"); + return; + } + data = usb_buf->skb->data; + + ret = usb_submit_urb(usb_buf->urb, GFP_ATOMIC); + if (ret) { + usb_err("aicwf_usb_bus_tx usb_submit_urb FAILED\n"); + goto fail; + } + + continue; +fail: + dev_kfree_skb(usb_buf->skb); + usb_buf->skb = NULL; + aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_free_list, usb_buf, + &usb_dev->tx_free_count, &usb_dev->tx_free_lock); + } +} + +int usb_bustx_thread(void *data) +{ + struct aicwf_bus *bus = (struct aicwf_bus *)data; + struct aic_usb_dev *usbdev = bus->bus_priv.usb; + + while (1) { + if (kthread_should_stop()) { + usb_err("usb bustx thread stop\n"); + break; + } + if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { + if (usbdev->bus_if->state == BUS_DOWN_ST) + continue; + if (usbdev->tx_post_count > 0) + aicwf_usb_tx_process(usbdev); + } + } + + return 0; +} + +int usb_busrx_thread(void *data) +{ + struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; + struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; + + while (1) { + if (kthread_should_stop()) { + usb_err("usb busrx thread stop\n"); + break; + } + if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { + if (bus_if->state == BUS_DOWN_ST) + continue; + aicwf_process_rxframes(rx_priv); + } + } + + return 0; +} + +static void aicwf_usb_send_msg_complete(struct urb *urb) +{ + struct aic_usb_dev *usb_dev = (struct aic_usb_dev *) urb->context; + + usb_dev->msg_finished = true; + if (waitqueue_active(&usb_dev->msg_wait)) + wake_up(&usb_dev->msg_wait); +} + +static int aicwf_usb_bus_txmsg(struct device *dev, u8 *buf, u32 len) +{ + int ret = 0; + struct aicwf_bus *bus_if = dev_get_drvdata(dev); + struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; + + if (usb_dev->state != USB_UP_ST) + return -EIO; + + if (buf == NULL || len == 0 || usb_dev->msg_out_urb == NULL) + return -EINVAL; + + if (test_and_set_bit(0, &usb_dev->msg_busy)) { + usb_err("In a control frame option, can't tx!\n"); + return -EIO; + } + + usb_dev->msg_finished = false; + + usb_fill_bulk_urb(usb_dev->msg_out_urb, + usb_dev->udev, + usb_dev->bulk_out_pipe, + buf, len, (usb_complete_t) aicwf_usb_send_msg_complete, usb_dev); + usb_dev->msg_out_urb->transfer_flags |= URB_ZERO_PACKET; + + ret = usb_submit_urb(usb_dev->msg_out_urb, GFP_ATOMIC); + if (ret) { + usb_err("usb_submit_urb failed %d\n", ret); + goto exit; + } + + ret = wait_event_timeout(usb_dev->msg_wait, + usb_dev->msg_finished, msecs_to_jiffies(CMD_TX_TIMEOUT)); + if (!ret) { + if (usb_dev->msg_out_urb) + usb_kill_urb(usb_dev->msg_out_urb); + usb_err("Txmsg wait timed out\n"); + ret = -EIO; + goto exit; + } + + if (usb_dev->msg_finished == false) { + usb_err("Txmsg timed out\n"); + ret = -ETIMEDOUT; + goto exit; + } +exit: + clear_bit(0, &usb_dev->msg_busy); + return ret; +} + + +static void aicwf_usb_free_urb(struct list_head *q, spinlock_t *qlock) +{ + struct aicwf_usb_buf *usb_buf, *tmp; + unsigned long flags; + + spin_lock_irqsave(qlock, flags); + list_for_each_entry_safe(usb_buf, tmp, q, list) { + spin_unlock_irqrestore(qlock, flags); + if (!usb_buf->urb) { + usb_err("bad usb_buf\n"); + spin_lock_irqsave(qlock, flags); + break; + } + usb_free_urb(usb_buf->urb); + list_del_init(&usb_buf->list); + spin_lock_irqsave(qlock, flags); + } + spin_unlock_irqrestore(qlock, flags); +} + +static int aicwf_usb_alloc_rx_urb(struct aic_usb_dev *usb_dev) +{ + int i; + + for (i = 0; i < AICWF_USB_RX_URBS; i++) { + struct aicwf_usb_buf *usb_buf = &usb_dev->usb_rx_buf[i]; + + usb_buf->usbdev = usb_dev; + usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!usb_buf->urb) { + usb_err("could not allocate rx data urb\n"); + goto err; + } + list_add_tail(&usb_buf->list, &usb_dev->rx_free_list); + } + return 0; + +err: + aicwf_usb_free_urb(&usb_dev->rx_free_list, &usb_dev->rx_free_lock); + return -ENOMEM; +} + +static int aicwf_usb_alloc_tx_urb(struct aic_usb_dev *usb_dev) +{ + int i; + + for (i = 0; i < AICWF_USB_TX_URBS; i++) { + struct aicwf_usb_buf *usb_buf = &usb_dev->usb_tx_buf[i]; + + usb_buf->usbdev = usb_dev; + usb_buf->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!usb_buf->urb) { + usb_err("could not allocate tx data urb\n"); + goto err; + } + list_add_tail(&usb_buf->list, &usb_dev->tx_free_list); + (usb_dev->tx_free_count)++; + } + return 0; + +err: + aicwf_usb_free_urb(&usb_dev->tx_free_list, &usb_dev->tx_free_lock); + return -ENOMEM; +} + + +static void aicwf_usb_state_change(struct aic_usb_dev *usb_dev, int state) +{ + int old_state; + + if (usb_dev->state == state) + return; + + old_state = usb_dev->state; + usb_dev->state = state; + + if (state == USB_DOWN_ST) { + usb_dev->bus_if->state = BUS_DOWN_ST; + } + if (state == USB_UP_ST) { + usb_dev->bus_if->state = BUS_UP_ST; + } +} + +static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb) +{ + u8 *buf; + u16 buf_len = 0; + u16 adjust_len = 0; + struct aicwf_usb_buf *usb_buf; + int ret = 0; + unsigned long flags; + struct aicwf_bus *bus_if = dev_get_drvdata(dev); + struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; + struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)skb->data; + struct rwnx_hw *rwnx_hw = usb_dev->rwnx_hw; + u8 usb_header[4]; + u8 adj_buf[4] = {0}; + u16 index = 0; + bool need_cfm = false; + + if (usb_dev->state != USB_UP_ST) { + usb_err("usb state is not up!\n"); + kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); + dev_kfree_skb_any(skb); + return -EIO; + } + + usb_buf = aicwf_usb_tx_dequeue(usb_dev, &usb_dev->tx_free_list, + &usb_dev->tx_free_count, &usb_dev->tx_free_lock); + if (!usb_buf) { + usb_err("free:%d, post:%d\n", usb_dev->tx_free_count, usb_dev->tx_post_count); + kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); + dev_kfree_skb_any(skb); + ret = -ENOMEM; + goto flow_ctrl; + } + + if (txhdr->sw_hdr->need_cfm) { + need_cfm = true; + buf = kmalloc(skb->len, GFP_KERNEL); + index += sizeof(usb_header); + memcpy(&buf[index], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); + index += sizeof(struct txdesc_api); + memcpy(&buf[index], &skb->data[txhdr->sw_hdr->headroom], skb->len - txhdr->sw_hdr->headroom); + index += skb->len - txhdr->sw_hdr->headroom; + buf_len = index; + if (buf_len & (TX_ALIGNMENT - 1)) { + adjust_len = roundup(buf_len, TX_ALIGNMENT)-buf_len; + memcpy(&buf[buf_len], adj_buf, adjust_len); + buf_len += adjust_len; + } + usb_header[0] = ((buf_len) & 0xff); + usb_header[1] = (((buf_len) >> 8)&0x0f); + usb_header[2] = 0x01; //data + usb_header[3] = 0; //reserved + memcpy(&buf[0], usb_header, sizeof(usb_header)); + usb_buf->skb = (struct sk_buff *)buf; + } else { + skb_pull(skb, txhdr->sw_hdr->headroom); + skb_push(skb, sizeof(struct txdesc_api)); + memcpy(&skb->data[0], (u8 *)(long)&txhdr->sw_hdr->desc, sizeof(struct txdesc_api)); + kmem_cache_free(rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); + + skb_push(skb, sizeof(usb_header)); + usb_header[0] = ((skb->len) & 0xff); + usb_header[1] = (((skb->len) >> 8)&0x0f); + usb_header[2] = 0x01; //data + usb_header[3] = 0; //reserved + memcpy(&skb->data[0], usb_header, sizeof(usb_header)); + + buf = skb->data; + buf_len = skb->len; + + usb_buf->skb = skb; + } + usb_buf->usbdev = usb_dev; + if (need_cfm) + usb_buf->cfm = true; + else + usb_buf->cfm = false; + usb_fill_bulk_urb(usb_buf->urb, usb_dev->udev, usb_dev->bulk_out_pipe, + buf, buf_len, aicwf_usb_tx_complete, usb_buf); + usb_buf->urb->transfer_flags |= URB_ZERO_PACKET; + + aicwf_usb_tx_queue(usb_dev, &usb_dev->tx_post_list, usb_buf, + &usb_dev->tx_post_count, &usb_dev->tx_post_lock); + complete(&bus_if->bustx_trgg); + ret = 0; + + flow_ctrl: + spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); + if (usb_dev->tx_free_count < AICWF_USB_TX_LOW_WATER) { + usb_dev->tbusy = true; + aicwf_usb_tx_flowctrl(usb_dev->rwnx_hw, true); + } + spin_unlock_irqrestore(&usb_dev->tx_flow_lock, flags); + + return ret; +} + +static int aicwf_usb_bus_start(struct device *dev) +{ + struct aicwf_bus *bus_if = dev_get_drvdata(dev); + struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; + + if (usb_dev->state == USB_UP_ST) + return 0; + + aicwf_usb_state_change(usb_dev, USB_UP_ST); + aicwf_usb_rx_prepare(usb_dev); + aicwf_usb_tx_prepare(usb_dev); + return 0; +} + +static void aicwf_usb_cancel_all_urbs(struct aic_usb_dev *usb_dev) +{ + struct aicwf_usb_buf *usb_buf, *tmp; + unsigned long flags; + + if (usb_dev->msg_out_urb) + usb_kill_urb(usb_dev->msg_out_urb); + + spin_lock_irqsave(&usb_dev->tx_post_lock, flags); + list_for_each_entry_safe(usb_buf, tmp, &usb_dev->tx_post_list, list) { + spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); + if (!usb_buf->urb) { + usb_err("bad usb_buf\n"); + spin_lock_irqsave(&usb_dev->tx_post_lock, flags); + break; + } + usb_kill_urb(usb_buf->urb); + spin_lock_irqsave(&usb_dev->tx_post_lock, flags); + } + spin_unlock_irqrestore(&usb_dev->tx_post_lock, flags); + + usb_kill_anchored_urbs(&usb_dev->rx_submitted); +} + +static void aicwf_usb_bus_stop(struct device *dev) +{ + struct aicwf_bus *bus_if = dev_get_drvdata(dev); + struct aic_usb_dev *usb_dev = bus_if->bus_priv.usb; + + usb_dbg("%s\r\n", __func__); + if (usb_dev == NULL) + return; + + if (usb_dev->state == USB_DOWN_ST) + return; + + aicwf_usb_state_change(usb_dev, USB_DOWN_ST); + aicwf_usb_cancel_all_urbs(usb_dev); +} + +static void aicwf_usb_deinit(struct aic_usb_dev *usbdev) +{ + cancel_work_sync(&usbdev->rx_urb_work); + aicwf_usb_free_urb(&usbdev->rx_free_list, &usbdev->rx_free_lock); + aicwf_usb_free_urb(&usbdev->tx_free_list, &usbdev->tx_free_lock); + usb_free_urb(usbdev->msg_out_urb); +} + +static void aicwf_usb_rx_urb_work(struct work_struct *work) +{ + struct aic_usb_dev *usb_dev = container_of(work, struct aic_usb_dev, rx_urb_work); + + aicwf_usb_rx_submit_all_urb(usb_dev); +} + +static int aicwf_usb_init(struct aic_usb_dev *usb_dev) +{ + int ret = 0; + + usb_dev->tbusy = false; + usb_dev->state = USB_DOWN_ST; + + init_waitqueue_head(&usb_dev->msg_wait); + init_usb_anchor(&usb_dev->rx_submitted); + + spin_lock_init(&usb_dev->tx_free_lock); + spin_lock_init(&usb_dev->tx_post_lock); + spin_lock_init(&usb_dev->rx_free_lock); + spin_lock_init(&usb_dev->tx_flow_lock); + + INIT_LIST_HEAD(&usb_dev->rx_free_list); + INIT_LIST_HEAD(&usb_dev->tx_free_list); + INIT_LIST_HEAD(&usb_dev->tx_post_list); + + usb_dev->tx_free_count = 0; + usb_dev->tx_post_count = 0; + + ret = aicwf_usb_alloc_rx_urb(usb_dev); + if (ret) { + goto error; + } + ret = aicwf_usb_alloc_tx_urb(usb_dev); + if (ret) { + goto error; + } + + + usb_dev->msg_out_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!usb_dev->msg_out_urb) { + usb_err("usb_alloc_urb (msg out) failed\n"); + ret = ENOMEM; + goto error; + } + + INIT_WORK(&usb_dev->rx_urb_work, aicwf_usb_rx_urb_work); + + return ret; + error: + usb_err("failed!\n"); + aicwf_usb_deinit(usb_dev); + return ret; +} + + +static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *interface) +{ + struct usb_interface_descriptor *interface_desc; + struct usb_host_interface *host_interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *usb = usb_dev->udev; + int i, endpoints; + u8 endpoint_num; + int ret = 0; + + usb_dev->bulk_in_pipe = 0; + usb_dev->bulk_out_pipe = 0; + + host_interface = &interface->altsetting[0]; + interface_desc = &host_interface->desc; + endpoints = interface_desc->bNumEndpoints; + + /* Check device configuration */ + if (usb->descriptor.bNumConfigurations != 1) { + usb_err("Number of configurations: %d not supported\n", + usb->descriptor.bNumConfigurations); + ret = -ENODEV; + goto exit; + } + + /* Check deviceclass */ +#ifndef CONFIG_USB_BT + if (usb->descriptor.bDeviceClass != 0x00) { + usb_err("DeviceClass %d not supported\n", + usb->descriptor.bDeviceClass); + ret = -ENODEV; + goto exit; + } +#endif + + /* Check interface number */ +#ifdef CONFIG_USB_BT + if (usb->actconfig->desc.bNumInterfaces != 3) { +#else + if (usb->actconfig->desc.bNumInterfaces != 1) { +#endif + usb_err("Number of interfaces: %d not supported\n", + usb->actconfig->desc.bNumInterfaces); + ret = -ENODEV; + goto exit; + } + + if ((interface_desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) || + (interface_desc->bInterfaceSubClass != 0xff) || + (interface_desc->bInterfaceProtocol != 0xff)) { + usb_err("non WLAN interface %d: 0x%x:0x%x:0x%x\n", + interface_desc->bInterfaceNumber, interface_desc->bInterfaceClass, + interface_desc->bInterfaceSubClass, interface_desc->bInterfaceProtocol); + ret = -ENODEV; + goto exit; + } + + for (i = 0; i < endpoints; i++) { + endpoint = &host_interface->endpoint[i].desc; + endpoint_num = usb_endpoint_num(endpoint); + + if (usb_endpoint_dir_in(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (!usb_dev->bulk_in_pipe) { + usb_dev->bulk_in_pipe = usb_rcvbulkpipe(usb, endpoint_num); + } + } + + if (usb_endpoint_dir_out(endpoint) && + usb_endpoint_xfer_bulk(endpoint)) { + if (!usb_dev->bulk_out_pipe) { + usb_dev->bulk_out_pipe = usb_sndbulkpipe(usb, endpoint_num); + } + } + } + + if (usb_dev->bulk_in_pipe == 0) { + usb_err("No RX (in) Bulk EP found\n"); + ret = -ENODEV; + goto exit; + } + if (usb_dev->bulk_out_pipe == 0) { + usb_err("No TX (out) Bulk EP found\n"); + ret = -ENODEV; + goto exit; + } + + if (usb->speed == USB_SPEED_HIGH) + printk("Aic high speed USB device detected\n"); + else + printk("Aic full speed USB device detected\n"); + + exit: + return ret; +} + + + +static struct aicwf_bus_ops aicwf_usb_bus_ops = { + .start = aicwf_usb_bus_start, + .stop = aicwf_usb_bus_stop, + .txdata = aicwf_usb_bus_txdata, + .txmsg = aicwf_usb_bus_txmsg, +}; + +static int aicwf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int ret = 0; + struct usb_device *usb = interface_to_usbdev(intf); + struct aicwf_bus *bus_if ; + struct device *dev = NULL; + struct aicwf_rx_priv *rx_priv = NULL; + struct aic_usb_dev *usb_dev = NULL; + + usb_dev = kzalloc(sizeof(struct aic_usb_dev), GFP_ATOMIC); + if (!usb_dev) { + return -ENOMEM; + } + + usb_dev->udev = usb; + usb_dev->dev = &usb->dev; + usb_set_intfdata(intf, usb_dev); + + ret = aicwf_parse_usb(usb_dev, intf); + if (ret) { + usb_err("aicwf_parse_usb err %d\n", ret); + goto out_free; + } + + ret = aicwf_usb_init(usb_dev); + if (ret) { + usb_err("aicwf_usb_init err %d\n", ret); + goto out_free; + } + + bus_if = kzalloc(sizeof(struct aicwf_bus), GFP_ATOMIC); + if (!bus_if) { + ret = -ENOMEM; + goto out_free_usb; + } + + dev = usb_dev->dev; + bus_if->dev = dev; + usb_dev->bus_if = bus_if; + bus_if->bus_priv.usb = usb_dev; + dev_set_drvdata(dev, bus_if); + + bus_if->ops = &aicwf_usb_bus_ops; + + rx_priv = aicwf_rx_init(usb_dev); + if (!rx_priv) { + txrx_err("rx init failed\n"); + ret = -1; + goto out_free_bus; + } + usb_dev->rx_priv = rx_priv; + + ret = aicwf_bus_init(0, dev); + if (ret < 0) { + usb_err("aicwf_bus_init err %d\n", ret); + goto out_free_bus; + } + + ret = aicwf_bus_start(bus_if); + if (ret < 0) { + usb_err("aicwf_bus_start err %d\n", ret); + goto out_free_bus; + } + + aicwf_rwnx_usb_platform_init(usb_dev); + aicwf_hostif_ready(); + return 0; + +out_free_bus: + aicwf_bus_deinit(dev); + kfree(bus_if); +out_free_usb: + aicwf_usb_deinit(usb_dev); +out_free: + usb_err("failed with errno %d\n", ret); + kfree(usb_dev); + usb_set_intfdata(intf, NULL); + return ret; +} + +static void aicwf_usb_disconnect(struct usb_interface *intf) +{ + struct aic_usb_dev *usb_dev = + (struct aic_usb_dev *) usb_get_intfdata(intf); + + if (!usb_dev) + return; + + aicwf_bus_deinit(usb_dev->dev); + aicwf_usb_deinit(usb_dev); + rwnx_cmd_mgr_deinit(&usb_dev->cmd_mgr); + + if (usb_dev->rx_priv) + aicwf_rx_deinit(usb_dev->rx_priv); + kfree(usb_dev->bus_if); + kfree(usb_dev); +} + +static int aicwf_usb_suspend(struct usb_interface *intf, pm_message_t state) +{ + struct aic_usb_dev *usb_dev = + (struct aic_usb_dev *) usb_get_intfdata(intf); + + aicwf_usb_state_change(usb_dev, USB_SLEEP_ST); + aicwf_bus_stop(usb_dev->bus_if); + return 0; +} + +static int aicwf_usb_resume(struct usb_interface *intf) +{ + struct aic_usb_dev *usb_dev = + (struct aic_usb_dev *) usb_get_intfdata(intf); + + if (usb_dev->state == USB_UP_ST) + return 0; + + aicwf_bus_start(usb_dev->bus_if); + return 0; +} + +static int aicwf_usb_reset_resume(struct usb_interface *intf) +{ + return aicwf_usb_resume(intf); +} + +static struct usb_device_id aicwf_usb_id_table[] = { +#ifndef CONFIG_USB_BT + {USB_DEVICE(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC)}, +#else + {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_AIC, USB_PRODUCT_ID_AIC, 0xff, 0xff, 0xff)}, +#endif + {} +}; + +MODULE_DEVICE_TABLE(usb, aicwf_usb_id_table); + +static struct usb_driver aicwf_usbdrvr = { + .name = KBUILD_MODNAME, + .probe = aicwf_usb_probe, + .disconnect = aicwf_usb_disconnect, + .id_table = aicwf_usb_id_table, + .suspend = aicwf_usb_suspend, + .resume = aicwf_usb_resume, + .reset_resume = aicwf_usb_reset_resume, + .supports_autosuspend = 1, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0) + .disable_hub_initiated_lpm = 1, +#endif +}; + +void aicwf_usb_register(void) +{ + if (usb_register(&aicwf_usbdrvr) < 0) { + usb_err("usb_register failed\n"); + } +} + +void aicwf_usb_exit(void) +{ + if (g_rwnx_plat && g_rwnx_plat->enabled) + rwnx_platform_deinit(g_rwnx_plat->usbdev->rwnx_hw); + usb_deregister(&aicwf_usbdrvr); + kfree(g_rwnx_plat); +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.h new file mode 100644 index 000000000000..cc3619b2dfe0 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.h @@ -0,0 +1,99 @@ +/** + * aicwf_usb.h + * + * USB function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + +#ifndef _AICWF_USB_H_ +#define _AICWF_USB_H_ + +#include <linux/usb.h> +#include "rwnx_cmds.h" + +#ifdef AICWF_USB_SUPPORT + +/* USB Device ID */ +#define USB_VENDOR_ID_AIC 0xA69C + +#ifndef CONFIG_USB_BT +#define USB_PRODUCT_ID_AIC 0x8800 +#else +#define USB_PRODUCT_ID_AIC 0x8801 +#endif + +#define AICWF_USB_RX_URBS (200) +#define AICWF_USB_TX_URBS (100) +#define AICWF_USB_TX_LOW_WATER (AICWF_USB_TX_URBS/4) +#define AICWF_USB_TX_HIGH_WATER (AICWF_USB_TX_LOW_WATER*3) +#define AICWF_USB_MAX_PKT_SIZE (2048) + +typedef enum { + USB_TYPE_DATA = 0X00, + USB_TYPE_CFG = 0X10, + USB_TYPE_CFG_CMD_RSP = 0X11, + USB_TYPE_CFG_DATA_CFM = 0X12 +} usb_type; + +enum aicwf_usb_state { + USB_DOWN_ST, + USB_UP_ST, + USB_SLEEP_ST +}; + +struct aicwf_usb_buf { + struct list_head list; + struct aic_usb_dev *usbdev; + struct urb *urb; + struct sk_buff *skb; + bool cfm; +}; + +struct aic_usb_dev { + struct rwnx_hw *rwnx_hw; + struct aicwf_bus *bus_if; + struct usb_device *udev; + struct device *dev; + struct aicwf_rx_priv *rx_priv; + enum aicwf_usb_state state; + struct rwnx_cmd_mgr cmd_mgr; + + struct usb_anchor rx_submitted; + struct work_struct rx_urb_work; + + spinlock_t rx_free_lock; + spinlock_t tx_free_lock; + spinlock_t tx_post_lock; + spinlock_t tx_flow_lock; + + struct list_head rx_free_list; + struct list_head tx_free_list; + struct list_head tx_post_list; + + uint bulk_in_pipe; + uint bulk_out_pipe; + + int tx_free_count; + int tx_post_count; + + struct aicwf_usb_buf usb_tx_buf[AICWF_USB_TX_URBS]; + struct aicwf_usb_buf usb_rx_buf[AICWF_USB_RX_URBS]; + + int msg_finished; + wait_queue_head_t msg_wait; + ulong msg_busy; + struct urb *msg_out_urb; + + bool tbusy; +}; + +extern void aicwf_usb_exit(void); +extern void aicwf_usb_register(void); +extern void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state); +int usb_bustx_thread(void *data); +int usb_busrx_thread(void *data); +extern void aicwf_hostif_ready(void); + +#endif /* AICWF_USB_SUPPORT */ +#endif /* _AICWF_USB_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/hal_desc.h b/drivers/net/wireless/aic8800/aic8800_fdrv/hal_desc.h new file mode 100644 index 000000000000..17cb02526282 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/hal_desc.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_compat.h b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_compat.h new file mode 100644 index 000000000000..069f69ee5ee0 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_compat.h @@ -0,0 +1,25 @@ +/** + **************************************************************************************** + * + * @file ipc_compat.h + * + * Copyright (C) RivieraWaves 2011-2019 + * + **************************************************************************************** + */ + +#ifndef _IPC_H_ +#define _IPC_H_ + +#define __INLINE inline + +#define __ALIGN4 __aligned(4) + +#define ASSERT_ERR(condition) \ + do { \ + if (unlikely(!(condition))) { \ + printk(KERN_ERR "%s:%d:ASSERT_ERR(" #condition ")\n", __FILE__, __LINE__); \ + } \ + } while (0) + +#endif /* _IPC_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_host.c b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_host.c new file mode 100644 index 000000000000..7746f4097976 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_host.c @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * + * @file ipc_host.c + * + * @brief IPC module. + * + * Copyright (C) RivieraWaves 2011-2019 + * + ****************************************************************************** + */ + +/* + * INCLUDE FILES + ****************************************************************************** + */ +#ifndef __KERNEL__ +#include <stdio.h> +#else +#include <linux/spinlock.h> +#include "rwnx_defs.h" +#include "rwnx_prof.h" +#endif + +#include "ipc_host.h" + +/* + * TYPES DEFINITION + ****************************************************************************** + */ + +const int nx_txdesc_cnt[] = { + NX_TXDESC_CNT0, + NX_TXDESC_CNT1, + NX_TXDESC_CNT2, + NX_TXDESC_CNT3, + #if NX_TXQ_CNT == 5 + NX_TXDESC_CNT4, + #endif +}; + +const int nx_txuser_cnt[] = { + CONFIG_USER_MAX, + CONFIG_USER_MAX, + CONFIG_USER_MAX, + CONFIG_USER_MAX, + #if NX_TXQ_CNT == 5 + 1, + #endif +}; + + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_host.h b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_host.h new file mode 100644 index 000000000000..583b66889aa4 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_host.h @@ -0,0 +1,168 @@ +/** + ****************************************************************************** + * + * @file ipc_host.h + * + * @brief IPC module. + * + * Copyright (C) RivieraWaves 2011-2019 + * + ****************************************************************************** + */ +#ifndef _IPC_HOST_H_ +#define _IPC_HOST_H_ + +/* + * INCLUDE FILES + ****************************************************************************** + */ +#include "ipc_shared.h" +#ifndef __KERNEL__ +#include "arch.h" +#else +#include "ipc_compat.h" +#endif + +/** + ****************************************************************************** + * @brief This structure is used to initialize the MAC SW + * + * The WLAN device driver provides functions call-back with this structure + ****************************************************************************** + */ +struct ipc_host_cb_tag { + /// WLAN driver call-back function: send_data_cfm + int (*send_data_cfm)(void *pthis, void *host_id); + + /// WLAN driver call-back function: recv_data_ind + uint8_t (*recv_data_ind)(void *pthis, void *host_id); + + /// WLAN driver call-back function: recv_radar_ind + uint8_t (*recv_radar_ind)(void *pthis, void *host_id); + + /// WLAN driver call-back function: recv_unsup_rx_vec_ind + uint8_t (*recv_unsup_rx_vec_ind)(void *pthis, void *host_id); + + /// WLAN driver call-back function: recv_msg_ind + uint8_t (*recv_msg_ind)(void *pthis, void *host_id); + + /// WLAN driver call-back function: recv_msgack_ind + uint8_t (*recv_msgack_ind)(void *pthis, void *host_id); + + /// WLAN driver call-back function: recv_dbg_ind + uint8_t (*recv_dbg_ind)(void *pthis, void *host_id); + + /// WLAN driver call-back function: prim_tbtt_ind + void (*prim_tbtt_ind)(void *pthis); + + /// WLAN driver call-back function: sec_tbtt_ind + void (*sec_tbtt_ind)(void *pthis); + +}; + +/* + * Struct used to store information about host buffers (DMA Address and local pointer) + */ +struct ipc_hostbuf { + void *hostid; ///< ptr to hostbuf client (ipc_host client) structure + uint32_t dma_addr; ///< ptr to real hostbuf dma address +}; + +/// Definition of the IPC Host environment structure. +struct ipc_host_env_tag { + /// Structure containing the callback pointers + struct ipc_host_cb_tag cb; + + /// Pointer to the shared environment + struct ipc_shared_env_tag *shared; + + #ifdef CONFIG_RWNX_FULLMAC + // Array used to store the descriptor addresses + struct ipc_hostbuf ipc_host_rxdesc_array[IPC_RXDESC_CNT]; + // Index of the host RX descriptor array (ipc_shared environment) + uint8_t ipc_host_rxdesc_idx; + /// Store the number of RX Descriptors + uint8_t rxdesc_nb; + #endif //(CONFIG_RWNX_FULLMAC) + + /// Fields for Data Rx handling + // Index used for ipc_host_rxbuf_array to point to current buffer + uint8_t ipc_host_rxbuf_idx; + // Store the number of Rx Data buffers + uint32_t rx_bufnb; + // Store the size of the Rx Data buffers + uint32_t rx_bufsz; + + /// Fields for Radar events handling + // Global array used to store the hostid and hostbuf addresses + struct ipc_hostbuf ipc_host_radarbuf_array[IPC_RADARBUF_CNT]; + // Index used for ipc_host_rxbuf_array to point to current buffer + uint8_t ipc_host_radarbuf_idx; + // Store the number of radar event buffers + uint32_t radar_bufnb; + // Store the size of the radar event buffers + uint32_t radar_bufsz; + + ///Fields for Unsupported frame handling + // Global array used to store the hostid and hostbuf addresses + struct ipc_hostbuf ipc_host_unsuprxvecbuf_array[IPC_UNSUPRXVECBUF_CNT]; + // Index used for ipc_host_unsuprxvecbuf_array to point to current buffer + uint8_t ipc_host_unsuprxvecbuf_idx; + // Store the number of unsupported rx vector buffers + uint32_t unsuprxvec_bufnb; + // Store the size of unsupported rx vector buffers + uint32_t unsuprxvec_bufsz; + + // Index used that points to the first free TX desc + uint32_t txdesc_free_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; + // Index used that points to the first used TX desc + uint32_t txdesc_used_idx[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; + // Array storing the currently pushed host ids for the BK queue + void *tx_host_id0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; + // Array storing the currently pushed host ids for the BE queue + void *tx_host_id1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; + // Array storing the currently pushed host ids for the VI queue + void *tx_host_id2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; + // Array storing the currently pushed host ids for the VO queue + void *tx_host_id3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; + #if NX_TXQ_CNT == 5 + // Array storing the currently pushed host ids for the BCN queue + void *tx_host_id4[1][NX_TXDESC_CNT4]; + #endif + // Pointer to the different host ids arrays, per IPC queue + void **tx_host_id[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; + // Pointer to the different TX descriptor arrays, per IPC queue + volatile struct txdesc_host *txdesc[IPC_TXQUEUE_CNT][CONFIG_USER_MAX]; + + /// Fields for Emb->App MSGs handling + // Global array used to store the hostid and hostbuf addresses for msg/ind + struct ipc_hostbuf ipc_host_msgbuf_array[IPC_MSGE2A_BUF_CNT]; + // Index of the MSG E2A buffers array to point to current buffer + uint8_t ipc_host_msge2a_idx; + // Store the number of E2A MSG buffers + uint32_t ipc_e2amsg_bufnb; + // Store the size of the E2A MSG buffers + uint32_t ipc_e2amsg_bufsz; + + /// E2A ACKs of A2E MSGs + uint8_t msga2e_cnt; + void *msga2e_hostid; + + /// Fields for Debug MSGs handling + // Global array used to store the hostid and hostbuf addresses for Debug messages + struct ipc_hostbuf ipc_host_dbgbuf_array[IPC_DBGBUF_CNT]; + // Index of the Debug messages buffers array to point to current buffer + uint8_t ipc_host_dbg_idx; + // Store the number of Debug messages buffers + uint32_t ipc_dbg_bufnb; + // Store the size of the Debug messages buffers + uint32_t ipc_dbg_bufsz; + + /// Pointer to the attached object (used in callbacks and register accesses) + void *pthis; +}; + +extern const int nx_txdesc_cnt[]; +extern const int nx_txuser_cnt[]; + +#endif // _IPC_HOST_H_ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h new file mode 100644 index 000000000000..7e2fedcb1b53 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h @@ -0,0 +1,785 @@ +/** + **************************************************************************************** + * + * @file ipc_shared.h + * + * @brief Shared data between both IPC modules. + * + * Copyright (C) RivieraWaves 2011-2019 + * + **************************************************************************************** + */ + +#ifndef _IPC_SHARED_H_ +#define _IPC_SHARED_H_ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "ipc_compat.h" +#include "lmac_mac.h" + +/* + * DEFINES AND MACROS + **************************************************************************************** + */ +#define CO_BIT(pos) (1U<<(pos)) + +#define IPC_TXQUEUE_CNT NX_TXQ_CNT +#define NX_TXDESC_CNT0 8 +#define NX_TXDESC_CNT1 64 +#define NX_TXDESC_CNT2 64 +#define NX_TXDESC_CNT3 32 +#if NX_TXQ_CNT == 5 +#define NX_TXDESC_CNT4 8 +#endif + +/* + * Number of Host buffers available for Data Rx handling (through DMA) + */ +#define IPC_RXBUF_CNT 128 + +/* + * Number of shared descriptors available for Data RX handling + */ +#define IPC_RXDESC_CNT 128 + +/* + * Number of Host buffers available for Radar events handling (through DMA) + */ +#define IPC_RADARBUF_CNT 16 + +/* + * Number of Host buffers available for unsupported Rx vectors handling (through DMA) + */ +#define IPC_UNSUPRXVECBUF_CNT 8 + +/* + * Size of RxVector + */ +#define IPC_RXVEC_SIZE 16 + +/* + * Number of Host buffers available for Emb->App MSGs sending (through DMA) + */ +#ifdef CONFIG_RWNX_FULLMAC +#define IPC_MSGE2A_BUF_CNT 64 +#endif +/* + * Number of Host buffers available for Debug Messages sending (through DMA) + */ +#define IPC_DBGBUF_CNT 32 + +/* + * Length used in MSGs structures + */ +#define IPC_A2E_MSG_BUF_SIZE 127 // size in 4-byte words +#ifdef CONFIG_RWNX_FULLMAC +#define IPC_E2A_MSG_SIZE_BASE 256 // size in 4-byte words +#endif + +#ifdef CONFIG_RWNX_TL4 +#define IPC_E2A_MSG_PARAM_SIZE (IPC_E2A_MSG_SIZE_BASE + (IPC_E2A_MSG_SIZE_BASE / 2)) +#else +#define IPC_E2A_MSG_PARAM_SIZE IPC_E2A_MSG_SIZE_BASE +#endif + +/* + * Debug messages buffers size (in bytes) + */ +#define IPC_DBG_PARAM_SIZE 256 + +/* + * Define used for Rx hostbuf validity. + * This value should appear only when hostbuf was used for a Reception. + */ +#define RX_DMA_OVER_PATTERN 0xAAAAAA00 + +/* + * Define used for MSG buffers validity. + * This value will be written only when a MSG buffer is used for sending from Emb to App. + */ +#define IPC_MSGE2A_VALID_PATTERN 0xADDEDE2A + +/* + * Define used for Debug messages buffers validity. + * This value will be written only when a DBG buffer is used for sending from Emb to App. + */ +#define IPC_DBG_VALID_PATTERN 0x000CACA0 + +/* + * Length of the receive vectors, in bytes + */ +#define DMA_HDR_PHYVECT_LEN 36 + +/* + * Maximum number of payload addresses and lengths present in the descriptor + */ +#ifdef CONFIG_RWNX_SPLIT_TX_BUF +#define NX_TX_PAYLOAD_MAX 6 +#else +#define NX_TX_PAYLOAD_MAX 1 +#endif + +/* + * Message struct/ID API version + */ +#define MSG_API_VER 33 + +/* + **************************************************************************************** + */ +// c.f LMAC/src/tx/tx_swdesc.h +/// Descriptor filled by the Host +struct hostdesc { + /// Pointer to packet payload + //u32_l packet_addr; + /// Size of the payload + u16_l packet_len; + u16_l flags_ext; + + u32_l hostid; +#ifdef CONFIG_RWNX_FULLMAC + /// Address of the status descriptor in host memory (used for confirmation upload) + //u32_l status_desc_addr; + /// Destination Address + struct mac_addr eth_dest_addr; + /// Source Address + struct mac_addr eth_src_addr; + /// Ethernet Type + u16_l ethertype; +#else /* ! CONFIG_RWNX_FULLMAC */ +#ifdef CONFIG_RWNX_AGG_TX + ///Sequence Number for AMPDU MPDUs - for quick check if it's allowed within window + u16_l sn; +#endif /* CONFIG_RWNX_AGG_TX */ + /// Padding between the buffer control structure and the MPDU in host memory + u8_l padding; +#endif /* CONFIG_RWNX_FULLMAC */ + u8_l ac; + /// Packet TID (0xFF if not a QoS frame) + u8_l tid; + /// Interface Id + u8_l vif_idx; + /// Station Id (0xFF if station is unknown) + u8_l staid; +#ifdef CONFIG_RWNX_MUMIMO_TX + /// MU-MIMO information (GroupId and User Position in the group) - The GroupId + /// is located on bits 0-5 and the User Position on bits 6-7. The GroupId value is set + /// to 63 if MU-MIMO shall not be used + u8_l mumimo_info; +#endif /* CONFIG_RWNX_MUMIMO_TX */ +#ifdef CONFIG_RWNX_FULLMAC + /// TX flags + u16_l flags; +#endif /* CONFIG_RWNX_FULLMAC */ +}; + +/// Descriptor filled by the UMAC +struct umacdesc { +#ifdef CONFIG_RWNX_AGG_TX + ///First Sequence Number of the BlockAck window + u16_l sn_win; + /// Flags from UMAC (match tx_hd.macctrlinfo2 format) + u32_l flags; + /// PHY related flags field - rate, GI type, BW type - filled by driver + u32_l phy_flags; +#endif //(CONFIG_RWNX_AGG_TX) +}; + +struct txdesc_api { + /// Information provided by Host + struct hostdesc host; +}; + + +struct txdesc_host { + u32_l ready; + + /// API of the embedded part + struct txdesc_api api; +}; + +/// Comes from ipc_dma.h +/// Element in the pool of TX DMA bridge descriptors. +struct dma_desc { + /** Application subsystem address which is used as source address for DMA payload + * transfer*/ + u32_l src; + /** Points to the start of the embedded data buffer associated with this descriptor. + * This address acts as the destination address for the DMA payload transfer*/ + u32_l dest; + /// Complete length of the buffer in memory + u16_l length; + /// Control word for the DMA engine (e.g. for interrupt generation) + u16_l ctrl; + /// Pointer to the next element of the chained list + u32_l next; +}; + +// Comes from la.h +/// Length of the configuration data of a logic analyzer +#define LA_CONF_LEN 10 + +/// Structure containing the configuration data of a logic analyzer +struct la_conf_tag { + u32_l conf[LA_CONF_LEN]; + u32_l trace_len; + u32_l diag_conf; +}; + +/// Size of a logic analyzer memory +#define LA_MEM_LEN (1024 * 1024) + +/// Type of errors +enum { + /// Recoverable error, not requiring any action from Upper MAC + DBG_ERROR_RECOVERABLE = 0, + /// Fatal error, requiring Upper MAC to reset Lower MAC and HW and restart operation + DBG_ERROR_FATAL +}; + +/// Maximum length of the SW diag trace +#define DBG_SW_DIAG_MAX_LEN 1024 + +/// Maximum length of the error trace +#define DBG_ERROR_TRACE_SIZE 256 + +/// Number of MAC diagnostic port banks +#define DBG_DIAGS_MAC_MAX 48 + +/// Number of PHY diagnostic port banks +#define DBG_DIAGS_PHY_MAX 32 + +/// Maximum size of the RX header descriptor information in the debug dump +#define DBG_RHD_MEM_LEN (5 * 1024) + +/// Maximum size of the RX buffer descriptor information in the debug dump +#define DBG_RBD_MEM_LEN (5 * 1024) + +/// Maximum size of the TX header descriptor information in the debug dump +#define DBG_THD_MEM_LEN (10 * 1024) + +/// Structure containing the information about the PHY channel that is used +struct phy_channel_info { + /// PHY channel information 1 + u32_l info1; + /// PHY channel information 2 + u32_l info2; +}; + +/// Debug information forwarded to host when an error occurs +struct dbg_debug_info_tag { + /// Type of error (0: recoverable, 1: fatal) + u32_l error_type; + /// Pointer to the first RX Header Descriptor chained to the MAC HW + u32_l rhd; + /// Size of the RX header descriptor buffer + u32_l rhd_len; + /// Pointer to the first RX Buffer Descriptor chained to the MAC HW + u32_l rbd; + /// Size of the RX buffer descriptor buffer + u32_l rbd_len; + /// Pointer to the first TX Header Descriptors chained to the MAC HW + u32_l thd[NX_TXQ_CNT]; + /// Size of the TX header descriptor buffer + u32_l thd_len[NX_TXQ_CNT]; + /// MAC HW diag configuration + u32_l hw_diag; + /// Error message + u32_l error[DBG_ERROR_TRACE_SIZE/4]; + /// SW diag configuration length + u32_l sw_diag_len; + /// SW diag configuration + u32_l sw_diag[DBG_SW_DIAG_MAX_LEN/4]; + /// PHY channel information + struct phy_channel_info chan_info; + /// Embedded LA configuration + struct la_conf_tag la_conf; + /// MAC diagnostic port state + u16_l diags_mac[DBG_DIAGS_MAC_MAX]; + /// PHY diagnostic port state + u16_l diags_phy[DBG_DIAGS_PHY_MAX]; + /// MAC HW RX Header descriptor pointer + u32_l rhd_hw_ptr; + /// MAC HW RX Buffer descriptor pointer + u32_l rbd_hw_ptr; +}; + +/// Full debug dump that is forwarded to host in case of error +struct dbg_debug_dump_tag { + /// Debug information + struct dbg_debug_info_tag dbg_info; + + /// RX header descriptor memory + u32_l rhd_mem[DBG_RHD_MEM_LEN/4]; + + /// RX buffer descriptor memory + u32_l rbd_mem[DBG_RBD_MEM_LEN/4]; + + /// TX header descriptor memory + u32_l thd_mem[NX_TXQ_CNT][DBG_THD_MEM_LEN/4]; + + /// Logic analyzer memory + u32_l la_mem[LA_MEM_LEN/4]; +}; + + +/// Number of pulses in a radar event structure +#define RADAR_PULSE_MAX 4 + +/// Definition of an array of radar pulses +struct radar_pulse_array_desc { + /// Buffer containing the radar pulses + u32_l pulse[RADAR_PULSE_MAX]; + /// Index of the radar detection chain that detected those pulses + u32_l idx; + /// Number of valid pulses in the buffer + u32_l cnt; +}; + +/// Bit mapping inside a radar pulse element +struct radar_pulse { + s32_l freq:6; /** Freq (resolution is 2Mhz range is [-Fadc/4 .. Fadc/4]) */ + u32_l fom:4; /** Figure of Merit */ + u32_l len:6; /** Length of the current radar pulse (resolution is 2us) */ + u32_l rep:16; /** Time interval between the previous radar event + and the current one (in us) */ +}; + +/// Definition of a RX vector descriptor +struct rx_vector_desc { + /// PHY channel information + struct phy_channel_info phy_info; + + /// RX vector 1 + u32_l rx_vect1[IPC_RXVEC_SIZE/4]; + + /// Used to print a valid rx vector + u32_l pattern; +}; + +/// +struct rxdesc_tag { + /// Host Buffer Address + u32_l host_id; + /// Length + u32_l frame_len; + /// Status + u16_l status; +}; + +/** + **************************************************************************************** + * @defgroup IPC IPC + * @ingroup NXMAC + * @brief Inter Processor Communication module. + * + * The IPC module implements the protocol to communicate between the Host CPU + * and the Embedded CPU. + * + * @see http://en.wikipedia.org/wiki/Circular_buffer + * For more information about the ring buffer typical use and difficulties. + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @addtogroup IPC_TX IPC Tx path + * @ingroup IPC + * @brief IPC Tx path structures and functions + * + * A typical use case of the IPC Tx path API: + * @msc + * hscale = "2"; + * + * a [label=Driver], + * b [label="IPC host"], + * c [label="IPC emb"], + * d [label=Firmware]; + * + * --- [label="Tx descriptor queue example"]; + * a=>a [label="Driver receives a Tx packet from OS"]; + * a=>b [label="ipc_host_txdesc_get()"]; + * a<<b [label="struct txdesc_host *"]; + * 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="Tx desc queue to pop"]; + * 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<<b [label="struct ipc_txcfm"]; + * a<=a [label="Packets are freed by the driver"]; + * @endmsc + * + * @{ + **************************************************************************************** + */ + +/// @} IPC_TX + +/** + **************************************************************************************** + * @defgroup IPC_RX IPC Rx path + * @ingroup IPC + * @brief IPC Rx path functions and structures + * + * A typical use case of the IPC Rx path API: + * @msc + * hscale = "2"; + * + * a [label=Firmware], + * b [label="IPC emb"], + * c [label="IPC host"], + * d [label=Driver]; + * + * --- [label="Rx buffer and desc queues usage example"]; + * 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)"]; + * a=>a [label=" Frame is received\n from the medium"]; + * a<<b [label="struct ipc_rxbuf"]; + * a=>a [label=" Firmware fill the buffer\n with received frame"]; + * a<<b [label="Push accepted"]; + * ... [label="(several Rx desc can be pushed)"]; + * b:>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<<b [label="struct ipc_rxbuf"]; + * c=>>d [label="Driver Rx buffer callback"]; + * d=>c [label="ipc_host_rxbuf_push()"]; + * d=>c [label="ipc_host_rxbuf_push()"]; + * d=>c [label="ipc_host_rxbuf_push()"]; + * ... [label="(several Rx buffer are pushed)"]; + * @endmsc + * + * @addtogroup IPC_RX + * @{ + **************************************************************************************** + */ + +/// @} IPC_RX + + + +/** + **************************************************************************************** + * @defgroup IPC_MISC IPC Misc + * @ingroup IPC + * @brief IPC miscellaneous functions + **************************************************************************************** + */ +/** IPC header structure. This structure is stored at the beginning of every IPC message. + * @warning This structure's size must NOT exceed 4 bytes in length. + */ +struct ipc_header { + /// IPC message type. + u16_l type; + /// IPC message size in number of bytes. + u16_l size; +}; + +struct ipc_msg_elt { + /// Message header (alignment forced on word size, see allocation in shared env). + struct ipc_header header __ALIGN4; +}; + +/// Message structure for MSGs from Emb to App +struct ipc_e2a_msg { + u16_l id; ///< Message id. + u16_l dummy_dest_id; + u16_l dummy_src_id; + u16_l param_len; ///< Parameter embedded struct length. + u32_l pattern; ///< Used to stamp a valid MSG buffer + u32_l param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. +}; + +/// Message structure for Debug messages from Emb to App +struct ipc_dbg_msg { + u32_l string[IPC_DBG_PARAM_SIZE/4]; ///< Debug string + u32_l pattern; ///< Used to stamp a valid buffer +}; + +/// Message structure for MSGs from App to Emb. +/// Actually a sub-structure will be used when filling the messages. +struct ipc_a2e_msg { + u32_l dummy_word; // used to cope with kernel message structure + u32_l msg[IPC_A2E_MSG_BUF_SIZE]; // body of the msg +}; + +struct ipc_shared_rx_buf { + /// < ptr to hostbuf client (ipc_host client) structure + u32_l hostid; + /// < ptr to real hostbuf dma address + u32_l dma_addr; +}; + +struct ipc_shared_rx_desc { + /// DMA Address + u32_l dma_addr; +}; + +/// Structure containing FW characteristics for compatibility checking +struct compatibility_tag { + /// Size of IPC shared memory + u16_l ipc_shared_size; + /// Message struct/ID API version + u16_l msg_api; + /// Version of IPC shared + u8_l ipc_shared_version; + /// Number of host buffers available for Emb->App MSGs sending + u8_l msge2a_buf_cnt; + /// Number of host buffers available for Debug Messages sending + u8_l dbgbuf_cnt; + /// Number of host buffers available for Radar events handling + u8_l radarbuf_cnt; + /// Number of host buffers available for unsupported Rx vectors handling + u8_l unsuprxvecbuf_cnt; + /// Number of shared descriptors available for Data RX handling + u8_l rxdesc_cnt; + /// Number of host buffers available for Data Rx handling + u8_l rxbuf_cnt; + /// Number of descriptors in BK TX queue (power of 2, min 4, max 64) + u8_l bk_txq; + /// Number of descriptors in BE TX queue (power of 2, min 4, max 64) + u8_l be_txq; + /// Number of descriptors in VI TX queue (power of 2, min 4, max 64) + u8_l vi_txq; + /// Number of descriptors in VO TX queue (power of 2, min 4, max 64) + u8_l vo_txq; + /// Number of descriptors in BCN TX queue (power of 2, min 4, max 64) + u8_l bcn_txq; +}; + +/* + * TYPE and STRUCT DEFINITIONS + **************************************************************************************** + */ + + +// Indexes are defined in the MIB shared structure +struct ipc_shared_env_tag { + volatile struct compatibility_tag comp_info; //FW characteristics + + volatile struct ipc_a2e_msg msg_a2e_buf; // room for MSG to be sent from App to Emb + + // Fields for MSGs sending from Emb to App + volatile struct ipc_e2a_msg msg_e2a_buf; // room to build the MSG to be DMA Xferred + volatile struct dma_desc msg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers + volatile u32_l msg_e2a_hostbuf_addr[IPC_MSGE2A_BUF_CNT]; // buffers @ for DMA Xfers + + // Fields for Debug MSGs sending from Emb to App + volatile struct ipc_dbg_msg dbg_buf; // room to build the MSG to be DMA Xferred + volatile struct dma_desc dbg_dma_desc; // DMA descriptor for Emb->App MSGs Xfers + volatile u32_l dbg_hostbuf_addr[IPC_DBGBUF_CNT]; // buffers @ for MSGs DMA Xfers + volatile u32_l la_dbginfo_addr; // Host buffer address for the debug information + volatile u32_l pattern_addr; + volatile u32_l radarbuf_hostbuf[IPC_RADARBUF_CNT]; // buffers @ for Radar Events + volatile u32_l unsuprxvecbuf_hostbuf[IPC_UNSUPRXVECBUF_CNT]; // buffers @ for unsupported Rx vectors + volatile struct txdesc_host txdesc0[CONFIG_USER_MAX][NX_TXDESC_CNT0]; + volatile struct txdesc_host txdesc1[CONFIG_USER_MAX][NX_TXDESC_CNT1]; + volatile struct txdesc_host txdesc2[CONFIG_USER_MAX][NX_TXDESC_CNT2]; + volatile struct txdesc_host txdesc3[CONFIG_USER_MAX][NX_TXDESC_CNT3]; + #if NX_TXQ_CNT == 5 + volatile struct txdesc_host txdesc4[1][NX_TXDESC_CNT4]; + #endif + #ifdef CONFIG_RWNX_FULLMAC + // RX Descriptors Array + volatile struct ipc_shared_rx_desc host_rxdesc[IPC_RXDESC_CNT]; + // RX Buffers Array + volatile struct ipc_shared_rx_buf host_rxbuf[IPC_RXBUF_CNT]; + #else + // buffers @ for Data Rx + volatile u32_l host_rxbuf[IPC_RXBUF_CNT]; + #endif /* CONFIG_RWNX_FULLMAC */ + + u32_l buffered[NX_REMOTE_STA_MAX][TID_MAX]; + + volatile uint16_t trace_pattern; + volatile uint32_t trace_start; + volatile uint32_t trace_end; + volatile uint32_t trace_size; + volatile uint32_t trace_offset; + volatile uint32_t trace_nb_compo; + volatile uint32_t trace_offset_compo; +}; + +extern struct ipc_shared_env_tag ipc_shared_env; + + +/* + * TYPE and STRUCT DEFINITIONS + **************************************************************************************** + */ + +// IRQs from app to emb +/// Interrupts bits used for the TX descriptors of the AC queues +#ifdef CONFIG_RWNX_MUMIMO_TX +#ifdef CONFIG_RWNX_OLD_IPC +#error "MU-MIMO cannot be compiled for old IPC" +#endif +/// Interrupts bits used +#if CONFIG_USER_MAX > 3 +#define IPC_IRQ_A2E_USER_MSK 0xF +#elif CONFIG_USER_MAX > 2 +#define IPC_IRQ_A2E_USER_MSK 0x7 +#else +#define IPC_IRQ_A2E_USER_MSK 0x3 +#endif + +/// Offset of the interrupts for AC0 +#define IPC_IRQ_A2E_AC0_OFT 8 +/// Mask of the interrupts for AC0 +#define IPC_IRQ_A2E_AC0_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC0_OFT) +/// Offset of the interrupts for AC1 +#define IPC_IRQ_A2E_AC1_OFT (IPC_IRQ_A2E_AC0_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for AC1 +#define IPC_IRQ_A2E_AC1_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC1_OFT) +/// Offset of the interrupts for AC2 +#define IPC_IRQ_A2E_AC2_OFT (IPC_IRQ_A2E_AC1_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for AC2 +#define IPC_IRQ_A2E_AC2_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC2_OFT) +/// Offset of the interrupts for AC3 +#define IPC_IRQ_A2E_AC3_OFT (IPC_IRQ_A2E_AC2_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for AC3 +#define IPC_IRQ_A2E_AC3_MSK (IPC_IRQ_A2E_USER_MSK << IPC_IRQ_A2E_AC3_OFT) +/// Offset of the interrupts for BCN +#define IPC_IRQ_A2E_BCN_OFT (IPC_IRQ_A2E_AC3_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for BCN +#define IPC_IRQ_A2E_BCN_MSK CO_BIT(IPC_IRQ_A2E_BCN_OFT) + +#define IPC_IRQ_A2E_AC_TXDESC (IPC_IRQ_A2E_AC0_MSK | IPC_IRQ_A2E_AC1_MSK | \ + IPC_IRQ_A2E_AC2_MSK | IPC_IRQ_A2E_AC3_MSK) + +/// Interrupts bits used for the TX descriptors of the BCN queue +#if NX_TXQ_CNT < 5 +#define IPC_IRQ_A2E_BCN_TXDESC 0 +#else +#define IPC_IRQ_A2E_BCN_TXDESC (0x01 << IPC_IRQ_A2E_BCN_OFT) +#endif + +/// IPC TX descriptor interrupt mask +#define IPC_IRQ_A2E_TXDESC (IPC_IRQ_A2E_AC_TXDESC | IPC_IRQ_A2E_BCN_TXDESC) +#else +/// IPC TX descriptor interrupt mask +#define IPC_IRQ_A2E_TXDESC 0xFF00 +#endif + +#define IPC_IRQ_A2E_TXDESC_FIRSTBIT (8) +#define IPC_IRQ_A2E_RXBUF_BACK CO_BIT(5) +#define IPC_IRQ_A2E_RXDESC_BACK CO_BIT(4) + +#define IPC_IRQ_A2E_MSG CO_BIT(1) +#define IPC_IRQ_A2E_DBG CO_BIT(0) + +#define IPC_IRQ_A2E_ALL (IPC_IRQ_A2E_TXDESC|IPC_IRQ_A2E_MSG|IPC_IRQ_A2E_DBG) + +// IRQs from emb to app +#define IPC_IRQ_E2A_TXCFM_POS 7 + +#ifdef CONFIG_RWNX_MUMIMO_TX +#ifdef CONFIG_RWNX_OLD_IPC +#error "MU-MIMO cannot be compiled for old IPC" +#endif +/// Interrupts bits used +#if CONFIG_USER_MAX > 3 +#define IPC_IRQ_E2A_USER_MSK 0xF +#elif CONFIG_USER_MAX > 2 +#define IPC_IRQ_E2A_USER_MSK 0x7 +#else +#define IPC_IRQ_E2A_USER_MSK 0x3 +#endif + +/// Offset of the interrupts for AC0 +#define IPC_IRQ_E2A_AC0_OFT IPC_IRQ_E2A_TXCFM_POS +/// Mask of the interrupts for AC0 +#define IPC_IRQ_E2A_AC0_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC0_OFT) +/// Offset of the interrupts for AC1 +#define IPC_IRQ_E2A_AC1_OFT (IPC_IRQ_E2A_AC0_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for AC1 +#define IPC_IRQ_E2A_AC1_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC1_OFT) +/// Offset of the interrupts for AC2 +#define IPC_IRQ_E2A_AC2_OFT (IPC_IRQ_E2A_AC1_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for AC2 +#define IPC_IRQ_E2A_AC2_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC2_OFT) +/// Offset of the interrupts for AC3 +#define IPC_IRQ_E2A_AC3_OFT (IPC_IRQ_E2A_AC2_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for AC3 +#define IPC_IRQ_E2A_AC3_MSK (IPC_IRQ_E2A_USER_MSK << IPC_IRQ_E2A_AC3_OFT) +/// Offset of the interrupts for BCN +#define IPC_IRQ_E2A_BCN_OFT (IPC_IRQ_E2A_AC3_OFT + CONFIG_USER_MAX) +/// Mask of the interrupts for BCN +#define IPC_IRQ_E2A_BCN_MSK CO_BIT(IPC_IRQ_E2A_BCN_OFT) + +#define IPC_IRQ_E2A_AC_TXCFM (IPC_IRQ_E2A_AC0_MSK | IPC_IRQ_E2A_AC1_MSK | \ + IPC_IRQ_E2A_AC2_MSK | IPC_IRQ_E2A_AC3_MSK) + +/// Interrupts bits used for the TX descriptors of the BCN queue +#if NX_TXQ_CNT < 5 +#define IPC_IRQ_E2A_BCN_TXCFM 0 +#else +#define IPC_IRQ_E2A_BCN_TXCFM (0x01 << IPC_IRQ_E2A_BCN_OFT) +#endif + +/// IPC TX descriptor interrupt mask +#define IPC_IRQ_E2A_TXCFM (IPC_IRQ_E2A_AC_TXCFM | IPC_IRQ_E2A_BCN_TXCFM) + +#else + +#define IPC_IRQ_E2A_TXCFM (((1 << NX_TXQ_CNT) - 1) << IPC_IRQ_E2A_TXCFM_POS) + +#endif /* CONFIG_RWNX_MUMIMO_TX */ + +#define IPC_IRQ_E2A_UNSUP_RX_VEC CO_BIT(7) +#define IPC_IRQ_E2A_RADAR CO_BIT(6) +#define IPC_IRQ_E2A_TBTT_SEC CO_BIT(5) +#define IPC_IRQ_E2A_TBTT_PRIM CO_BIT(4) +#define IPC_IRQ_E2A_RXDESC CO_BIT(3) +#define IPC_IRQ_E2A_MSG_ACK CO_BIT(2) +#define IPC_IRQ_E2A_MSG CO_BIT(1) +#define IPC_IRQ_E2A_DBG CO_BIT(0) + +#define IPC_IRQ_E2A_ALL (IPC_IRQ_E2A_TXCFM \ + | IPC_IRQ_E2A_RXDESC \ + | IPC_IRQ_E2A_MSG_ACK \ + | IPC_IRQ_E2A_MSG \ + | IPC_IRQ_E2A_DBG \ + | IPC_IRQ_E2A_TBTT_PRIM \ + | IPC_IRQ_E2A_TBTT_SEC \ + | IPC_IRQ_E2A_RADAR \ + | IPC_IRQ_E2A_UNSUP_RX_VEC) + +// FLAGS for RX desc +#define IPC_RX_FORWARD CO_BIT(1) +#define IPC_RX_INTRABSS CO_BIT(0) + + +// IPC message TYPE +enum { + IPC_MSG_NONE = 0, + IPC_MSG_WRAP, + IPC_MSG_KMSG, + + IPC_DBG_STRING, + +}; + +#endif // _IPC_SHARED_H_ + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h new file mode 100644 index 000000000000..2753d4d23253 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h @@ -0,0 +1,564 @@ +/** + **************************************************************************************** + * + * @file lmac_mac_types.h + * + * @brief MAC related definitions. + * + * Adapted from mac_types.h to used lmac_types.h instead of standard types + * eg: perl -pi -e '$_ =~ s/uint(\d{1,2})_t/u$1_l/g; \ + * $_ =~ s/int(\d{1,2})_t/s$1_l/g; \ + * $_ =~ s/CO_BIT/BIT/g;' lmac_mac.h + * + * Copyright (C) RivieraWaves 2011-2019 + * + **************************************************************************************** + */ + +#ifndef LMAC_MAC_H_ +#define LMAC_MAC_H_ + +#include "lmac_types.h" + +/// Interface types +enum mac_vif_type { + /// ESS STA interface + VIF_STA, + /// IBSS STA interface + VIF_IBSS, + /// AP interface + VIF_AP, + /// Mesh Point interface + VIF_MESH_POINT, + /// Monitor interface + VIF_MONITOR, + /// Unknown type + VIF_UNKNOWN +}; + +/// MAC address length in bytes. +#define MAC_ADDR_LEN 6 + +/// MAC address structure. +struct mac_addr { + /// Array of 16-bit words that make up the MAC address. + u16_l array[MAC_ADDR_LEN/2]; +}; + +/// SSID maximum length. +#define MAC_SSID_LEN 32 + +/// SSID. +struct mac_ssid { + /// Actual length of the SSID. + u8_l length; + /// Array containing the SSID name. + u8_l array[MAC_SSID_LEN]; +}; + +/// BSS type +enum mac_bss_type { + INFRASTRUCTURE_MODE = 1, + INDEPENDENT_BSS_MODE, + ANY_BSS_MODE +}; + +/// Channel Band +enum mac_chan_band { + /// 2.4GHz Band + PHY_BAND_2G4, + /// 5GHz band + PHY_BAND_5G, + /// Number of bands + PHY_BAND_MAX, +}; + +/// Operating Channel Bandwidth +enum mac_chan_bandwidth { + /// 20MHz BW + PHY_CHNL_BW_20, + /// 40MHz BW + PHY_CHNL_BW_40, + /// 80MHz BW + PHY_CHNL_BW_80, + /// 160MHz BW + PHY_CHNL_BW_160, + /// 80+80MHz BW + PHY_CHNL_BW_80P80, + /// Reserved BW + PHY_CHNL_BW_OTHER, +}; + +/// max number of channels in the 2.4 GHZ band +#define MAC_DOMAINCHANNEL_24G_MAX 14 + +/// max number of channels in the 5 GHZ band +#define MAC_DOMAINCHANNEL_5G_MAX 28 + +/// Channel Flag +enum mac_chan_flags { + /// Cannot initiate radiation on this channel + CHAN_NO_IR = BIT(0), + /// Channel is not allowed + CHAN_DISABLED = BIT(1), + /// Radar detection required on this channel + CHAN_RADAR = BIT(2), +}; + +/// Primary Channel definition +struct mac_chan_def { + /// Frequency of the channel (in MHz) + u16_l freq; + /// RF band (@ref mac_chan_band) + u8_l band; + /// Additional information (@ref mac_chan_flags) + u8_l flags; + /// Max transmit power allowed on this channel (dBm) + s8_l tx_power; +}; + +/// Operating Channel +struct mac_chan_op { + /// Band (@ref mac_chan_band) + u8_l band; + /// Channel type (@ref mac_chan_bandwidth) + u8_l type; + /// Frequency for Primary 20MHz channel (in MHz) + u16_l prim20_freq; + /// Frequency center of the contiguous channel or center of Primary 80+80 (in MHz) + u16_l center1_freq; + /// Frequency center of the non-contiguous secondary 80+80 (in MHz) + u16_l center2_freq; + /// Max transmit power allowed on this channel (dBm) + s8_l tx_power; + /// Additional information (@ref mac_chan_flags) + u8_l flags; +}; + +/// Cipher suites (order is important as it is used by MACHW) +enum mac_cipher_suite { + /// 00-0F-AC 1 + MAC_CIPHER_WEP40 = 0, + /// 00-0F-AC 2 + MAC_CIPHER_TKIP = 1, + /// 00-0F-AC 4 + MAC_CIPHER_CCMP = 2, + /// 00-0F-AC 5 + MAC_CIPHER_WEP104 = 3, + /// 00-14-72 1 + MAC_CIPHER_WPI_SMS4 = 4, + /// 00-0F-AC 6 (aka AES_CMAC) + MAC_CIPHER_BIP_CMAC_128 = 5, + + // following cipher are not supported by MACHW + /// 00-0F-AC 08 + MAC_CIPHER_GCMP_128, + /// 00-0F-AC 09 + MAC_CIPHER_GCMP_256, + /// 00-0F-AC 10 + MAC_CIPHER_CCMP_256, + /// 00-0F-AC 11 + MAC_CIPHER_BIP_GMAC_128, + /// 00-0F-AC 12 + MAC_CIPHER_BIP_GMAC_256, + /// 00-0F-AC 13 + MAC_CIPHER_BIP_CMAC_256, + + MAC_CIPHER_INVALID = 0xFF +}; + +/// Authentication and Key Management suite +enum mac_akm_suite { + /// No security + MAC_AKM_NONE, + /// Pre RSN (WEP or WPA) + MAC_AKM_PRE_RSN, + /// 00-0F-AC 1 + MAC_AKM_8021X, + /// 00-0F-AC 2 + MAC_AKM_PSK, + /// 00-0F-AC 3 + MAC_AKM_FT_8021X, + /// 00-0F-AC 4 + MAC_AKM_FT_PSK, + /// 00-0F-AC 5 + MAC_AKM_8021X_SHA256, + /// 00-0F-AC 6 + MAC_AKM_PSK_SHA256, + /// 00-0F-AC 7 + MAC_AKM_TDLS, + /// 00-0F-AC 8 + MAC_AKM_SAE, + /// 00-0F-AC 9 + MAC_AKM_FT_OVER_SAE, + /// 00-0F-AC 11 + MAC_AKM_8021X_SUITE_B, + /// 00-0F-AC 12 + MAC_AKM_8021X_SUITE_B_192, + /// 00-0F-AC 14 + MAC_AKM_FILS_SHA256, + /// 00-0F-AC 15 + MAC_AKM_FILS_SHA384, + /// 00-0F-AC 16 + MAC_AKM_FT_FILS_SHA256, + /// 00-0F-AC 17 + MAC_AKM_FT_FILS_SHA384, + /// 00-0F-AC 18 + MAC_AKM_OWE, + + /// 00-14-72 1 + MAC_AKM_WAPI_CERT, + /// 00-14-72 2 + MAC_AKM_WAPI_PSK, +}; + +/// Scan result element, parsed from beacon or probe response frames. +struct mac_scan_result { + /// Scan result is valid + bool valid_flag; + /// Network BSSID. + struct mac_addr bssid; + /// Network name. + struct mac_ssid ssid; + /// Network type (@ref mac_bss_type). + u16_l bsstype; + /// Network channel. + struct mac_chan_def *chan; + /// Network beacon period (in TU). + u16_l beacon_period; + /// Capability information + u16_l cap_info; + /// Supported AKM (bit-field of @ref mac_akm_suite) + u32_l akm; + /// Group cipher (bit-field of @ref mac_cipher_suite) + u16_l group_cipher; + /// Group cipher (bit-field of @ref mac_cipher_suite) + u16_l pairwise_cipher; + /// RSSI of the scanned BSS (in dBm) + s8_l rssi; +}; + +/// Legacy rate 802.11 definitions +enum mac_legacy_rates { + /// DSSS/CCK 1Mbps + MAC_RATE_1MBPS = 2, + /// DSSS/CCK 2Mbps + MAC_RATE_2MBPS = 4, + /// DSSS/CCK 5.5Mbps + MAC_RATE_5_5MBPS = 11, + /// OFDM 6Mbps + MAC_RATE_6MBPS = 12, + /// OFDM 9Mbps + MAC_RATE_9MBPS = 18, + /// DSSS/CCK 11Mbps + MAC_RATE_11MBPS = 22, + /// OFDM 12Mbps + MAC_RATE_12MBPS = 24, + /// OFDM 18Mbps + MAC_RATE_18MBPS = 36, + /// OFDM 24Mbps + MAC_RATE_24MBPS = 48, + /// OFDM 36Mbps + MAC_RATE_36MBPS = 72, + /// OFDM 48Mbps + MAC_RATE_48MBPS = 96, + /// OFDM 54Mbps + MAC_RATE_54MBPS = 108 +}; + +/// BSS Membership Selector definitions +enum mac_bss_membership { + /// HT PHY + MAC_BSS_MEMBERSHIP_HT_PHY = 127, + /// VHT PHY + MAC_BSS_MEMBERSHIP_VHT_PHY = 126, +}; + +/// MAC rateset maximum length +#define MAC_RATESET_LEN 12 + +/// Structure containing the legacy rateset of a station +struct mac_rateset { + /// Number of legacy rates supported + u8_l length; + /// Array of legacy rates + u8_l array[MAC_RATESET_LEN]; +}; + +/// MAC Security Key maximum length +#define MAC_SEC_KEY_LEN 32 // TKIP keys 256 bits (max length) with MIC keys + +/// Structure defining a security key +struct mac_sec_key { + /// Key material length + u8_l length; + /// Key material + u32_l array[MAC_SEC_KEY_LEN/4]; +}; + +/// Access Category enumeration +enum mac_ac { + /// Background + AC_BK = 0, + /// Best-effort + AC_BE, + /// Video + AC_VI, + /// Voice + AC_VO, + /// Number of access categories + AC_MAX +}; + +/// Traffic ID enumeration +enum mac_tid { + /// TID_0. Mapped to @ref AC_BE as per 802.11 standard. + TID_0, + /// TID_1. Mapped to @ref AC_BK as per 802.11 standard. + TID_1, + /// TID_2. Mapped to @ref AC_BK as per 802.11 standard. + TID_2, + /// TID_3. Mapped to @ref AC_BE as per 802.11 standard. + TID_3, + /// TID_4. Mapped to @ref AC_VI as per 802.11 standard. + TID_4, + /// TID_5. Mapped to @ref AC_VI as per 802.11 standard. + TID_5, + /// TID_6. Mapped to @ref AC_VO as per 802.11 standard. + TID_6, + /// TID_7. Mapped to @ref AC_VO as per 802.11 standard. + TID_7, + /// Non standard Management TID used internally + TID_MGT, + /// Number of TID supported + TID_MAX +}; + +/// MCS bitfield maximum size (in bytes) +#define MAX_MCS_LEN 16 // 16 * 8 = 128 + +/// MAC HT capability information element +struct mac_htcapability { + /// HT capability information + u16_l ht_capa_info; + /// A-MPDU parameters + u8_l a_mpdu_param; + /// Supported MCS + u8_l mcs_rate[MAX_MCS_LEN]; + /// HT extended capability information + u16_l ht_extended_capa; + /// Beamforming capability information + u32_l tx_beamforming_capa; + /// Antenna selection capability information + u8_l asel_capa; +}; + +/// MAC VHT capability information element +struct mac_vhtcapability { + /// VHT capability information + u32_l vht_capa_info; + /// RX MCS map + u16_l rx_mcs_map; + /// RX highest data rate + u16_l rx_highest; + /// TX MCS map + u16_l tx_mcs_map; + /// TX highest data rate + u16_l tx_highest; +}; + +/// Length (in bytes) of the MAC HE capability field +#define MAC_HE_MAC_CAPA_LEN 6 +/// Length (in bytes) of the PHY HE capability field +#define MAC_HE_PHY_CAPA_LEN 11 +/// Maximum length (in bytes) of the PPE threshold data +#define MAC_HE_PPE_THRES_MAX_LEN 25 + +/// Structure listing the per-NSS, per-BW supported MCS combinations +struct mac_he_mcs_nss_supp { + /// per-NSS supported MCS in RX, for BW <= 80MHz + u16_l rx_mcs_80; + /// per-NSS supported MCS in TX, for BW <= 80MHz + u16_l tx_mcs_80; + /// per-NSS supported MCS in RX, for BW = 160MHz + u16_l rx_mcs_160; + /// per-NSS supported MCS in TX, for BW = 160MHz + u16_l tx_mcs_160; + /// per-NSS supported MCS in RX, for BW = 80+80MHz + u16_l rx_mcs_80p80; + /// per-NSS supported MCS in TX, for BW = 80+80MHz + u16_l tx_mcs_80p80; +}; + +/// MAC HE capability information element +struct mac_hecapability { + /// MAC HE capabilities + u8_l mac_cap_info[MAC_HE_MAC_CAPA_LEN]; + /// PHY HE capabilities + u8_l phy_cap_info[MAC_HE_PHY_CAPA_LEN]; + /// Supported MCS combinations + struct mac_he_mcs_nss_supp mcs_supp; + /// PPE Thresholds data + u8_l ppe_thres[MAC_HE_PPE_THRES_MAX_LEN]; +}; + +/// Station flags +enum mac_sta_flags { + /// Bit indicating that a STA has QoS (WMM) capability + STA_QOS_CAPA = BIT(0), + /// Bit indicating that a STA has HT capability + STA_HT_CAPA = BIT(1), + /// Bit indicating that a STA has VHT capability + STA_VHT_CAPA = BIT(2), + /// Bit indicating that a STA has MFP capability + STA_MFP_CAPA = BIT(3), + /// Bit indicating that the STA included the Operation Notification IE + STA_OPMOD_NOTIF = BIT(4), + /// Bit indicating that a STA has HE capability + STA_HE_CAPA = BIT(5), +}; + +/// Connection flags +enum mac_connection_flags { + /// Flag indicating whether the control port is controlled by host or not + CONTROL_PORT_HOST = BIT(0), + /// Flag indicating whether the control port frame shall be sent unencrypted + CONTROL_PORT_NO_ENC = BIT(1), + /// Flag indicating whether HT and VHT shall be disabled or not + DISABLE_HT = BIT(2), + /// Flag indicating whether WPA or WPA2 authentication is in use + WPA_WPA2_IN_USE = BIT(3), + /// Flag indicating whether MFP is in use + MFP_IN_USE = BIT(4), + // Flag indicating Roam + REASSOCIATION = BIT(5), +}; + +#ifdef CONFIG_HE_FOR_OLD_KERNEL +#define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 +#define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G 0x04 +#define IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD 0x20 +#define IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US 0x40 +#define IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS 0x80 +#define IEEE80211_HE_PHY_CAP2_MIDAMBLE_RX_TX_MAX_NSTS 0x01 +#define IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US 0x02 +#define IEEE80211_HE_PHY_CAP2_DOPPLER_RX 0x20 +#define IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ 0x08 +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM 0x18 +#define IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 0x00 +#define IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA 0x40 +#define IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE 0x01 +#define IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4 0x0c +#define IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK 0x40 +#define IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK 0x80 +#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU 0x01 +#define IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU 0x02 +#define IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB 0x04 +#define IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB 0x08 +#define IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT 0x80 +#define IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO 0x40 +#define IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI 0x04 +#define IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G 0x02 +#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_COMP_SIGB 0x10 +#define IEEE80211_HE_PHY_CAP9_RX_FULL_BW_SU_USING_MU_WITH_NON_COMP_SIGB 0x20 + +#define IEEE80211_HE_PPE_THRES_MAX_LEN 25 + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) +#define WLAN_EID_EXTENSION 255 +/* Element ID Extensions for Element ID 255 */ + +enum ieee80211_eid_ext { + WLAN_EID_EXT_ASSOC_DELAY_INFO = 1, + WLAN_EID_EXT_FILS_REQ_PARAMS = 2, + WLAN_EID_EXT_FILS_KEY_CONFIRM = 3, + WLAN_EID_EXT_FILS_SESSION = 4, + WLAN_EID_EXT_FILS_HLP_CONTAINER = 5, + WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN = 6, + WLAN_EID_EXT_KEY_DELIVERY = 7, + WLAN_EID_EXT_FILS_WRAPPED_DATA = 8, + WLAN_EID_EXT_FILS_PUBLIC_KEY = 12, + WLAN_EID_EXT_FILS_NONCE = 13, + WLAN_EID_EXT_FUTURE_CHAN_GUIDANCE = 14, + +}; + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) +#define WLAN_EID_EXT_HE_CAPABILITY 35 +#define WLAN_EID_EXT_HE_OPERATION 36 +#define WLAN_EID_EXT_UORA 37 +#define WLAN_EID_EXT_HE_MU_EDCA 38 +#define WLAN_EID_EXT_HE_SPR 39 +#define WLAN_EID_EXT_NDP_FEEDBACK_REPORT_PARAMSET 41 +#define WLAN_EID_EXT_BSS_COLOR_CHG_ANN 42 +#define WLAN_EID_EXT_QUIET_TIME_PERIOD_SETUP 43 +#define WLAN_EID_EXT_ESS_REPORT 45 +#define WLAN_EID_EXT_OPS 46 +#define WLAN_EID_EXT_HE_BSS_LOAD 47 +#define WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME 52 +#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55 +#define WLAN_EID_EXT_NON_INHERITANCE 56 +#define WLAN_EID_EXT_KNOWN_BSSID 57 +#define WLAN_EID_EXT_SHORT_SSID_LIST 58 +#define WLAN_EID_EXT_HE_6GHZ_CAPA 59 +#define WLAN_EID_EXT_UL_MU_POWER_CAPA 60 +#define WLAN_EID_EXT_EHT_OPERATION 106 +#define WLAN_EID_EXT_EHT_MULTI_LINK 107 +#define WLAN_EID_EXT_EHT_CAPABILITY 108 +#endif + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) +#include <linux/ieee80211.h> +#else +struct ieee80211_he_cap_elem { + u8 mac_cap_info[6]; + u8 phy_cap_info[11]; +} __packed; + +struct ieee80211_he_mcs_nss_supp { + __le16 rx_mcs_80; + __le16 tx_mcs_80; + __le16 rx_mcs_160; + __le16 tx_mcs_160; + __le16 rx_mcs_80p80; + __le16 tx_mcs_80p80; +} __packed; + +struct ieee80211_sta_he_cap { + bool has_he; + struct ieee80211_he_cap_elem he_cap_elem; + struct ieee80211_he_mcs_nss_supp he_mcs_nss_supp; + u8 ppe_thres[IEEE80211_HE_PPE_THRES_MAX_LEN]; +}; + +struct ieee80211_sband_iftype_data { + u16 types_mask; + struct ieee80211_sta_he_cap he_cap; +}; +#endif +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) || defined(CONFIG_VHT_FOR_OLD_KERNEL) +struct ieee80211_vht_mcs_info { + __le16 rx_mcs_map; + __le16 rx_highest; + __le16 tx_mcs_map; + __le16 tx_highest; +} __packed; + +struct ieee80211_vht_cap { + __le32 vht_cap_info; + struct ieee80211_vht_mcs_info supp_mcs; +}; +#define WLAN_EID_VHT_CAPABILITY 191 + +struct ieee80211_sta_vht_cap { + bool vht_supported; + u32 cap; /* use IEEE80211_VHT_CAP_ */ + struct ieee80211_vht_mcs_info vht_mcs; +}; +#endif +#endif // LMAC_MAC_H_ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h new file mode 100644 index 000000000000..061248c1015d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h @@ -0,0 +1,2969 @@ +/** + **************************************************************************************** + * + * @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, + + /// 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; +}; + +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 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; + }; +}; + + +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; + +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]; +}; + +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, +}; + +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_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_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; + }; +}; + +/// 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, + + /// 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, + /// MAX number of messages + TDLS_MAX +}; + +/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_REQ message +struct tdls_chan_switch_req { + /// Index of the VIF + u8_l vif_index; + /// STA Index + u8_l sta_idx; + /// MAC address of the TDLS station + struct mac_addr peer_mac_addr; + bool_l initiator; + /// Band (2.4GHz or 5GHz) + u8_l band; + /// Channel type: 20,40,80,160 or 80+80 MHz + u8_l type; + /// Frequency for Primary 20MHz channel (in MHz) + u16_l prim20_freq; + /// Frequency for Center of the contiguous channel or center of Primary 80+80 + u16_l center1_freq; + /// Frequency for Center of the non-contiguous secondary 80+80 + u16_l center2_freq; + /// TX power (in dBm) + s8_l tx_power; + /// Operating class + u8_l op_class; +}; + +/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_REQ message +struct tdls_cancel_chan_switch_req { + /// Index of the VIF + u8_l vif_index; + /// STA Index + u8_l sta_idx; + /// MAC address of the TDLS station + struct mac_addr peer_mac_addr; +}; + + +/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_CFM message +struct tdls_chan_switch_cfm { + /// Status of the operation + u8_l status; +}; + +/// Structure containing the parameters of the @ref TDLS_CANCEL_CHAN_SWITCH_CFM message +struct tdls_cancel_chan_switch_cfm { + /// Status of the operation + u8_l status; +}; + +/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_IND message +struct tdls_chan_switch_ind { + /// VIF Index + u8_l vif_index; + /// Channel Context Index + u8_l chan_ctxt_index; + /// Status of the operation + u8_l status; +}; + +/// Structure containing the parameters of the @ref TDLS_CHAN_SWITCH_BASE_IND message +struct tdls_chan_switch_base_ind { + /// VIF Index + u8_l vif_index; + /// Channel Context index + u8_l chan_ctxt_index; +}; + +/// Structure containing the parameters of the @ref TDLS_PEER_PS_IND message +struct tdls_peer_ps_ind { + /// VIF Index + u8_l vif_index; + /// STA Index + u8_l sta_idx; + /// MAC ADDR of the TDLS STA + struct mac_addr peer_mac_addr; + /// Flag to indicate if the TDLS peer is going to sleep + bool ps_on; +}; + +/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_REQ message +struct tdls_peer_traffic_ind_req { + /// VIF Index + u8_l vif_index; + /// STA Index + u8_l sta_idx; + // MAC ADDR of the TDLS STA + struct mac_addr peer_mac_addr; + /// Dialog token + u8_l dialog_token; + /// TID of the latest MPDU transmitted over the TDLS direct link to the TDLS STA + u8_l last_tid; + /// Sequence number of the latest MPDU transmitted over the TDLS direct link + /// to the TDLS STA + u16_l last_sn; +}; + +/// Structure containing the parameters of the @ref TDLS_PEER_TRAFFIC_IND_CFM message +struct tdls_peer_traffic_ind_cfm { + /// Status of the operation + u8_l status; +}; + + +#endif // LMAC_MSG_H_ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_types.h b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_types.h new file mode 100644 index 000000000000..83b112290409 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_types.h @@ -0,0 +1,62 @@ +/** + **************************************************************************************** + * + * @file co_types.h + * + * @brief This file replaces the need to include stdint or stdbool typical headers, + * which may not be available in all toolchains, and adds new types + * + * Copyright (C) RivieraWaves 2009-2019 + * + * $Rev: $ + * + **************************************************************************************** + */ + +#ifndef _LMAC_INT_H_ +#define _LMAC_INT_H_ + + +/** + **************************************************************************************** + * @addtogroup CO_INT + * @ingroup COMMON + * @brief Common integer standard types (removes use of stdint) + * + * @{ + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +#include <linux/version.h> +#include <linux/types.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) +#include <linux/bits.h> +#else +#include <linux/bitops.h> +#endif + +#ifdef CONFIG_RWNX_TL4 +typedef uint16_t u8_l; +typedef int16_t s8_l; +typedef uint16_t bool_l; +#else +typedef uint8_t u8_l; +typedef int8_t s8_l; +typedef bool bool_l; +#endif +typedef uint16_t u16_l; +typedef int16_t s16_l; +typedef uint32_t u32_l; +typedef int32_t s32_l; +typedef uint64_t u64_l; + + + +/// @} CO_INT +#endif // _LMAC_INT_H_ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/md5.c b/drivers/net/wireless/aic8800/aic8800_fdrv/md5.c new file mode 100644 index 000000000000..3d7b65375adb --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/md5.c @@ -0,0 +1,161 @@ +#include <linux/memory.h> +#include "md5.h" + +unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +void MD5Init(MD5_CTX *context) +{ + context->count[0] = 0; + context->count[1] = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; +} +void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen) +{ + unsigned int i = 0,index = 0,partlen = 0; + index = (context->count[0] >> 3) & 0x3F; + partlen = 64 - index; + context->count[0] += inputlen << 3; + if(context->count[0] < (inputlen << 3)) + context->count[1]++; + context->count[1] += inputlen >> 29; + + if(inputlen >= partlen) + { + memcpy(&context->buffer[index],input,partlen); + MD5Transform(context->state,context->buffer); + for(i = partlen;i+64 <= inputlen;i+=64) + MD5Transform(context->state,&input[i]); + index = 0; + } + else + { + i = 0; + } + memcpy(&context->buffer[index],&input[i],inputlen-i); +} +void MD5Final(MD5_CTX *context,unsigned char digest[16]) +{ + unsigned int index = 0,padlen = 0; + unsigned char bits[8]; + index = (context->count[0] >> 3) & 0x3F; + padlen = (index < 56)?(56-index):(120-index); + MD5Encode(bits,context->count,8); + MD5Update(context,PADDING,padlen); + MD5Update(context,bits,8); + MD5Encode(digest,context->state,16); +} +void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len) +{ + unsigned int i = 0,j = 0; + while(j < len) + { + output[j] = input[i] & 0xFF; + output[j+1] = (input[i] >> 8) & 0xFF; + output[j+2] = (input[i] >> 16) & 0xFF; + output[j+3] = (input[i] >> 24) & 0xFF; + i++; + j+=4; + } +} +void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len) +{ + unsigned int i = 0,j = 0; + while(j < len) + { + output[i] = (input[j]) | + (input[j+1] << 8) | + (input[j+2] << 16) | + (input[j+3] << 24); + i++; + j+=4; + } +} +void MD5Transform(unsigned int state[4],unsigned char block[64]) +{ + unsigned int a = state[0]; + unsigned int b = state[1]; + unsigned int c = state[2]; + unsigned int d = state[3]; + unsigned int x[64]; + MD5Decode(x,block,64); + FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ + FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ + II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/md5.h b/drivers/net/wireless/aic8800/aic8800_fdrv/md5.h new file mode 100644 index 000000000000..6ed5c0f8e886 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/md5.h @@ -0,0 +1,48 @@ +#ifndef MD5_H +#define MD5_H + +typedef struct +{ + unsigned int count[2]; + unsigned int state[4]; + unsigned char buffer[64]; +}MD5_CTX; + + +#define F(x,y,z) ((x & y) | (~x & z)) +#define G(x,y,z) ((x & z) | (y & ~z)) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y ^ (x | ~z)) +#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n))) +#define FF(a,b,c,d,x,s,ac) \ + { \ + a += F(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +#define GG(a,b,c,d,x,s,ac) \ + { \ + a += G(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +#define HH(a,b,c,d,x,s,ac) \ + { \ + a += H(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +#define II(a,b,c,d,x,s,ac) \ + { \ + a += I(b,c,d) + x + ac; \ + a = ROTATE_LEFT(a,s); \ + a += b; \ + } +void MD5Init(MD5_CTX *context); +void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen); +void MD5Final(MD5_CTX *context,unsigned char digest[16]); +void MD5Transform(unsigned int state[4],unsigned char block[64]); +void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len); +void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len); + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/reg_access.h b/drivers/net/wireless/aic8800/aic8800_fdrv/reg_access.h new file mode 100644 index 000000000000..568146624cee --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/reg_access.h @@ -0,0 +1,148 @@ +/** + ****************************************************************************** + * + * @file reg_access.h + * + * @brief Definitions and macros for MAC HW and platform register accesses + * + * Copyright (C) RivieraWaves 2011-2019 + * + ****************************************************************************** + */ + +#ifndef REG_ACCESS_H_ +#define REG_ACCESS_H_ + +/***************************************************************************** + * Addresses within RWNX_ADDR_SYSTEM + *****************************************************************************/ +/* Shard RAM */ +#define SHARED_RAM_START_ADDR 0x00000000 + +/* IPC registers */ +#define IPC_REG_BASE_ADDR 0x00800000 + +/* System Controller Registers */ +#define SYSCTRL_SIGNATURE_ADDR 0x00900000 +// old diag register name +#define SYSCTRL_DIAG_CONF_ADDR 0x00900068 +#define SYSCTRL_PHYDIAG_CONF_ADDR 0x00900074 +#define SYSCTRL_RIUDIAG_CONF_ADDR 0x00900078 +// new diag register name +#define SYSCTRL_DIAG_CONF0 0x00900064 +#define SYSCTRL_DIAG_CONF1 0x00900068 +#define SYSCTRL_DIAG_CONF2 0x00900074 +#define SYSCTRL_DIAG_CONF3 0x00900078 +#define SYSCTRL_MISC_CNTL_ADDR 0x009000E0 +#define BOOTROM_ENABLE BIT(4) +#define FPGA_B_RESET BIT(1) +#define SOFT_RESET BIT(0) + +/* MAC platform */ +#define NXMAC_VERSION_1_ADDR 0x00B00004 +#define NXMAC_MU_MIMO_TX_BIT BIT(19) +#define NXMAC_BFMER_BIT BIT(18) +#define NXMAC_BFMEE_BIT BIT(17) +#define NXMAC_MAC_80211MH_FORMAT_BIT BIT(16) +#define NXMAC_COEX_BIT BIT(14) +#define NXMAC_WAPI_BIT BIT(13) +#define NXMAC_TPC_BIT BIT(12) +#define NXMAC_VHT_BIT BIT(11) +#define NXMAC_HT_BIT BIT(10) +#define NXMAC_RCE_BIT BIT(8) +#define NXMAC_CCMP_BIT BIT(7) +#define NXMAC_TKIP_BIT BIT(6) +#define NXMAC_WEP_BIT BIT(5) +#define NXMAC_SECURITY_BIT BIT(4) +#define NXMAC_SME_BIT BIT(3) +#define NXMAC_HCCA_BIT BIT(2) +#define NXMAC_EDCA_BIT BIT(1) +#define NXMAC_QOS_BIT BIT(0) + +#define NXMAC_RX_CNTRL_ADDR 0x00B00060 +#define NXMAC_EN_DUPLICATE_DETECTION_BIT BIT(31) +#define NXMAC_ACCEPT_UNKNOWN_BIT BIT(30) +#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT BIT(29) +#define NXMAC_ACCEPT_QO_S_NULL_BIT BIT(28) +#define NXMAC_ACCEPT_QCFWO_DATA_BIT BIT(27) +#define NXMAC_ACCEPT_Q_DATA_BIT BIT(26) +#define NXMAC_ACCEPT_CFWO_DATA_BIT BIT(25) +#define NXMAC_ACCEPT_DATA_BIT BIT(24) +#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT BIT(23) +#define NXMAC_ACCEPT_CF_END_BIT BIT(22) +#define NXMAC_ACCEPT_ACK_BIT BIT(21) +#define NXMAC_ACCEPT_CTS_BIT BIT(20) +#define NXMAC_ACCEPT_RTS_BIT BIT(19) +#define NXMAC_ACCEPT_PS_POLL_BIT BIT(18) +#define NXMAC_ACCEPT_BA_BIT BIT(17) +#define NXMAC_ACCEPT_BAR_BIT BIT(16) +#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT BIT(15) +#define NXMAC_ACCEPT_BFMEE_FRAMES_BIT BIT(14) +#define NXMAC_ACCEPT_ALL_BEACON_BIT BIT(13) +#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT BIT(12) +#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT BIT(11) +#define NXMAC_ACCEPT_BEACON_BIT BIT(10) +#define NXMAC_ACCEPT_PROBE_RESP_BIT BIT(9) +#define NXMAC_ACCEPT_PROBE_REQ_BIT BIT(8) +#define NXMAC_ACCEPT_MY_UNICAST_BIT BIT(7) +#define NXMAC_ACCEPT_UNICAST_BIT BIT(6) +#define NXMAC_ACCEPT_ERROR_FRAMES_BIT BIT(5) +#define NXMAC_ACCEPT_OTHER_BSSID_BIT BIT(4) +#define NXMAC_ACCEPT_BROADCAST_BIT BIT(3) +#define NXMAC_ACCEPT_MULTICAST_BIT BIT(2) +#define NXMAC_DONT_DECRYPT_BIT BIT(1) +#define NXMAC_EXC_UNENCRYPTED_BIT BIT(0) + +#define NXMAC_DEBUG_PORT_SEL_ADDR 0x00B00510 +#define NXMAC_SW_SET_PROFILING_ADDR 0x00B08564 +#define NXMAC_SW_CLEAR_PROFILING_ADDR 0x00B08568 + +/* Modem Status */ +#define MDM_HDMCONFIG_ADDR 0x00C00000 + +/* Clock gating configuration */ +#define MDM_MEMCLKCTRL0_ADDR 0x00C00848 +#define MDM_CLKGATEFCTRL0_ADDR 0x00C00874 +#define CRM_CLKGATEFCTRL0_ADDR 0x00940010 + +/* AGC (trident) */ +#define AGC_RWNXAGCCNTL_ADDR 0x00C02060 + +/* LDPC RAM*/ +#define PHY_LDPC_RAM_ADDR 0x00C09000 + +/* FCU (elma )*/ +#define FCU_RWNXFCAGCCNTL_ADDR 0x00C09034 + +/* AGC RAM */ +#define PHY_AGC_UCODE_ADDR 0x00C0A000 + +/* RIU */ +#define RIU_RWNXVERSION_ADDR 0x00C0B000 +#define RIU_RWNXDYNAMICCONFIG_ADDR 0x00C0B008 +#define RIU_AGCMEMBISTSTAT_ADDR 0x00C0B238 +#define RIU_AGCMEMSIGNATURESTAT_ADDR 0x00C0B23C +#define RIU_RWNXAGCCNTL_ADDR 0x00C0B390 + +/* FCU RAM */ +#define PHY_FCU_UCODE_ADDR 0x00C0E000 + +/* RF ITF */ +#define FPGAB_MPIF_SEL_ADDR 0x00C10030 +#define RF_V6_DIAGPORT_CONF1_ADDR 0x00C10010 +#define RF_v6_PHYDIAG_CONF1_ADDR 0x00C10018 + +#define RF_V7_DIAGPORT_CONF1_ADDR 0x00F10010 +#define RF_v7_PHYDIAG_CONF1_ADDR 0x00F10018 + +/***************************************************************************** + * Macros for generated register files + *****************************************************************************/ +/* Macros for IPC registers access (used in reg_ipc_app.h) */ +#define REG_IPC_APP_RD(env, INDEX) \ + (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX))) + +#define REG_IPC_APP_WR(env, INDEX, value) \ + (*(volatile u32 *)((u8 *)env + IPC_REG_BASE_ADDR + 4 * (INDEX)) = value) + +#endif /* REG_ACCESS_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/regdb.c b/drivers/net/wireless/aic8800/aic8800_fdrv/regdb.c new file mode 100644 index 000000000000..0f8777066936 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/regdb.c @@ -0,0 +1,2898 @@ +#include <linux/nl80211.h> +#include <net/cfg80211.h> +#include <linux/version.h> + +//#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_bfmer.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_bfmer.c new file mode 100644 index 000000000000..b39cf0f205a3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_bfmer.c @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * + * @file rwnx_bfmer.c + * + * @brief VHT Beamformer function definitions + * + * Copyright (C) RivieraWaves 2016-2019 + * + ****************************************************************************** + */ + +/** + * INCLUDE FILES + ****************************************************************************** + */ + +#include <linux/slab.h> +#include "rwnx_bfmer.h" + +/** + * FUNCTION DEFINITIONS + ****************************************************************************** + */ + +int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, + unsigned int length) +{ + gfp_t flags; + struct rwnx_bfmer_report *bfm_report ; + + if (in_softirq()) + flags = GFP_ATOMIC; + else + flags = GFP_KERNEL; + + /* Allocate a structure that will contain the beamforming report */ + bfm_report = kmalloc(sizeof(*bfm_report) + length, flags); + + + /* Check report allocation */ + if (!bfm_report) { + /* Do not use beamforming */ + return -1; + } + + /* Store report length */ + bfm_report->length = length; + + /* + * Need to provide a Virtual Address to the MAC so that it can + * upload the received Beamforming Report in driver memory + */ + bfm_report->dma_addr = dma_map_single(rwnx_hw->dev, &bfm_report->report[0], + length, DMA_FROM_DEVICE); + + /* Check DMA mapping result */ + if (dma_mapping_error(rwnx_hw->dev, bfm_report->dma_addr)) { + /* Free allocated report */ + kfree(bfm_report); + /* And leave */ + return -1; + } + + /* Store report structure */ + rwnx_sta->bfm_report = bfm_report; + + return 0; +} + +void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta) +{ + /* Verify if a report has been allocated */ + if (rwnx_sta->bfm_report) { + struct rwnx_bfmer_report *bfm_report = rwnx_sta->bfm_report; + + /* Unmap DMA region */ + dma_unmap_single(rwnx_hw->dev, bfm_report->dma_addr, + bfm_report->length, DMA_BIDIRECTIONAL); + + /* Free allocated report structure and clean the pointer */ + kfree(bfm_report); + rwnx_sta->bfm_report = NULL; + } +} + +#ifdef CONFIG_RWNX_FULLMAC +u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa) +{ + int i; + u8 rx_nss = 0; + u16 rx_mcs_map = le16_to_cpu(vht_capa->supp_mcs.rx_mcs_map); + + for (i = 7; i >= 0; i--) { + u8 mcs = (rx_mcs_map >> (2 * i)) & 3; + + if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) { + rx_nss = i + 1; + break; + } + } + + return rx_nss; +} +#endif /* CONFIG_RWNX_FULLMAC */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_bfmer.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_bfmer.h new file mode 100644 index 000000000000..4ce16496ef2e --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_bfmer.h @@ -0,0 +1,100 @@ +/** + ****************************************************************************** + * + * @file rwnx_bfmer.h + * + * @brief VHT Beamformer function declarations + * + * Copyright (C) RivieraWaves 2016-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_BFMER_H_ +#define _RWNX_BFMER_H_ + +/** + * INCLUDE FILES + ****************************************************************************** + */ + +#include "rwnx_defs.h" + +/** + * DEFINES + ****************************************************************************** + */ + +/// Maximal supported report length (in bytes) +#define RWNX_BFMER_REPORT_MAX_LEN 2048 + +/// Size of the allocated report space (twice the maximum report length) +#define RWNX_BFMER_REPORT_SPACE_SIZE (RWNX_BFMER_REPORT_MAX_LEN * 2) + +/** + * TYPE DEFINITIONS + ****************************************************************************** + */ + +/* + * Structure used to store a beamforming report. + */ +struct rwnx_bfmer_report { + dma_addr_t dma_addr; /* Virtual address provided to MAC for + DMA transfer of the Beamforming Report */ + unsigned int length; /* Report Length */ + u8 report[1]; /* Report to be used for VHT TX Beamforming */ +}; + +/** + * FUNCTION DECLARATIONS + ****************************************************************************** + */ + +/** + ****************************************************************************** + * @brief Allocate memory aiming to contains the Beamforming Report received + * from a Beamformee capable capable. + * The providing length shall be large enough to contain the VHT Compressed + * Beaforming Report and the MU Exclusive part. + * It also perform a DMA Mapping providing an address to be provided to the HW + * responsible for the DMA transfer of the report. + * If successful a struct rwnx_bfmer_report object is allocated, it's address + * is stored in rwnx_sta->bfm_report. + * + * @param[in] rwnx_hw PHY Information + * @param[in] rwnx_sta Peer STA Information + * @param[in] length Memory size to be allocated + * + * @return 0 if operation is successful, else -1. + ****************************************************************************** + */ +int rwnx_bfmer_report_add(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, + unsigned int length); + +/** + ****************************************************************************** + * @brief Free a previously allocated memory intended to be used for + * Beamforming Reports. + * + * @param[in] rwnx_hw PHY Information + * @param[in] rwnx_sta Peer STA Information + * + ****************************************************************************** + */ +void rwnx_bfmer_report_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); + +#ifdef CONFIG_RWNX_FULLMAC +/** + ****************************************************************************** + * @brief Parse a Rx VHT-MCS map in order to deduce the maximum number of + * Spatial Streams supported by a beamformee. + * + * @param[in] vht_capa Received VHT Capability field. + * + ****************************************************************************** + */ +u8 rwnx_bfmer_get_rx_nss(const struct ieee80211_vht_cap *vht_capa); +#endif /* CONFIG_RWNX_FULLMAC */ + +#endif /* _RWNX_BFMER_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cfgfile.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cfgfile.c new file mode 100644 index 000000000000..39a5a251482a --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cfgfile.c @@ -0,0 +1,239 @@ +/** + **************************************************************************************** + * + * @file rwnx_configparse.c + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ +#include <linux/firmware.h> +#include <linux/if_ether.h> + +#include "rwnx_defs.h" +#include "rwnx_cfgfile.h" + +/** + * + */ +static const char *rwnx_find_tag(const u8 *file_data, unsigned int file_size, + const char *tag_name, unsigned int tag_len) +{ + unsigned int curr, line_start = 0, line_size; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + /* Walk through all the lines of the configuration file */ + while (line_start < file_size) { + /* Search the end of the current line (or the end of the file) */ + for (curr = line_start; curr < file_size; curr++) + if (file_data[curr] == '\n') + break; + + /* Compute the line size */ + line_size = curr - line_start; + + /* Check if this line contains the expected tag */ + if ((line_size == (strlen(tag_name) + tag_len)) && + (!strncmp(&file_data[line_start], tag_name, strlen(tag_name)))) + return &file_data[line_start + strlen(tag_name)]; + + /* Move to next line */ + line_start = curr + 1; + } + + /* Tag not found */ + return NULL; +} + +/** + * Parse the Config file used at init time + */ +int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, + struct rwnx_conf_file *config) +{ + const struct firmware *config_fw; + u8 dflt_mac[ETH_ALEN] = { 0, 111, 111, 111, 111, 0 }; + int ret; + const u8 *tag_ptr; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + ret = request_firmware(&config_fw, filename, rwnx_hw->dev); + if (ret) { + printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); + return ret; + } + + /* Get MAC Address */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "MAC_ADDR=", strlen("00:00:00:00:00:00")); + if (tag_ptr != NULL) { + u8 *addr = config->mac_addr; + if (sscanf(tag_ptr, + "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + addr + 0, addr + 1, addr + 2, + addr + 3, addr + 4, addr + 5) != ETH_ALEN) + memcpy(config->mac_addr, dflt_mac, ETH_ALEN); + } else + memcpy(config->mac_addr, dflt_mac, ETH_ALEN); + + RWNX_DBG("MAC Address is:\n%pM\n", config->mac_addr); + + /* Release the configuration file */ + release_firmware(config_fw); + + return 0; +} + +/** + * Parse the Config file used at init time + */ +int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, + struct rwnx_phy_conf_file *config, int path) +{ + const struct firmware *config_fw; + int ret; + const u8 *tag_ptr; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + ret = request_firmware(&config_fw, filename, rwnx_hw->dev); + if (ret) { + printk(KERN_CRIT "%s: Failed to get %s (%d)\n", __func__, filename, ret); + return ret; + } + + /* Get Trident path mapping */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "TRD_PATH_MAPPING=", strlen("00")); + if (tag_ptr != NULL) { + u8 val; + if (sscanf(tag_ptr, "%hhx", &val) == 1) + config->trd.path_mapping = val; + else + config->trd.path_mapping = path; + } else + config->trd.path_mapping = path; + + RWNX_DBG("Trident path mapping is: %d\n", config->trd.path_mapping); + + /* Get DC offset compensation */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "TX_DC_OFF_COMP=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->trd.tx_dc_off_comp) != 1) + config->trd.tx_dc_off_comp = 0; + } else + config->trd.tx_dc_off_comp = 0; + + RWNX_DBG("TX DC offset compensation is: %08X\n", config->trd.tx_dc_off_comp); + + /* Get Karst TX IQ compensation value for path0 on 2.4GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_TX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[0]) != 1) + config->karst.tx_iq_comp_2_4G[0] = 0x01000000; + } else + config->karst.tx_iq_comp_2_4G[0] = 0x01000000; + + RWNX_DBG("Karst TX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[0]); + + /* Get Karst TX IQ compensation value for path1 on 2.4GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_TX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_2_4G[1]) != 1) + config->karst.tx_iq_comp_2_4G[1] = 0x01000000; + } else + config->karst.tx_iq_comp_2_4G[1] = 0x01000000; + + RWNX_DBG("Karst TX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.tx_iq_comp_2_4G[1]); + + /* Get Karst RX IQ compensation value for path0 on 2.4GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_RX_IQ_COMP_2_4G_PATH_0=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[0]) != 1) + config->karst.rx_iq_comp_2_4G[0] = 0x01000000; + } else + config->karst.rx_iq_comp_2_4G[0] = 0x01000000; + + RWNX_DBG("Karst RX IQ compensation for path 0 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[0]); + + /* Get Karst RX IQ compensation value for path1 on 2.4GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_RX_IQ_COMP_2_4G_PATH_1=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_2_4G[1]) != 1) + config->karst.rx_iq_comp_2_4G[1] = 0x01000000; + } else + config->karst.rx_iq_comp_2_4G[1] = 0x01000000; + + RWNX_DBG("Karst RX IQ compensation for path 1 on 2.4GHz is: %08X\n", config->karst.rx_iq_comp_2_4G[1]); + + /* Get Karst TX IQ compensation value for path0 on 5GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_TX_IQ_COMP_5G_PATH_0=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[0]) != 1) + config->karst.tx_iq_comp_5G[0] = 0x01000000; + } else + config->karst.tx_iq_comp_5G[0] = 0x01000000; + + RWNX_DBG("Karst TX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[0]); + + /* Get Karst TX IQ compensation value for path1 on 5GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_TX_IQ_COMP_5G_PATH_1=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.tx_iq_comp_5G[1]) != 1) + config->karst.tx_iq_comp_5G[1] = 0x01000000; + } else + config->karst.tx_iq_comp_5G[1] = 0x01000000; + + RWNX_DBG("Karst TX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.tx_iq_comp_5G[1]); + + /* Get Karst RX IQ compensation value for path0 on 5GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_RX_IQ_COMP_5G_PATH_0=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[0]) != 1) + config->karst.rx_iq_comp_5G[0] = 0x01000000; + } else + config->karst.rx_iq_comp_5G[0] = 0x01000000; + + RWNX_DBG("Karst RX IQ compensation for path 0 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[0]); + + /* Get Karst RX IQ compensation value for path1 on 5GHz */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_RX_IQ_COMP_5G_PATH_1=", strlen("00000000")); + if (tag_ptr != NULL) { + if (sscanf(tag_ptr, "%08x", &config->karst.rx_iq_comp_5G[1]) != 1) + config->karst.rx_iq_comp_5G[1] = 0x01000000; + } else + config->karst.rx_iq_comp_5G[1] = 0x01000000; + + RWNX_DBG("Karst RX IQ compensation for path 1 on 5GHz is: %08X\n", config->karst.rx_iq_comp_5G[1]); + + /* Get Karst default path */ + tag_ptr = rwnx_find_tag(config_fw->data, config_fw->size, + "KARST_DEFAULT_PATH=", strlen("00")); + if (tag_ptr != NULL) { + u8 val; + if (sscanf(tag_ptr, "%hhx", &val) == 1) + config->karst.path_used = val; + else + config->karst.path_used = path; + } else + config->karst.path_used = path; + + RWNX_DBG("Karst default path is: %d\n", config->karst.path_used); + + /* Release the configuration file */ + release_firmware(config_fw); + + return 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cfgfile.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cfgfile.h new file mode 100644 index 000000000000..7dc96fe5862b --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cfgfile.h @@ -0,0 +1,35 @@ +/** + **************************************************************************************** + * + * @file rwnx_cfgfile.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ + +#ifndef _RWNX_CFGFILE_H_ +#define _RWNX_CFGFILE_H_ + +/* + * Structure used to retrieve information from the Config file used at Initialization time + */ +struct rwnx_conf_file { + u8 mac_addr[ETH_ALEN]; +}; + +/* + * Structure used to retrieve information from the PHY Config file used at Initialization time + */ +struct rwnx_phy_conf_file { + struct phy_trd_cfg_tag trd; + struct phy_karst_cfg_tag karst; +}; + +int rwnx_parse_configfile(struct rwnx_hw *rwnx_hw, const char *filename, + struct rwnx_conf_file *config); + +int rwnx_parse_phy_configfile(struct rwnx_hw *rwnx_hw, const char *filename, + struct rwnx_phy_conf_file *config, int path); + +#endif /* _RWNX_CFGFILE_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c new file mode 100644 index 000000000000..36f4686ed9a0 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c @@ -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 <linux/list.h> + +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.h new file mode 100644 index 000000000000..b757a65cf1ce --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.h @@ -0,0 +1,124 @@ +/** + ****************************************************************************** + * + * rwnx_cmds.h + * + * Copyright (C) RivieraWaves 2014-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_CMDS_H_ +#define _RWNX_CMDS_H_ + +#include <linux/spinlock.h> +#include <linux/completion.h> +#include <linux/module.h> +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_compat.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_compat.h new file mode 100644 index 000000000000..9287eca607f8 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_compat.h @@ -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 <linux/version.h> + +#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 <linux/bitfield.h> +#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 <linux/types.h> + +struct ieee80211_wmm_ac_param { + u8 aci_aifsn; /* AIFSN, ACM, ACI */ + u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ + __le16 txop_limit; +} __packed; + +struct ieee80211_wmm_param_ie { + u8 element_id; /* Element ID: 221 (0xdd); */ + u8 len; /* Length: 24 */ + /* required fields for WMM version 1 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 1 */ + u8 version; /* 1 for WMM version 1.0 */ + u8 qos_info; /* AP/STA specific QoS info */ + u8 reserved; /* 0 */ + /* AC_BE, AC_BK, AC_VI, AC_VO */ + struct ieee80211_wmm_ac_param ac[4]; +} __packed; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) +enum { + IEEE80211_HE_MCS_SUPPORT_0_7 = 0, + IEEE80211_HE_MCS_SUPPORT_0_9 = 1, + IEEE80211_HE_MCS_SUPPORT_0_11 = 2, + IEEE80211_HE_MCS_NOT_SUPPORTED = 3, +}; +#endif + +/* MAC80211 */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0) +#define rwnx_ops_mgd_prepare_tx(hw, vif, duration) \ + rwnx_ops_mgd_prepare_tx(hw, vif) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) + +#define RX_ENC_HT(s) (s->flag |= RX_FLAG_HT) +#define RX_ENC_HT_GF(s) (s->flag |= (RX_FLAG_HT | RX_FLAG_HT_GF)) +#define RX_ENC_VHT(s) (s->flag |= RX_FLAG_HT) +#define RX_ENC_HE(s) (s->flag |= RX_FLAG_HT) +#define RX_ENC_FLAG_SHORT_GI(s) (s->flag |= RX_FLAG_SHORT_GI) +#define RX_ENC_FLAG_SHORT_PRE(s) (s->flag |= RX_FLAG_SHORTPRE) +#define RX_ENC_FLAG_LDPC(s) (s->flag |= RX_FLAG_LDPC) +#define RX_BW_40MHZ(s) (s->flag |= RX_FLAG_40MHZ) +#define RX_BW_80MHZ(s) (s->vht_flag |= RX_VHT_FLAG_80MHZ) +#define RX_BW_160MHZ(s) (s->vht_flag |= RX_VHT_FLAG_160MHZ) +#define RX_NSS(s) s->vht_nss + +#else +#define RX_ENC_HT(s) (s->encoding = RX_ENC_HT) +#define RX_ENC_HT_GF(s) { s->encoding = RX_ENC_HT; \ + s->enc_flags |= RX_ENC_FLAG_HT_GF; } +#define RX_ENC_VHT(s) (s->encoding = RX_ENC_VHT) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) +#define RX_ENC_HE(s) (s->encoding = RX_ENC_VHT) +#else +#define RX_ENC_HE(s) (s->encoding = RX_ENC_HE) +#endif +#define RX_ENC_FLAG_SHORT_GI(s) (s->enc_flags |= RX_ENC_FLAG_SHORT_GI) +#define RX_ENC_FLAG_SHORT_PRE(s) (s->enc_flags |= RX_ENC_FLAG_SHORTPRE) +#define RX_ENC_FLAG_LDPC(s) (s->enc_flags |= RX_ENC_FLAG_LDPC) +#define RX_BW_40MHZ(s) (s->bw = RATE_INFO_BW_40) +#define RX_BW_80MHZ(s) (s->bw = RATE_INFO_BW_80) +#define RX_BW_160MHZ(s) (s->bw = RATE_INFO_BW_160) +#define RX_NSS(s) s->nss + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) +#define ieee80211_cqm_rssi_notify(vif, event, level, gfp) \ + ieee80211_cqm_rssi_notify(vif, event, gfp) +#endif + +#ifndef CONFIG_VENDOR_RWNX_AMSDUS_TX +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0)) +#define rwnx_ops_ampdu_action(hw, vif, params) \ + rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size) +#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) +#define rwnx_ops_ampdu_action(hw, vif, params) \ + rwnx_ops_ampdu_action(hw, vif, enum ieee80211_ampdu_mlme_action action, \ + struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, \ + bool amsdu) +#endif +#endif /* CONFIG_VENDOR_RWNX_AMSDUS_TX */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +#define IEEE80211_HW_SUPPORT_FAST_XMIT 0 +#define ieee80211_hw_check(hw, feat) (hw->flags & IEEE80211_HW_##feat) +#define ieee80211_hw_set(hw, feat) {hw->flags |= IEEE80211_HW_##feat; } +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) +#define rwnx_ops_sw_scan_start(hw, vif, mac_addr) \ + rwnx_ops_sw_scan_start(hw) +#define rwnx_ops_sw_scan_complete(hw, vif) \ + rwnx_ops_sw_scan_complete(hw) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) +#define rwnx_ops_hw_scan(hw, vif, hw_req) \ + rwnx_ops_hw_scan(hw, vif, struct cfg80211_scan_request *req) +#endif + +/* NET */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) +#define rwnx_select_queue(dev, skb, sb_dev) \ + rwnx_select_queue(dev, skb) +#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) +#define rwnx_select_queue(dev, skb, sb_dev) \ + rwnx_select_queue(dev, skb, void *accel_priv, select_queue_fallback_t fallback) +#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) +#define rwnx_select_queue(dev, skb, sb_dev) \ + rwnx_select_queue(dev, skb, sb_dev, select_queue_fallback_t fallback) +#else +#define rwnx_select_queue(dev, skb, sb_dev) \ + rwnx_select_queue(dev, skb, sb_dev) +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)) && !(defined CONFIG_VENDOR_RWNX) +#define sk_pacing_shift_update(sk, shift) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) +#define alloc_netdev_mqs(size, name, assign, setup, txqs, rxqs) \ + alloc_netdev_mqs(size, name, setup, txqs, rxqs) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) +#define NET_NAME_UNKNOWN 0 +#endif + +/* TRACE */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +#define trace_print_symbols_seq ftrace_print_symbols_seq +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) +#define trace_seq_buffer_ptr(p) (p->buffer + p->len) +#endif + +/* TIME */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) +#define time64_to_tm(t, o, tm) time_to_tm((time_t)t, o, tm) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) +#define ktime_get_real_seconds get_seconds +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) +typedef __s64 time64_t; +#endif + +#endif /* _RWNX_COMPAT_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c new file mode 100644 index 000000000000..f4594f4bcc1d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c @@ -0,0 +1,2325 @@ +/** + ****************************************************************************** + * + * @file rwnx_debugfs.c + * + * @brief Definition of debugfs entries + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + + +#include <linux/kernel.h> +#include <linux/kmod.h> +#include <linux/debugfs.h> +#include <linux/string.h> +#include <linux/sort.h> +#include <linux/vmalloc.h> + +#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:<ALL|KE|DBG|IPC|DMA|MM|TX|RX|PHY>]* " + "[DBG:<NONE|CRT|ERR|WRN|INF|VRB>]\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; + + 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) + + +#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); + +#ifdef CONFIG_RWNX_P2P_DEBUGFS + { + /* Create a p2p directory */ + struct dentry *dir_p2p; + dir_p2p = debugfs_create_dir("p2p", dir_drv); + if (!dir_p2p) + goto err; + + /* Add file allowing to control Opportunistic PS */ + DEBUGFS_ADD_FILE(oppps, dir_p2p, S_IRUSR); + /* Add file allowing to control Notice of Absence */ + DEBUGFS_ADD_FILE(noa, dir_p2p, S_IRUSR); + } +#endif /* CONFIG_RWNX_P2P_DEBUGFS */ + + if (rwnx_hw->fwlog_en) { + rwnx_fw_log_init(&rwnx_hw->debugfs.fw_log); + DEBUGFS_ADD_FILE(fw_log, dir_drv, S_IWUSR | S_IRUSR); + } +#ifdef CONFIG_RWNX_RADAR + { + struct dentry *dir_radar, *dir_sec; + dir_radar = debugfs_create_dir("radar", dir_drv); + if (!dir_radar) + goto err; + + DEBUGFS_ADD_FILE(pulses_prim, dir_radar, S_IRUSR); + DEBUGFS_ADD_FILE(detected, dir_radar, S_IRUSR); + DEBUGFS_ADD_FILE(enable, dir_radar, S_IRUSR); + + if (rwnx_hw->phy.cnt == 2) { + DEBUGFS_ADD_FILE(pulses_sec, dir_radar, S_IRUSR); + + dir_sec = debugfs_create_dir("sec", dir_radar); + if (!dir_sec) + goto err; + + DEBUGFS_ADD_FILE(band, dir_sec, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(type, dir_sec, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(prim20, dir_sec, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(center1, dir_sec, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(center2, dir_sec, S_IWUSR | S_IRUSR); + DEBUGFS_ADD_FILE(set, dir_sec, S_IWUSR | S_IRUSR); + } + } +#endif /* CONFIG_RWNX_RADAR */ + return 0; + +err: + rwnx_dbgfs_unregister(rwnx_hw); + return -ENOMEM; +} + +void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_debugfs *rwnx_debugfs = &rwnx_hw->debugfs; +#ifdef CONFIG_RWNX_FULLMAC + struct rwnx_rc_config_save *cfg, *next; +#endif + +#ifdef CONFIG_RWNX_FULLMAC + list_for_each_entry_safe(cfg, next, &rwnx_debugfs->rc_config_save, list) { + list_del(&cfg->list); + kfree(cfg); + } +#endif /* CONFIG_RWNX_FULLMAC */ + + if (rwnx_hw->fwlog_en) + rwnx_fw_log_deinit(&rwnx_hw->debugfs.fw_log); + + if (!rwnx_hw->debugfs.dir) + return; + + rwnx_debugfs->unregistering = true; +#ifdef CONFIG_RWNX_FULLMAC + flush_work(&rwnx_debugfs->rc_stat_work); +#endif + debugfs_remove_recursive(rwnx_hw->debugfs.dir); + rwnx_hw->debugfs.dir = NULL; +} + +#endif /* CONFIG_DEBUG_FS */ + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.h new file mode 100644 index 000000000000..7f5c7c9c575d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.h @@ -0,0 +1,202 @@ +/** + ****************************************************************************** + * + * @file rwnx_debugfs.h + * + * @brief Miscellaneous utility function definitions + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + + +#ifndef _RWNX_DEBUGFS_H_ +#define _RWNX_DEBUGFS_H_ +#include <linux/version.h> + +#include <linux/workqueue.h> +#include <linux/if_ether.h> +#include "rwnx_fw_trace.h" + +struct rwnx_hw; +struct rwnx_sta; + +/* some macros taken from iwlwifi */ +/* TODO: replace with generic read and fill read buffer in open to avoid double + * reads */ +#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ + if (!debugfs_create_file(#name, mode, parent, rwnx_hw, \ + &rwnx_dbgfs_##name##_ops)) \ + goto err; \ +} while (0) + +#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ +} while (0) + +#define DEBUGFS_ADD_X64(name, parent, ptr) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_x64(#name, S_IWUSR | S_IRUSR, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ +} while (0) + +#define DEBUGFS_ADD_U64(name, parent, ptr, mode) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_u64(#name, mode, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ +} while (0) + +#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ +} while (0) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) +#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ + debugfs_create_u32(#name, mode, \ + parent, ptr); \ +} while (0) +#else +#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \ + struct dentry *__tmp; \ + __tmp = debugfs_create_u32(#name, mode, \ + parent, ptr); \ + if (IS_ERR(__tmp) || !__tmp) \ + goto err; \ + } while (0) +#endif + + + +/* file operation */ +#define DEBUGFS_READ_FUNC(name) \ + static ssize_t rwnx_dbgfs_##name##_read(struct file *file, \ + char __user *user_buf, \ + size_t count, loff_t *ppos); + +#define DEBUGFS_WRITE_FUNC(name) \ + static ssize_t rwnx_dbgfs_##name##_write(struct file *file, \ + const char __user *user_buf,\ + size_t count, loff_t *ppos); + +#define DEBUGFS_OPEN_FUNC(name) \ + static int rwnx_dbgfs_##name##_open(struct inode *inode, \ + struct file *file); + +#define DEBUGFS_RELEASE_FUNC(name) \ + static int rwnx_dbgfs_##name##_release(struct inode *inode, \ + struct file *file); + +#define DEBUGFS_READ_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ +static const struct file_operations rwnx_dbgfs_##name##_ops = { \ + .read = rwnx_dbgfs_##name##_read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_WRITE_FILE_OPS(name) \ + DEBUGFS_WRITE_FUNC(name); \ +static const struct file_operations rwnx_dbgfs_##name##_ops = { \ + .write = rwnx_dbgfs_##name##_write, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ + DEBUGFS_WRITE_FUNC(name); \ +static const struct file_operations rwnx_dbgfs_##name##_ops = { \ + .write = rwnx_dbgfs_##name##_write, \ + .read = rwnx_dbgfs_##name##_read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_READ_WRITE_OPEN_RELEASE_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ + DEBUGFS_WRITE_FUNC(name); \ + DEBUGFS_OPEN_FUNC(name); \ + DEBUGFS_RELEASE_FUNC(name); \ +static const struct file_operations rwnx_dbgfs_##name##_ops = { \ + .write = rwnx_dbgfs_##name##_write, \ + .read = rwnx_dbgfs_##name##_read, \ + .open = rwnx_dbgfs_##name##_open, \ + .release = rwnx_dbgfs_##name##_release, \ + .llseek = generic_file_llseek, \ +}; + + +#ifdef CONFIG_RWNX_DEBUGFS + +struct rwnx_debugfs { + unsigned long long rateidx; + struct dentry *dir; + bool trace_prst; + + char helper_cmd[64]; + //struct work_struct helper_work; + bool helper_scheduled; + spinlock_t umh_lock; + bool unregistering; + +#ifndef CONFIG_RWNX_FHOST + struct rwnx_fw_log fw_log; +#endif /* CONFIG_RWNX_FHOST */ + +#ifdef CONFIG_RWNX_FULLMAC + struct work_struct rc_stat_work; + uint8_t rc_sta[NX_REMOTE_STA_MAX]; + uint8_t rc_write; + uint8_t rc_read; + struct dentry *dir_rc; + struct dentry *dir_sta[NX_REMOTE_STA_MAX]; + int rc_config[NX_REMOTE_STA_MAX]; + struct list_head rc_config_save; +#endif +}; + +#ifdef CONFIG_RWNX_FULLMAC + +// Max duration in msecs to save rate config for a sta after disconnection +#define RC_CONFIG_DUR 600000 + +struct rwnx_rc_config_save { + struct list_head list; + unsigned long timestamp; + int rate; + u8 mac_addr[ETH_ALEN]; +}; +#endif + +int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name); +void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw); +#ifdef CONFIG_RWNX_FULLMAC +void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); +void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); +#endif +#else +struct rwnx_debugfs { +}; +static inline int rwnx_dbgfs_register(struct rwnx_hw *rwnx_hw, const char *name) { return 0; } +static inline void rwnx_dbgfs_unregister(struct rwnx_hw *rwnx_hw) {} +#ifdef CONFIG_RWNX_FULLMAC +static inline void rwnx_dbgfs_register_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} +static inline void rwnx_dbgfs_unregister_rc_stat(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) {} +#endif +#endif /* CONFIG_RWNX_DEBUGFS */ + + +#endif /* _RWNX_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h new file mode 100644 index 000000000000..4e966dee2fad --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h @@ -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 <linux/interrupt.h> +#include <linux/device.h> +#include <linux/dmapool.h> +#include <linux/skbuff.h> +#include <net/cfg80211.h> +#include <linux/slab.h> + +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_dini.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_dini.c new file mode 100644 index 000000000000..17d55da1156f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_dini.c @@ -0,0 +1,297 @@ +/** + ****************************************************************************** + * + * @file rwnx_dini.c - Add support for dini platform + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#include "rwnx_dini.h" +#include "rwnx_defs.h" +#include "rwnx_irqs.h" +#include "reg_access.h" + +/* Config FPGA is accessed via bar0 */ +#define CFPGA_DMA0_CTRL_REG 0x02C +#define CFPGA_DMA1_CTRL_REG 0x04C +#define CFPGA_DMA2_CTRL_REG 0x06C +#define CFPGA_UINTR_SRC_REG 0x0E8 +#define CFPGA_UINTR_MASK_REG 0x0EC +#define CFPGA_BAR4_HIADDR_REG 0x100 +#define CFPGA_BAR4_LOADDR_REG 0x104 +#define CFPGA_BAR4_LOADDR_MASK_REG 0x110 +#define CFPGA_BAR_TOUT 0x120 + +#define CFPGA_DMA_CTRL_ENABLE 0x00001400 +#define CFPGA_DMA_CTRL_DISABLE 0x00001000 +#define CFPGA_DMA_CTRL_CLEAR 0x00001800 +#define CFPGA_DMA_CTRL_REREAD_TIME_MASK (BIT(10) - 1) + +#define CFPGA_BAR4_LOADDR_MASK_MAX 0xFF000000 + +#define CFPGA_PCIEX_IT 0x00000001 +#define CFPGA_ALL_ITS 0x0000000F + +/* Programmable BAR4 Window start address */ +#define CPU_RAM_WINDOW_HIGH 0x00000000 +#define CPU_RAM_WINDOW_LOW 0x00000000 +#define AHB_BRIDGE_WINDOW_HIGH 0x00000000 +#define AHB_BRIDGE_WINDOW_LOW 0x60000000 + +struct rwnx_dini { + u8 *pci_bar0_vaddr; + u8 *pci_bar4_vaddr; +}; + +static const u32 mv_cfg_fpga_dma_ctrl_regs[] = { + CFPGA_DMA0_CTRL_REG, + CFPGA_DMA1_CTRL_REG, + CFPGA_DMA2_CTRL_REG +}; + +/* This also clears running transactions */ +static void dini_dma_on(struct rwnx_dini *rwnx_dini) +{ + int i; + u32 reread_time; + volatile void *reg; + + for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { + reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; + reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; + + writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); + writel(CFPGA_DMA_CTRL_ENABLE | reread_time, reg); + } +} + +/* This also clears running transactions */ +static void dini_dma_off(struct rwnx_dini *rwnx_dini) +{ + int i; + u32 reread_time; + volatile void *reg; + + for (i = 0; i < ARRAY_SIZE(mv_cfg_fpga_dma_ctrl_regs); i++) { + reg = rwnx_dini->pci_bar0_vaddr + mv_cfg_fpga_dma_ctrl_regs[i]; + reread_time = readl(reg) & CFPGA_DMA_CTRL_REREAD_TIME_MASK; + + writel(CFPGA_DMA_CTRL_DISABLE | reread_time, reg); + writel(CFPGA_DMA_CTRL_CLEAR | reread_time, reg); + } +} + + +/* Configure address range for BAR4. + * By default BAR4_LOADDR_MASK value is 0xFF000000, then there is no need to + * change it because the addresses we need to access are covered by this mask + */ +static void dini_set_bar4_win(u32 low, u32 high, struct rwnx_dini *rwnx_dini) +{ + writel(low, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_REG); + writel(high, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_HIADDR_REG); + writel(CFPGA_BAR4_LOADDR_MASK_MAX, + rwnx_dini->pci_bar0_vaddr + CFPGA_BAR4_LOADDR_MASK_REG); +} + + +/** + * Enable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 + * and request the corresponding IRQ line + */ +int rwnx_cfpga_irq_enable(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + unsigned int cfpga_uintr_mask; + volatile void *reg; + int ret; + + /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ + ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, "rwnx", rwnx_hw); + if (ret) + return ret; + + reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; + cfpga_uintr_mask = readl(reg); + writel(cfpga_uintr_mask | CFPGA_PCIEX_IT, reg); + + return ret; +} + +/** + * Disable User Interrupts of CFPGA that trigger PCIe IRQs on PCIE_10 + * and free the corresponding IRQ line + */ +int rwnx_cfpga_irq_disable(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + unsigned int cfpga_uintr_mask; + volatile void *reg; + + reg = rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_MASK_REG; + cfpga_uintr_mask = readl(reg); + writel(cfpga_uintr_mask & ~CFPGA_PCIEX_IT, reg); + + free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); + + return 0; +} + +static int rwnx_dini_platform_enable(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + +#ifdef CONFIG_RWNX_SDM + writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); +#endif + + dini_dma_on(rwnx_dini); + return rwnx_cfpga_irq_enable(rwnx_hw); +} + +static int rwnx_dini_platform_disable(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + int ret; + + ret = rwnx_cfpga_irq_disable(rwnx_hw); + dini_dma_off(rwnx_dini); + return ret; +} + +static void rwnx_dini_platform_deinit(struct rwnx_plat *rwnx_plat) +{ + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + + pci_disable_device(rwnx_plat->pci_dev); + iounmap(rwnx_dini->pci_bar0_vaddr); + iounmap(rwnx_dini->pci_bar4_vaddr); + pci_release_regions(rwnx_plat->pci_dev); + + kfree(rwnx_plat); +} + +static u8 *rwnx_dini_get_address(struct rwnx_plat *rwnx_plat, int addr_name, + unsigned int offset) +{ + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + + if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) + return NULL; + + if (addr_name == RWNX_ADDR_CPU) + dini_set_bar4_win(CPU_RAM_WINDOW_LOW, CPU_RAM_WINDOW_HIGH, rwnx_dini); + else + dini_set_bar4_win(AHB_BRIDGE_WINDOW_LOW, AHB_BRIDGE_WINDOW_HIGH, rwnx_dini); + + return rwnx_dini->pci_bar4_vaddr + offset; +} + +static void rwnx_dini_ack_irq(struct rwnx_plat *rwnx_plat) +{ + struct rwnx_dini *rwnx_dini = (struct rwnx_dini *)rwnx_plat->priv; + + writel(CFPGA_ALL_ITS, rwnx_dini->pci_bar0_vaddr + CFPGA_UINTR_SRC_REG); +} + +static const u32 rwnx_dini_config_reg[] = { + NXMAC_DEBUG_PORT_SEL_ADDR, + SYSCTRL_DIAG_CONF_ADDR, + RF_V6_DIAGPORT_CONF1_ADDR, + RF_v6_PHYDIAG_CONF1_ADDR, +}; + +static int rwnx_dini_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) +{ + if (!list) + return 0; + + *list = rwnx_dini_config_reg; + return ARRAY_SIZE(rwnx_dini_config_reg); +} + +/** + * rwnx_dini_platform_init - Initialize the DINI platform + * + * @pci_dev PCI device + * @rwnx_plat Pointer on struct rwnx_stat * to be populated + * + * @return 0 on success, < 0 otherwise + * + * Allocate and initialize a rwnx_plat structure for the dini platform. + */ +int rwnx_dini_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) +{ + struct rwnx_dini *rwnx_dini; + u16 pci_cmd; + int ret = 0; + + *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_dini), + GFP_KERNEL); + if (!*rwnx_plat) + return -ENOMEM; + + rwnx_dini = (struct rwnx_dini *)(*rwnx_plat)->priv; + + /* Hotplug fixups */ + pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); + pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); + //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); + + ret = pci_enable_device(pci_dev); + if (ret) { + dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); + goto out_enable; + } + + pci_set_master(pci_dev); +#if 0 + ret = pci_request_regions(pci_dev, KBUILD_MODNAME); + if (ret) { + dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); + goto out_request; + } +#endif + rwnx_dini->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); + if (!rwnx_dini->pci_bar0_vaddr) { + dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); + ret = -ENOMEM; + goto out_bar0; + } + rwnx_dini->pci_bar4_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 4); + if (!rwnx_dini->pci_bar4_vaddr) { + dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 4); + ret = -ENOMEM; + goto out_bar4; + } + + (*rwnx_plat)->enable = rwnx_dini_platform_enable; + (*rwnx_plat)->disable = rwnx_dini_platform_disable; + (*rwnx_plat)->deinit = rwnx_dini_platform_deinit; + (*rwnx_plat)->get_address = rwnx_dini_get_address; + (*rwnx_plat)->ack_irq = rwnx_dini_ack_irq; + (*rwnx_plat)->get_config_reg = rwnx_dini_get_config_reg; + +#ifdef CONFIG_RWNX_SDM + writel(0x0000FFFF, rwnx_dini->pci_bar0_vaddr + CFPGA_BAR_TOUT); +#endif + + return 0; + +out_bar4: + iounmap(rwnx_dini->pci_bar0_vaddr); +out_bar0: + pci_release_regions(pci_dev); +//out_request: + pci_disable_device(pci_dev); +out_enable: + kfree(*rwnx_plat); + return ret; +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_dini.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_dini.h new file mode 100644 index 000000000000..d9f57c10ed4f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_dini.h @@ -0,0 +1,20 @@ +/** + **************************************************************************************** + * + * @file rwnx_dini.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_DINI_H_ +#define _RWNX_DINI_H_ + +#include <linux/pci.h> +#include "rwnx_platform.h" + +int rwnx_dini_platform_init(struct pci_dev *pci_dev, + struct rwnx_plat **rwnx_plat); + +#endif /* _RWNX_DINI_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_events.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_events.h new file mode 100644 index 000000000000..3bd59807f663 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_events.h @@ -0,0 +1,1326 @@ +/** + ****************************************************************************** + * + * @file rwnx_events.h + * + * @brief Trace events definition + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM rwnx + +#if !defined(_RWNX_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _RWNX_EVENTS_H + +#include <linux/tracepoint.h> +#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 <linux/trace_seq.h> + +/* 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 <linux/trace_seq.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +#include <linux/trace_events.h> +#else +#include <linux/ftrace_event.h> +#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 <trace/define_trace.h> diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.c new file mode 100644 index 000000000000..9151c8b81f59 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.c @@ -0,0 +1,48 @@ +/** + ****************************************************************************** + * + * @file rwnx_fw_trace.c + * + * Copyright (C) RivieraWaves 2017-2019 + * + ****************************************************************************** + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/delay.h> +#include "rwnx_fw_trace.h" +#include "aicwf_debug.h" + +int rwnx_fw_log_init(struct rwnx_fw_log *fw_log) +{ + u8 *buf = kmalloc(FW_LOG_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + fw_log->buf.data = buf; + fw_log->buf.start = fw_log->buf.data; + fw_log->buf.size = 0; + fw_log->buf.end = fw_log->buf.data; + fw_log->buf.dataend = fw_log->buf.data + FW_LOG_SIZE; + spin_lock_init(&fw_log->lock); + + AICWFDBG(LOGINFO, "fw_log_init: %lx, %lx\n", (unsigned long)fw_log->buf.start, (unsigned long)(fw_log->buf.dataend)); + return 0; +} + +void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log) +{ + if (!fw_log) + return; + + if (fw_log->buf.data) + kfree(fw_log->buf.data); + fw_log->buf.start = NULL; + fw_log->buf.end = NULL; + fw_log->buf.size = 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.h new file mode 100644 index 000000000000..7956790957c3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_fw_trace.h @@ -0,0 +1,35 @@ +/** + ****************************************************************************** + * + * rwnx_fw_trace.h + * + * Copyright (C) RivieraWaves 2017-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_FW_TRACE_H_ +#define _RWNX_FW_TRACE_H_ + +#include <linux/mutex.h> +#include <linux/wait.h> +#include <linux/workqueue.h> + +#define FW_LOG_SIZE (10240) + +struct rwnx_fw_log_buf { + uint8_t *data; + uint8_t *start; + uint8_t *end; + uint8_t *dataend; + uint32_t size; +}; + +struct rwnx_fw_log { + struct rwnx_fw_log_buf buf; + spinlock_t lock; +}; + +int rwnx_fw_log_init(struct rwnx_fw_log *fw_log); +void rwnx_fw_log_deinit(struct rwnx_fw_log *fw_log); +#endif /* _RWNX_FW_TRACE_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_gki.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_gki.c new file mode 100644 index 000000000000..7f6333d91e59 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_gki.c @@ -0,0 +1,408 @@ +#include <linux/version.h> +#ifdef ANDROID_PLATFORM +#include "net/wireless/core.h" +#endif +#include <include/linux/types.h> + +#undef NL80211_MCGRP_MLME +#define NL80211_MCGRP_MLME 3 +//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + +static struct genl_family rwnx_nl80211_fam; + +static bool __rwnx_cfg80211_unexpected_frame(struct net_device *dev, u8 cmd, + const u8 *addr, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct sk_buff *msg; + void *hdr; + u32 nlportid = READ_ONCE(wdev->ap_unexpected_nlportid); + + if (!nlportid) + return false; + + msg = nlmsg_new(100, gfp); + if (!msg) + return true; + + hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, cmd); + if (!hdr) { + nlmsg_free(msg); + return true; + } + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); + return true; + + nla_put_failure: + nlmsg_free(msg); + return true; +} + +bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + bool ret; + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO)) { + return false; + } + ret = __rwnx_cfg80211_unexpected_frame(dev, NL80211_CMD_UNEXPECTED_FRAME, + addr, gfp); + return ret; +} + +bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + bool ret; + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO && + wdev->iftype != NL80211_IFTYPE_AP_VLAN)) { + return false; + } + ret = __rwnx_cfg80211_unexpected_frame(dev, + NL80211_CMD_UNEXPECTED_4ADDR_FRAME, + addr, gfp); + return ret; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) +void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, + const u8 *ie, u8 ie_len, + int sig_dbm, gfp_t gfp) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct sk_buff *msg; + void *hdr; + + if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT)) + return; + + msg = nlmsg_new(100 + ie_len, gfp); + if (!msg) + return; + + hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_NEW_PEER_CANDIDATE); + if (!hdr) { + nlmsg_free(msg); + return; + } + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || + (ie_len && ie && + nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) || + (sig_dbm && + nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm))) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + +#define NL80211_MCGRP_MLME 3 + genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, + NL80211_MCGRP_MLME, gfp); + return; + + nla_put_failure: + nlmsg_free(msg); +} +#endif + +void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, + const u8 *frame, size_t len, + int freq, int sig_dbm) +{ + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct sk_buff *msg; + void *hdr; + struct cfg80211_beacon_registration *reg; + + spin_lock_bh(&rdev->beacon_registrations_lock); + list_for_each_entry(reg, &rdev->beacon_registrations, list) { + msg = nlmsg_new(len + 100, GFP_ATOMIC); + if (!msg) { + spin_unlock_bh(&rdev->beacon_registrations_lock); + return; + } + + hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, NL80211_CMD_FRAME); + if (!hdr) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + (freq && + nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || + (sig_dbm && + nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || + nla_put(msg, NL80211_ATTR_FRAME, len, frame)) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, reg->nlportid); + } + spin_unlock_bh(&rdev->beacon_registrations_lock); + return; + + nla_put_failure: + spin_unlock_bh(&rdev->beacon_registrations_lock); + nlmsg_free(msg); +} + +static int rwnx_nl80211_send_chandef(struct sk_buff *msg, + const struct cfg80211_chan_def *chandef) +{ + if (WARN_ON(!cfg80211_chandef_valid(chandef))) + return -EINVAL; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, + chandef->chan->center_freq)) + return -ENOBUFS; + switch (chandef->width) { + case NL80211_CHAN_WIDTH_20_NOHT: + case NL80211_CHAN_WIDTH_20: + case NL80211_CHAN_WIDTH_40: + if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, + cfg80211_get_chandef_type(chandef))) + return -ENOBUFS; + break; + default: + break; + } + if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, chandef->width)) + return -ENOBUFS; + if (nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, chandef->center_freq1)) + return -ENOBUFS; + if (chandef->center_freq2 && + nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, chandef->center_freq2)) + return -ENOBUFS; + return 0; +} + +void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + struct cfg80211_chan_def *chandef, + gfp_t gfp, + enum nl80211_commands notif, + u8 count) +{ + struct sk_buff *msg; + void *hdr; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = genlmsg_put(msg, 0, 0, &rwnx_nl80211_fam, 0, notif); + if (!hdr) { + nlmsg_free(msg); + return; + } + + if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) + goto nla_put_failure; + + if (rwnx_nl80211_send_chandef(msg, chandef)) + goto nla_put_failure; + + if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) && + (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count))) + goto nla_put_failure; + + genlmsg_end(msg, hdr); + + genlmsg_multicast_netns(&rwnx_nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, + NL80211_MCGRP_MLME, gfp); + return; + + nla_put_failure: + nlmsg_free(msg); +} + +void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, + struct cfg80211_chan_def *chandef, + u8 count + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) + , bool quiet + #endif + ) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + + rwnx_cfg80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, + NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count); +} + +int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, + struct ieee80211_regdomain *rd) +{ + wiphy_apply_custom_regulatory(wiphy, rd); + return 0; +} + +void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) +{ + unsigned long flags; + struct sk_buff *prev = old; + struct sk_buff *next = prev->next; + spin_lock_irqsave(&list->lock, flags); + WRITE_ONCE(newsk->next, next); + WRITE_ONCE(newsk->prev, prev); + WRITE_ONCE(next->prev, newsk); + WRITE_ONCE(prev->next, newsk); + list->qlen++; + spin_unlock_irqrestore(&list->lock, flags); +} + +bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, + u8 *op_class) +{ + u8 vht_opclass; + u32 freq = chandef->center_freq1; + + if (freq >= 2412 && freq <= 2472) { + if (chandef->width > NL80211_CHAN_WIDTH_40) + return false; + + /* 2.407 GHz, channels 1..13 */ + if (chandef->width == NL80211_CHAN_WIDTH_40) { + if (freq > chandef->chan->center_freq) + *op_class = 83; /* HT40+ */ + else + *op_class = 84; /* HT40- */ + } else { + *op_class = 81; + } + + return true; + } + + if (freq == 2484) { + /* channel 14 is only for IEEE 802.11b */ + if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT) + return false; + + *op_class = 82; /* channel 14 */ + return true; + } + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_80: + vht_opclass = 128; + break; + case NL80211_CHAN_WIDTH_160: + vht_opclass = 129; + break; + case NL80211_CHAN_WIDTH_80P80: + vht_opclass = 130; + break; + case NL80211_CHAN_WIDTH_10: + case NL80211_CHAN_WIDTH_5: + return false; /* unsupported for now */ + default: + vht_opclass = 0; + break; + } + + /* 5 GHz, channels 36..48 */ + if (freq >= 5180 && freq <= 5240) { + if (vht_opclass) { + *op_class = vht_opclass; + } else if (chandef->width == NL80211_CHAN_WIDTH_40) { + if (freq > chandef->chan->center_freq) + *op_class = 116; + else + *op_class = 117; + } else { + *op_class = 115; + } + + return true; + } + + /* 5 GHz, channels 52..64 */ + if (freq >= 5260 && freq <= 5320) { + if (vht_opclass) { + *op_class = vht_opclass; + } else if (chandef->width == NL80211_CHAN_WIDTH_40) { + if (freq > chandef->chan->center_freq) + *op_class = 119; + else + *op_class = 120; + } else { + *op_class = 118; + } + + return true; + } + + /* 5 GHz, channels 100..144 */ + if (freq >= 5500 && freq <= 5720) { + if (vht_opclass) { + *op_class = vht_opclass; + } else if (chandef->width == NL80211_CHAN_WIDTH_40) { + if (freq > chandef->chan->center_freq) + *op_class = 122; + else + *op_class = 123; + } else { + *op_class = 121; + } + + return true; + } + + /* 5 GHz, channels 149..169 */ + if (freq >= 5745 && freq <= 5845) { + if (vht_opclass) { + *op_class = vht_opclass; + } else if (chandef->width == NL80211_CHAN_WIDTH_40) { + if (freq > chandef->chan->center_freq) + *op_class = 126; + else + *op_class = 127; + } else if (freq <= 5805) { + *op_class = 124; + } else { + *op_class = 125; + } + + return true; + } + + /* 56.16 GHz, channel 1..4 */ + if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) { + if (chandef->width >= NL80211_CHAN_WIDTH_40) + return false; + + *op_class = 180; + return true; + } + + /* not supported yet */ + return false; +} + +int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait) +{ + return -1; +} + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_gki.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_gki.h new file mode 100644 index 000000000000..a41f57832279 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_gki.h @@ -0,0 +1,72 @@ +#ifndef __RWNX_GKI_H +#define __RWNX_GKI_H + +#ifdef ANDROID_PLATFORM +#include "net/wireless/core.h" +#endif + +//#if IS_ENABLED(CONFIG_GKI_OPT_FEATURES) && IS_ENABLED(CONFIG_ANDROID) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)) + + +bool rwnx_cfg80211_rx_spurious_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp); + +bool rwnx_cfg80211_rx_unexpected_4addr_frame(struct net_device *dev, + const u8 *addr, gfp_t gfp); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) +void rwnx_cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr, + const u8 *ie, u8 ie_len, + int sig_dbm, gfp_t gfp); +#endif + +void rwnx_cfg80211_report_obss_beacon(struct wiphy *wiphy, + const u8 *frame, size_t len, + int freq, int sig_dbm); + +void rwnx_cfg80211_ch_switch_notify(struct cfg80211_registered_device *rdev, + struct net_device *netdev, + struct cfg80211_chan_def *chandef, + gfp_t gfp, + enum nl80211_commands notif, + u8 count); + +void rwnx_cfg80211_ch_switch_started_notify(struct net_device *dev, + struct cfg80211_chan_def *chandef, + u8 count + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) + , bool quiet + #endif + ); + +int rwnx_regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, + struct ieee80211_regdomain *rd); + +void rwnx_skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list); + +bool rwnx_ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, + u8 *op_class); + +int rwnx_call_usermodehelper(const char *path, char **argv, char **envp, int wait); + +#else + +#define rwnx_cfg80211_rx_spurious_frame cfg80211_rx_spurious_frame +#define rwnx_cfg80211_rx_unexpected_4addr_frame cfg80211_rx_unexpected_4addr_frame + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) +#define rwnx_cfg80211_notify_new_peer_candidate cfg80211_notify_new_peer_candidate +#endif + +#define rwnx_cfg80211_report_obss_beacon cfg80211_report_obss_beacon +#define rwnx_cfg80211_ch_switch_notify cfg80211_ch_switch_notify +#define rwnx_cfg80211_ch_switch_started_notify cfg80211_ch_switch_started_notify +#define rwnx_regulatory_set_wiphy_regd_sync_rtnl regulatory_set_wiphy_regd_sync_rtnl +#define rwnx_skb_append skb_append +#define rwnx_ieee80211_chandef_to_operating_class ieee80211_chandef_to_operating_class +#define rwnx_call_usermodehelper call_usermodehelper + +#endif + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_irqs.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_irqs.c new file mode 100644 index 000000000000..8ba95b703f17 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_irqs.c @@ -0,0 +1,65 @@ +/** + ****************************************************************************** + * + * @file rwnx_irqs.c + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#include <linux/interrupt.h> + +#include "rwnx_defs.h" +#include "ipc_host.h" +#include "rwnx_prof.h" + +/** + * rwnx_irq_hdlr - IRQ handler + * + * Handler registerd by the platform driver + */ +irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id) +{ + struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)dev_id; + disable_irq_nosync(irq); + tasklet_schedule(&rwnx_hw->task); + return IRQ_HANDLED; +} + +/** + * rwnx_task - Bottom half for IRQ handler + * + * Read irq status and process accordingly + */ +void rwnx_task(unsigned long data) +{ + struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)data; + +#if 0 + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + u32 status, statuses = 0; + + /* Ack unconditionnally in case ipc_host_get_status does not see the irq */ + rwnx_plat->ack_irq(rwnx_plat); + + while ((status = ipc_host_get_status(rwnx_hw->ipc_env))) { + statuses |= status; + /* All kinds of IRQs will be handled in one shot (RX, MSG, DBG, ...) + * this will ack IPC irqs not the cfpga irqs */ + ipc_host_irq(rwnx_hw->ipc_env, status); + + rwnx_plat->ack_irq(rwnx_plat); + } +#endif + //if (statuses & IPC_IRQ_E2A_RXDESC) + // rwnx_hw->stats.last_rx = now; + //if (statuses & IPC_IRQ_E2A_TXCFM) + // rwnx_hw->stats.last_tx = now; + + spin_lock_bh(&rwnx_hw->tx_lock); + rwnx_hwq_process_all(rwnx_hw); + spin_unlock_bh(&rwnx_hw->tx_lock); +#if 0 + enable_irq(rwnx_platform_get_irq(rwnx_plat)); +#endif +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_irqs.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_irqs.h new file mode 100644 index 000000000000..d3fb4519c615 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_irqs.h @@ -0,0 +1,20 @@ +/** + ****************************************************************************** + * + * @file rwnx_irqs.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#ifndef _RWNX_IRQS_H_ +#define _RWNX_IRQS_H_ + +#include <linux/interrupt.h> + +/* IRQ handler to be registered by platform driver */ +irqreturn_t rwnx_irq_hdlr(int irq, void *dev_id); + +void rwnx_task(unsigned long data); + +#endif /* _RWNX_IRQS_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c new file mode 100644 index 000000000000..9b35c0d43d03 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c @@ -0,0 +1,7279 @@ +/** + ****************************************************************************** + * + * @file rwnx_main.c + * + * @brief Entry point of the RWNX driver + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/inetdevice.h> +#include <net/cfg80211.h> +#include <net/ip.h> +#include <linux/etherdevice.h> +#include <linux/netdevice.h> +#include <net/netlink.h> +#include <linux/wireless.h> +#include <linux/if_arp.h> +#include <linux/ctype.h> +#include <linux/random.h> +#include <linux/vmalloc.h> +#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" + + +#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), + .num_different_channels = NX_CHAN_CTXT_CNT, + .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; */ +int aicwf_dbg_level = LOGERROR; +module_param(aicwf_dbg_level, int, 0660); +int testmode = 0; +char aic_fw_path[200]; +u8 chip_sub_id = 0; +u8 chip_mcu_id = 0; +u8 chip_id = 0; + +int rwnx_init_cmd_array(void); +void rwnx_free_cmd_array(void); + + +/********************************************************************* + * helper + *********************************************************************/ +struct rwnx_sta *rwnx_get_sta(struct rwnx_hw *rwnx_hw, const u8 *mac_addr) +{ + int i; + + for (i = 0; i < NX_REMOTE_STA_MAX; i++) { + struct rwnx_sta *sta = &rwnx_hw->sta_table[i]; + if (sta->valid && (memcmp(mac_addr, &sta->mac_addr, 6) == 0)) + return sta; + } + + return NULL; +} + +void rwnx_enable_wapi(struct rwnx_hw *rwnx_hw) +{ + //cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_SMS4; + rwnx_hw->wiphy->n_cipher_suites++; + rwnx_hw->wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; +} + +void rwnx_enable_mfp(struct rwnx_hw *rwnx_hw) +{ + cipher_suites[rwnx_hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC; + rwnx_hw->wiphy->n_cipher_suites++; +} + +u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new) +{ + u8 *buf, *pos; + + if (new->head) { + u8 *head = kmalloc(new->head_len, GFP_KERNEL); + + if (!head) + return NULL; + + if (bcn->head) + kfree(bcn->head); + + bcn->head = head; + bcn->head_len = new->head_len; + memcpy(bcn->head, new->head, new->head_len); + } + if (new->tail) { + u8 *tail = kmalloc(new->tail_len, GFP_KERNEL); + + if (!tail) + return NULL; + + if (bcn->tail) + kfree(bcn->tail); + + bcn->tail = tail; + bcn->tail_len = new->tail_len; + memcpy(bcn->tail, new->tail, new->tail_len); + } + + if (!bcn->head) + return NULL; + + bcn->tim_len = 6; + bcn->len = bcn->head_len + bcn->tail_len + bcn->ies_len + bcn->tim_len; + + buf = kmalloc(bcn->len, GFP_KERNEL); + if (!buf) + return NULL; + + // Build the beacon buffer + pos = buf; + memcpy(pos, bcn->head, bcn->head_len); + pos += bcn->head_len; + *pos++ = WLAN_EID_TIM; + *pos++ = 4; + *pos++ = 0; + *pos++ = bcn->dtim; + *pos++ = 0; + *pos++ = 0; + if (bcn->tail) { + memcpy(pos, bcn->tail, bcn->tail_len); + pos += bcn->tail_len; + } + if (bcn->ies) { + memcpy(pos, bcn->ies, bcn->ies_len); + } + + return buf; +} + + +static void rwnx_del_bcn(struct rwnx_bcn *bcn) +{ + if (bcn->head) { + kfree(bcn->head); + bcn->head = NULL; + } + bcn->head_len = 0; + + if (bcn->tail) { + kfree(bcn->tail); + bcn->tail = NULL; + } + bcn->tail_len = 0; + + if (bcn->ies) { + kfree(bcn->ies); + bcn->ies = NULL; + } + bcn->ies_len = 0; + bcn->tim_len = 0; + bcn->dtim = 0; + bcn->len = 0; +} + +/** + * Link channel ctxt to a vif and thus increments count for this context. + */ +void rwnx_chanctx_link(struct rwnx_vif *vif, u8 ch_idx, + struct cfg80211_chan_def *chandef) +{ + struct rwnx_chanctx *ctxt; + + if (ch_idx >= NX_CHAN_CTXT_CNT) { + WARN(1, "Invalid channel ctxt id %d", ch_idx); + return; + } + + vif->ch_index = ch_idx; + ctxt = &vif->rwnx_hw->chanctx_table[ch_idx]; + ctxt->count++; + + // For now chandef is NULL for STATION interface + if (chandef) { + if (!ctxt->chan_def.chan) + ctxt->chan_def = *chandef; + else { + // TODO. check that chandef is the same as the one already + // set for this ctxt + } + } +} + +/** + * Unlink channel ctxt from a vif and thus decrements count for this context + */ +void rwnx_chanctx_unlink(struct rwnx_vif *vif) +{ + struct rwnx_chanctx *ctxt; + + if (vif->ch_index == RWNX_CH_NOT_SET) + return; + + ctxt = &vif->rwnx_hw->chanctx_table[vif->ch_index]; + + if (ctxt->count == 0) { + WARN(1, "Chan ctxt ref count is already 0"); + } else { + ctxt->count--; + } + + if (ctxt->count == 0) { + if (vif->ch_index == vif->rwnx_hw->cur_chanctx) { + /* If current chan ctxt is no longer linked to a vif + disable radar detection (no need to check if it was activated) */ + rwnx_radar_detection_enable(&vif->rwnx_hw->radar, + RWNX_RADAR_DETECT_DISABLE, + RWNX_RADAR_RIU); + } + /* set chan to null, so that if this ctxt is relinked to a vif that + don't have channel information, don't use wrong information */ + ctxt->chan_def.chan = NULL; + } + vif->ch_index = RWNX_CH_NOT_SET; +} + +int rwnx_chanctx_valid(struct rwnx_hw *rwnx_hw, u8 ch_idx) +{ + if (ch_idx >= NX_CHAN_CTXT_CNT || + rwnx_hw->chanctx_table[ch_idx].chan_def.chan == NULL) { + return 0; + } + + return 1; +} + +static void rwnx_del_csa(struct rwnx_vif *vif) +{ + struct rwnx_csa *csa = vif->ap.csa; + + if (!csa) + return; + + rwnx_del_bcn(&csa->bcn); + kfree(csa); + vif->ap.csa = NULL; +} +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +static void rwnx_csa_finish(struct work_struct *ws) +{ + struct rwnx_csa *csa = container_of(ws, struct rwnx_csa, work); + struct rwnx_vif *vif = csa->vif; + struct rwnx_hw *rwnx_hw = vif->rwnx_hw; + int error = csa->status; + u8 *buf, *pos; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + buf = kmalloc(csa->bcn.len, GFP_KERNEL); + if (!buf) { + printk ("%s buf fail\n", __func__); + return; + } + pos = buf; + + memcpy(pos, csa->bcn.head, csa->bcn.head_len); + pos += csa->bcn.head_len; + *pos++ = WLAN_EID_TIM; + *pos++ = 4; + *pos++ = 0; + *pos++ = csa->bcn.dtim; + *pos++ = 0; + *pos++ = 0; + if (csa->bcn.tail) { + memcpy(pos, csa->bcn.tail, csa->bcn.tail_len); + pos += csa->bcn.tail_len; + } + if (csa->bcn.ies) { + memcpy(pos, csa->bcn.ies, csa->bcn.ies_len); + } + + if (!error) { + error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, csa->bcn.len); + if (error) + return; + error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, + csa->bcn.len, csa->bcn.head_len, + csa->bcn.tim_len, NULL); + } + + if (error) { + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) + cfg80211_stop_iface(rwnx_hw->wiphy, &vif->wdev, GFP_KERNEL); + #else + cfg80211_disconnected(vif->ndev, 0, NULL, 0, 0, GFP_KERNEL); + #endif + } else { + 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 */ + set_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); + atomic_set(&rwnx_vif->drv_conn_state, RWNX_DRV_STATUS_DISCONNECTED); + } + #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 + + 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; + mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); + atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); + } + } + + 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)){ +#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 + clear_bit(RWNX_DEV_STARTED, &rwnx_vif->drv_flags); + } +#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 + +#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, +}; + +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 = 0; + } + 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_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_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) + +static int rwnx_do_ioctl(struct net_device *net, struct ifreq *req, int cmd) +{ + 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, + .ndo_do_ioctl = rwnx_do_ioctl, + .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) +{ + 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; + mod_timer(&rwnx_hw->p2p_alive_timer, jiffies + msecs_to_jiffies(1000)); + atomic_set(&rwnx_hw->p2p_alive_timer_count, 0); + } 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 = false; + 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; +} + +/** + * @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); + 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 + int link_id, + 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 <linux/rfkill-wlan.h> +#endif +#ifdef CONFIG_PLATFORM_ROCKCHIP2 +#include <linux/rfkill-wlan.h> +#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_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 + flush_workqueue(rwnx_hw->apmStaloss_wq); + destroy_workqueue(rwnx_hw->apmStaloss_wq); + + rwnx_wdev_unregister(rwnx_hw); + wiphy_unregister(rwnx_hw->wiphy); + rwnx_radar_detection_deinit(&rwnx_hw->radar); + rwnx_platform_off(rwnx_hw, NULL); + kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); +#ifdef CONFIG_FILTER_TCP_ACK + tcp_ack_deinit(rwnx_hw); +#endif + aicwf_wakeup_lock_deinit(rwnx_hw); + wiphy_free(rwnx_hw->wiphy); +} + +static void aicsmac_driver_register(void) +{ +#ifdef AICWF_SDIO_SUPPORT + aicwf_sdio_register(); +#endif +#ifdef AICWF_USB_SUPPORT + aicwf_usb_register(); +#endif +#ifdef AICWF_PCIE_SUPPORT + aicwf_pcie_register(); +#endif +} + +//static DECLARE_WORK(aicsmac_driver_work, aicsmac_driver_register); + +struct completion hostif_register_done; +static int rwnx_driver_err = -1; + +#define REGISTRATION_TIMEOUT 9000 + +void aicwf_hostif_ready(void) +{ + rwnx_driver_err = 0; + g_rwnx_plat->enabled = true; + complete(&hostif_register_done); +} + +void aicwf_hostif_fail(void) +{ + rwnx_driver_err = 1; + complete(&hostif_register_done); +} + +static int __init rwnx_mod_init(void) +{ + RWNX_DBG(RWNX_FN_ENTRY_STR); + rwnx_print_version(); + rwnx_init_cmd_array(); + +//#ifndef CONFIG_PLATFORM_ROCKCHIP + if (aicbsp_set_subsys(AIC_WIFI, AIC_PWR_ON) < 0) { + AICWFDBG(LOGERROR, "%s, set power on fail!\n", __func__); + if(!aicbsp_get_load_fw_in_fdrv()){ + return -ENODEV; + } + } +//#endif + + init_completion(&hostif_register_done); + aicsmac_driver_register(); + + if ((wait_for_completion_timeout(&hostif_register_done, msecs_to_jiffies(REGISTRATION_TIMEOUT)) == 0) || rwnx_driver_err) { + AICWFDBG(LOGERROR, "register_driver timeout or error\n"); +#ifdef AICWF_SDIO_SUPPORT + aicwf_sdio_exit(); +#endif /* AICWF_SDIO_SUPPORT */ +#ifdef AICWF_USB_SUPPORT + aicwf_usb_exit(); +#endif /*AICWF_USB_SUPPORT */ + aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); + return -ENODEV; + } + +#ifdef AICWF_PCIE_SUPPORT + return rwnx_platform_register_drv(); +#else + return 0; +#endif +} + +/** + * + */ +static void __exit rwnx_mod_exit(void) +{ + RWNX_DBG(RWNX_FN_ENTRY_STR); + +#ifdef AICWF_PCIE_SUPPORT + rwnx_platform_unregister_drv(); +#endif + +#ifdef AICWF_SDIO_SUPPORT + aicwf_sdio_exit(); +#endif + +#ifdef AICWF_USB_SUPPORT + aicwf_usb_exit(); +#endif +//#ifndef CONFIG_PLATFORM_ROCKCHIP + aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); +//#endif + rwnx_free_cmd_array(); + +} + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +#endif + +module_init(rwnx_mod_init); +module_exit(rwnx_mod_exit); + +MODULE_FIRMWARE(RWNX_CONFIG_FW_NAME); + +MODULE_DESCRIPTION(RW_DRV_DESCRIPTION); +MODULE_VERSION(RWNX_VERS_MOD); +MODULE_AUTHOR(RW_DRV_COPYRIGHT " " RW_DRV_AUTHOR); +MODULE_LICENSE("GPL"); + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.h new file mode 100644 index 000000000000..684ab081ff34 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mesh.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mesh.c new file mode 100644 index 000000000000..8773db61a664 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mesh.c @@ -0,0 +1,42 @@ +/** + **************************************************************************************** + * + * @file rwnx_mesh.c + * + * Copyright (C) RivieraWaves 2016-2019 + * + **************************************************************************************** + */ + +/** + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwnx_mesh.h" + +/** + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + +struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local) +{ + struct rwnx_mesh_proxy *p_mesh_proxy = NULL; + struct rwnx_mesh_proxy *p_cur_proxy; + + /* Look for proxied devices with provided address */ + list_for_each_entry(p_cur_proxy, &p_rwnx_vif->ap.proxy_list, list) { + if (p_cur_proxy->local != local) { + continue; + } + + if (!memcmp(&p_cur_proxy->ext_sta_addr, p_sta_addr, ETH_ALEN)) { + p_mesh_proxy = p_cur_proxy; + break; + } + } + + /* Return the found information */ + return p_mesh_proxy; +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mesh.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mesh.h new file mode 100644 index 000000000000..db8950f160de --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mesh.h @@ -0,0 +1,45 @@ +/** + **************************************************************************************** + * + * @file rwnx_mesh.h + * + * @brief VHT Beamformer function declarations + * + * Copyright (C) RivieraWaves 2016-2019 + * + **************************************************************************************** + */ + +#ifndef _RWNX_MESH_H_ +#define _RWNX_MESH_H_ + +/** + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwnx_defs.h" + +/** + * DEFINES + **************************************************************************************** + */ + +/** + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/** + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief TODO [LT] + **************************************************************************************** + */ +struct rwnx_mesh_proxy *rwnx_get_mesh_proxy_info(struct rwnx_vif *p_rwnx_vif, u8 *p_sta_addr, bool local); + +#endif /* _RWNX_MESH_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c new file mode 100644 index 000000000000..9e23a3cbcb7e --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c @@ -0,0 +1,1752 @@ +/** +****************************************************************************** +* +* @file rwnx_mod_params.c +* +* @brief Set configuration according to modules parameters +* +* Copyright (C) RivieraWaves 2012-2019 +* +****************************************************************************** +*/ +#include <linux/module.h> +#include <linux/rtnetlink.h> + +#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_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_WIPHY_SELF_MANAGED; + + rtnl_lock(); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) + if (regulatory_set_wiphy_regd_sync(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ + wiphy_err(wiphy, "Failed to set custom regdomain\n"); + } + #else + if (regulatory_set_wiphy_regd_sync_rtnl(wiphy, getRegdomainFromRwnxDB(wiphy, default_ccode))){ + wiphy_err(wiphy, "Failed to set custom regdomain\n"); + } + #endif + + else{ + wiphy_err(wiphy,"\n" + "*******************************************************\n" + "** CAUTION: USING PERMISSIVE CUSTOM REGULATORY RULES **\n" + "*******************************************************\n"); + } + rtnl_unlock(); +#endif + +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.h new file mode 100644 index 000000000000..fb407746d424 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c new file mode 100644 index 000000000000..662fb9378dff --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c @@ -0,0 +1,1549 @@ +/** + **************************************************************************************** + * + * @file rwnx_msg_rx.c + * + * @brief RX function definitions + * + * Copyright (C) RivieraWaves 2012-2021 + * + **************************************************************************************** + */ +#include <linux/vmalloc.h> +#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" +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; +} + +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, +}; + +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) +{ + //printk("%s msg->id:0x%x \r\n", __func__, msg->id); + + rwnx_hw->cmd_mgr->msgind(rwnx_hw->cmd_mgr, msg, + msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]); +} + +void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len) +{ + u8 *data_end = NULL; + (void)data_end; + + if (!rwnx_hw || !rwnx_hw->fwlog_en) { + pr_err("FWLOG-OVFL: %s", msg); + return; + } + + printk("FWLOG: %s", msg); + +#ifdef CONFIG_RWNX_DEBUGFS + data_end = rwnx_hw->debugfs.fw_log.buf.dataend; + + if (!rwnx_hw->debugfs.fw_log.buf.data) + return ; + + //printk("end=%lx, len=%d\n", (unsigned long)rwnx_hw->debugfs.fw_log.buf.end, len); + + spin_lock_bh(&rwnx_hw->debugfs.fw_log.lock); + + if (rwnx_hw->debugfs.fw_log.buf.end + len > data_end) { + int rem = data_end - rwnx_hw->debugfs.fw_log.buf.end; + memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, rem); + memcpy(rwnx_hw->debugfs.fw_log.buf.data, &msg[rem], len - rem); + rwnx_hw->debugfs.fw_log.buf.end = rwnx_hw->debugfs.fw_log.buf.data + (len - rem); + } else { + memcpy(rwnx_hw->debugfs.fw_log.buf.end, msg, len); + rwnx_hw->debugfs.fw_log.buf.end += len; + } + + rwnx_hw->debugfs.fw_log.buf.size += len; + if (rwnx_hw->debugfs.fw_log.buf.size > FW_LOG_SIZE) + rwnx_hw->debugfs.fw_log.buf.size = FW_LOG_SIZE; + + spin_unlock_bh(&rwnx_hw->debugfs.fw_log.lock); +#endif +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.h new file mode 100644 index 000000000000..b5556d160ff0 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.h @@ -0,0 +1,19 @@ +/** + **************************************************************************************** + * + * @file rwnx_msg_rx.h + * + * @brief RX function declarations + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ + +#ifndef _RWNX_MSG_RX_H_ +#define _RWNX_MSG_RX_H_ + +void rwnx_rx_handle_msg(struct rwnx_hw *rwnx_hw, struct ipc_e2a_msg *msg); +void rwnx_rx_handle_print(struct rwnx_hw *rwnx_hw, u8 *msg, u32 len); + +#endif /* _RWNX_MSG_RX_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c new file mode 100644 index 000000000000..054afeb7a5c3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c @@ -0,0 +1,3516 @@ +/** + ****************************************************************************** + * + * @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_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; + + default: + error = -ENOMEM; + break; + } + + return error; +} + + +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_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, 20, 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); + 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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.h new file mode 100644 index 000000000000..a3890fe2b26d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.h @@ -0,0 +1,180 @@ +/** + **************************************************************************************** + * + * @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_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_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); + + +#endif /* _RWNX_MSG_TX_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.c new file mode 100644 index 000000000000..538f14306afb --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.c @@ -0,0 +1,659 @@ +/** + ****************************************************************************** + * + * @file rwnx_mu_group.c + * + * Copyright (C) RivieraWaves 2016-2019 + * + ****************************************************************************** + */ + +#include "rwnx_defs.h" +#include "rwnx_msg_tx.h" +#include "rwnx_events.h" + + +/** + * rwnx_mu_group_sta_init - Initialize group information for a STA + * + * @sta: Sta to initialize + */ +void rwnx_mu_group_sta_init(struct rwnx_sta *sta, + const struct ieee80211_vht_cap *vht_cap) +{ + sta->group_info.map = 0; + sta->group_info.cnt = 0; + sta->group_info.active.next = LIST_POISON1; + sta->group_info.update.next = LIST_POISON1; + sta->group_info.last_update = 0; + sta->group_info.traffic = 0; + sta->group_info.group = 0; + + if (!vht_cap || + !(vht_cap->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { + sta->group_info.map = RWNX_SU_GROUP; + } +} + +/** + * rwnx_mu_group_sta_del - Remove a sta from all MU group + * + * @rwnx_hw: main driver data + * @sta: STA to remove + * + * Remove one sta from all the MU groups it belongs to. + */ +void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) +{ + struct rwnx_mu_info *mu = &rwnx_hw->mu; + int i, j, group_id; + bool lock_taken; + u64 map; + + lock_taken = (down_interruptible(&mu->lock) == 0); + + group_sta_for_each(sta, group_id, map) { + struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); + + for (i = 0; i < CONFIG_USER_MAX; i++) { + if (group->users[i] == sta) { + group->users[i] = NULL; + group->user_cnt--; + /* Don't keep group with only one user */ + if (group->user_cnt == 1) { + for (j = 0; j < CONFIG_USER_MAX; j++) { + if (group->users[j]) { + group->users[j]->group_info.cnt--; + group->users[j]->group_info.map &= ~BIT_ULL(group->group_id); + if (group->users[j]->group_info.group == group_id) + group->users[j]->group_info.group = 0; + group->user_cnt--; + break; + } + } + mu->group_cnt--; + trace_mu_group_delete(group->group_id); + } else { + trace_mu_group_update(group); + } + break; + } + } + + WARN((i == CONFIG_USER_MAX), "sta %d doesn't belongs to group %d", + sta->sta_idx, group_id); + } + + sta->group_info.map = 0; + sta->group_info.cnt = 0; + sta->group_info.traffic = 0; + + if (sta->group_info.active.next != LIST_POISON1) + list_del(&sta->group_info.active); + + if (sta->group_info.update.next != LIST_POISON1) + list_del(&sta->group_info.update); + + if (lock_taken) + up(&mu->lock); +} + +/** + * rwnx_mu_group_sta_get_map - Get the list of group a STA belongs to + * + * @sta: pointer to the sta + * + * @return the list of group a STA belongs to as a bitfield + */ +u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) +{ + if (sta) + return sta->group_info.map; + return 0; +} + +/** + * rwnx_mu_group_sta_get_pos - Get sta position in a group + * + * @rwnx_hw: main driver data + * @sta: pointer to the sta + * @group_id: Group id + * + * @return the positon of @sta in group @group_id or -1 if the sta + * doesn't belongs to the group (or group id is invalid) + */ +int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, + int group_id) +{ + struct rwnx_mu_group *group; + int i; + + group = rwnx_mu_group_from_id(&rwnx_hw->mu, group_id); + if (!group) + return -1; + + for (i = 0; i < CONFIG_USER_MAX; i++) { + if (group->users[i] == sta) + return i; + } + + WARN(1, "sta %d doesn't belongs to group %d", + sta->sta_idx, group_id); + return -1; +} + +/** + * rwnx_mu_group_move_head - Move (or add) one element at the top of a list + * + * @list: list pointer + * @elem: element to move (or add) at the top of @list + * + */ +static inline +void rwnx_mu_group_move_head(struct list_head *list, struct list_head *elem) +{ + if (elem->next != LIST_POISON1) { + __list_del_entry(elem); + } + list_add(elem, list); +} + +/** + * rwnx_mu_group_remove_users - Remove all the users of a group + * + * @mu: pointer on MU info + * @group: pointer on group to remove users from + * + * Loop over all users one one group and remove this group from their + * map (and count). + * Each users is also added to the update_sta list, so that group info + * will be resent to fw for this user. + */ +static inline +void rwnx_mu_group_remove_users(struct rwnx_mu_info *mu, + struct rwnx_mu_group *group) +{ + struct rwnx_sta *sta; + int i, group_id = group->group_id; + + for (i = 0; i < CONFIG_USER_MAX; i++) { + if (group->users[i]) { + sta = group->users[i]; + group->users[i] = NULL; + sta->group_info.cnt--; + sta->group_info.map &= ~BIT_ULL(group_id); + rwnx_mu_group_move_head(&mu->update_sta, + &sta->group_info.update); + } + } + + if (group->user_cnt) + mu->group_cnt--; + group->user_cnt = 0; + trace_mu_group_delete(group_id); +} + +/** + * rwnx_mu_group_add_users - Add users to a group + * + * @mu: pointer on MU info + * @group: pointer on group to add users in + * @nb_user: number of users to ad + * @users: table of user to add + * + * Add @nb_users to @group (which may already have users) + * Each new users is added to the first free position. + * It is assume that @group has at least @nb_user free position. If it is not + * case it only add the number of users needed to complete the group. + * Each users (effectively added to @group) is also added to the update_sta + * list, so that group info will be resent to fw for this user. + */ +static inline +void rwnx_mu_group_add_users(struct rwnx_mu_info *mu, + struct rwnx_mu_group *group, + int nb_user, struct rwnx_sta **users) +{ + int i, j, group_id = group->group_id; + + if (!group->user_cnt) + mu->group_cnt++; + + j = 0; + for (i = 0; i < nb_user ; i++) { + for (; j < CONFIG_USER_MAX ; j++) { + if (group->users[j] == NULL) { + group->users[j] = users[i]; + users[i]->group_info.cnt++; + users[i]->group_info.map |= BIT_ULL(group_id); + + rwnx_mu_group_move_head(&(mu->update_sta), + &(users[i]->group_info.update)); + group->user_cnt++; + j++; + break; + } + + WARN(j == (CONFIG_USER_MAX - 1), + "Too many user for group %d (nb_user=%d)", + group_id, group->user_cnt + nb_user - i); + } + } + + trace_mu_group_update(group); +} + + +/** + * rwnx_mu_group_create_one - create on group with a specific group of user + * + * @mu: pointer on MU info + * @nb_user: number of user to include in the group (<= CONFIG_USER_MAX) + * @users: table of users + * + * Try to create a new group with a specific group of users. + * 1- First it checks if a group containing all this users already exists. + * + * 2- Then it checks if it is possible to complete a group which already + * contains at least one user. + * + * 3- Finally it create a new group. To do so, it take take the last group of + * the active_groups list, remove all its current users and add the new ones + * + * In all cases, the group selected is moved at the top of the active_groups + * list + * + * @return 1 if a new group has been created and 0 otherwise + */ +static +int rwnx_mu_group_create_one(struct rwnx_mu_info *mu, int nb_user, + struct rwnx_sta **users, int *nb_group_left) +{ + int i, group_id; + struct rwnx_mu_group *group; + u64 group_match; + u64 group_avail; + + group_match = users[0]->group_info.map; + group_avail = users[0]->group_info.map; + for (i = 1; i < nb_user ; i++) { + group_match &= users[i]->group_info.map; + group_avail |= users[i]->group_info.map; + + } + + if (group_match) { + /* a group (or more) with all the users already exist */ + group_id = RWNX_GET_FIRST_GROUP_ID(group_match); + group = rwnx_mu_group_from_id(mu, group_id); + rwnx_mu_group_move_head(&mu->active_groups, &group->list); + return 0; + } + +#if CONFIG_USER_MAX > 2 + if (group_avail) { + /* check if we can complete a group */ + struct rwnx_sta *users2[CONFIG_USER_MAX]; + int nb_user2; + + group_for_each(group_id, group_avail) { + group = rwnx_mu_group_from_id(mu, group_id); + if (group->user_cnt == CONFIG_USER_MAX) + continue; + + nb_user2 = 0; + for (i = 0; i < nb_user ; i++) { + if (!(users[i]->group_info.map & BIT_ULL(group_id))) { + users2[nb_user2] = users[i]; + nb_user2++; + } + } + + if ((group->user_cnt + nb_user2) <= CONFIG_USER_MAX) { + rwnx_mu_group_add_users(mu, group, nb_user2, users2); + rwnx_mu_group_move_head(&mu->active_groups, &group->list); + return 0; + } + } + } +#endif /* CONFIG_USER_MAX > 2*/ + + /* create a new group */ + group = list_last_entry(&mu->active_groups, struct rwnx_mu_group, list); + rwnx_mu_group_remove_users(mu, group); + rwnx_mu_group_add_users(mu, group, nb_user, users); + rwnx_mu_group_move_head(&mu->active_groups, &group->list); + (*nb_group_left)--; + + return 1; +} + +/** + * rwnx_mu_group_create - Create new groups containing one specific sta + * + * @mu: pointer on MU info + * @sta: sta to add in each group + * @nb_group_left: maximum number to new group allowed. (updated on exit) + * + * This will try to create "all the possible" group with a specific sta being + * a member of all these group. + * The function simply loops over the @active_sta list (starting from @sta). + * When it has (CONFIG_USER_MAX - 1) users it try to create a new group with + * these users (plus @sta). + * Loops end when there is no more users, or no more new group is allowed + * + */ +static +void rwnx_mu_group_create(struct rwnx_mu_info *mu, struct rwnx_sta *sta, + int *nb_group_left) +{ + struct rwnx_sta *user_sta = sta; + struct rwnx_sta *users[CONFIG_USER_MAX]; + int nb_user = 1; + + users[0] = sta; + while (*nb_group_left) { + + list_for_each_entry_continue(user_sta, &mu->active_sta, group_info.active) { + users[nb_user] = user_sta; + if (++nb_user == CONFIG_USER_MAX) { + break; + } + } + + if (nb_user > 1) { + if (rwnx_mu_group_create_one(mu, nb_user, users, nb_group_left)) + (*nb_group_left)--; + + if (nb_user < CONFIG_USER_MAX) + break; + else + nb_user = 1; + } else + break; + } +} + +/** + * rwnx_mu_group_work - process function of the "group_work" + * + * The work is scheduled when several sta (MU beamformee capable) are active. + * When called, the @active_sta contains the list of the active sta (starting + * from the most recent one), and @active_groups is the list of all possible + * groups ordered so that the first one is the most recently used. + * + * This function will create new groups, starting from group containing the + * most "active" sta. + * For example if the list of sta is : + * sta8 -> sta3 -> sta4 -> sta7 -> sta1 + * and the number of user per group is 3, it will create grooups : + * - sta8 / sta3 / sta4 + * - sta8 / sta7 / sta1 + * - sta3 / sta4 / sta7 + * - sta3 / sta1 + * - sta4 / sta7 / sta1 + * - sta7 / sta1 + * + * To create new group, the least used group are first selected. + * It is only allowed to create NX_MU_GROUP_MAX per iteration. + * + * Once groups have been updated, mu group information is update to the fw. + * To do so it use the @update_sta list to know which sta has been affected. + * As it is necessary to wait for fw confirmation before using this new group + * MU is temporarily disabled during group update + * + * Work is then rescheduled. + * + * At the end of the function, both @active_sta and @update_sta list are empty. + * + * Note: + * - This is still a WIP, and will require more tuning + * - not all combinations are created, to avoid to much processing. + * - reschedule delay should be adaptative + */ +void rwnx_mu_group_work(struct work_struct *ws) +{ + struct delayed_work *dw = container_of(ws, struct delayed_work, work); + struct rwnx_mu_info *mu = container_of(dw, struct rwnx_mu_info, group_work); + struct rwnx_hw *rwnx_hw = container_of(mu, struct rwnx_hw, mu); + struct rwnx_sta *sta, *next; + int nb_group_left = NX_MU_GROUP_MAX; + + if (WARN(!rwnx_hw->mod_params->mutx, + "In group formation work, but mutx disabled")) + return; + + if (down_interruptible(&mu->lock) != 0) + return; + + mu->update_count++; + if (!mu->update_count) + mu->update_count++; + + list_for_each_entry_safe(sta, next, &mu->active_sta, group_info.active) { + if (nb_group_left) + rwnx_mu_group_create(mu, sta, &nb_group_left); + + sta->group_info.last_update = mu->update_count; + list_del(&sta->group_info.active); + } + + if (!list_empty(&mu->update_sta)) { + list_for_each_entry_safe(sta, next, &mu->update_sta, group_info.update) { + rwnx_send_mu_group_update_req(rwnx_hw, sta); + list_del(&sta->group_info.update); + } + } + + mu->next_group_select = jiffies; + rwnx_mu_group_sta_select(rwnx_hw); + up(&mu->lock); + + return; +} + +/** + * rwnx_mu_group_init - Initialize MU groups + * + * @rwnx_hw: main driver data + * + * Initialize all MU group + */ +void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_mu_info *mu = &rwnx_hw->mu; + int i; + + INIT_LIST_HEAD(&mu->active_groups); + INIT_LIST_HEAD(&mu->active_sta); + INIT_LIST_HEAD(&mu->update_sta); + + for (i = 0; i < NX_MU_GROUP_MAX; i++) { + int j; + mu->groups[i].user_cnt = 0; + mu->groups[i].group_id = i + 1; + for (j = 0; j < CONFIG_USER_MAX; j++) { + mu->groups[i].users[j] = NULL; + } + list_add(&mu->groups[i].list, &mu->active_groups); + } + + mu->update_count = 1; + mu->group_cnt = 0; + mu->next_group_select = jiffies; + INIT_DELAYED_WORK(&mu->group_work, rwnx_mu_group_work); + sema_init(&mu->lock, 1); +} + +/** + * rwnx_mu_set_active_sta - mark a STA as active + * + * @rwnx_hw: main driver data + * @sta: pointer to the sta + * @traffic: Number of buffers to add in the sta's traffic counter + * + * If @sta is MU beamformee capable (and MU-MIMO tx is enabled) move the + * sta at the top of the @active_sta list. + * It also schedule the group_work if not already scheduled and the list + * contains more than one sta. + * + * If a STA was already in the list during the last group update + * (i.e. sta->group_info.last_update == mu->update_count) it is not added + * back to the list until a sta that wasn't active during the last update is + * added. This is to avoid scheduling group update with a list of sta that + * were all already in the list during previous update. + * + * It is called with mu->lock taken. + */ +void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, + int traffic) +{ + struct rwnx_mu_info *mu = &rwnx_hw->mu; + + if (!sta || (sta->group_info.map & RWNX_SU_GROUP)) + return; + + sta->group_info.traffic += traffic; + + if ((sta->group_info.last_update != mu->update_count) || + !list_empty(&mu->active_sta)) { + + rwnx_mu_group_move_head(&mu->active_sta, &sta->group_info.active); + + if (!delayed_work_pending(&mu->group_work) && + !list_is_singular(&mu->active_sta)) { + schedule_delayed_work(&mu->group_work, + msecs_to_jiffies(RWNX_MU_GROUP_INTERVAL)); + } + } +} + +/** + * rwnx_mu_set_active_group - mark a MU group as active + * + * @rwnx_hw: main driver data + * @group_id: Group id + * + * move a group at the top of the @active_groups list + */ +void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) +{ + struct rwnx_mu_info *mu = &rwnx_hw->mu; + struct rwnx_mu_group *group = rwnx_mu_group_from_id(mu, group_id); + + rwnx_mu_group_move_head(&mu->active_groups, &group->list); +} + + +/** + * rwnx_mu_group_sta_select - Select the best group for MU stas + * + * @rwnx_hw: main driver data + * + * For each MU capable client of AP interfaces this function tries to select + * the best group to use. + * + * In first pass, gather information from all stations to form statistics + * for each group for the previous @RWNX_MU_GROUP_SELECT_INTERVAL interval: + * - number of buffers transmitted + * - number of user + * + * Then groups with more than 2 active users, are assigned after being ordered + * by traffic : + * - group with highest traffic is selected: set this group for all its users + * - update nb_users for all others group (as one sta may be in several groups) + * - select the next group that have still mor than 2 users and assign it. + * - continue until all group are processed + * + */ +void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) +{ + struct rwnx_mu_info *mu = &rwnx_hw->mu; + int nb_users[NX_MU_GROUP_MAX + 1]; + int traffic[NX_MU_GROUP_MAX + 1]; + int order[NX_MU_GROUP_MAX + 1]; + struct rwnx_sta *sta; + struct rwnx_vif *vif; + struct list_head *head; + u64 map; + int i, j, update, group_id, tmp, cnt = 0; + + if (!mu->group_cnt || time_before(jiffies, mu->next_group_select)) + return; + + list_for_each_entry(vif, &rwnx_hw->vifs, list) { + + if (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) + continue; + +#ifdef CONFIG_RWNX_FULLMAC + head = &vif->ap.sta_list; +#else + head = &vif->stations; +#endif /* CONFIG_RWNX_FULLMAC */ + + memset(nb_users, 0, sizeof(nb_users)); + memset(traffic, 0, sizeof(traffic)); + list_for_each_entry(sta, head, list) { + int sta_traffic = sta->group_info.traffic; + + /* reset statistics for next selection */ + sta->group_info.traffic = 0; + if (sta->group_info.group) + trace_mu_group_selection(sta, 0); + sta->group_info.group = 0; + + if (sta->group_info.cnt == 0 || + sta_traffic < RWNX_MU_GROUP_MIN_TRAFFIC) + continue; + + group_sta_for_each(sta, group_id, map) { + nb_users[group_id]++; + traffic[group_id] += sta_traffic; + + /* list group with 2 users or more */ + if (nb_users[group_id] == 2) + order[cnt++] = group_id; + } + } + + /* reorder list of group with more that 2 users */ + update = 1; + while (update) { + update = 0; + for (i = 0; i < cnt - 1; i++) { + if (traffic[order[i]] < traffic[order[i + 1]]) { + tmp = order[i]; + order[i] = order[i + 1]; + order[i + 1] = tmp; + update = 1; + } + } + } + + /* now assign group in traffic order */ + for (i = 0; i < cnt; i++) { + struct rwnx_mu_group *group; + group_id = order[i]; + + if (nb_users[group_id] < 2) + continue; + + group = rwnx_mu_group_from_id(mu, group_id); + for (j = 0; j < CONFIG_USER_MAX; j++) { + if (group->users[j]) { + trace_mu_group_selection(group->users[j], group_id); + group->users[j]->group_info.group = group_id; + + group_sta_for_each(group->users[j], tmp, map) { + if (group_id != tmp) + nb_users[tmp]--; + } + } + } + } + } + + mu->next_group_select = jiffies + + msecs_to_jiffies(RWNX_MU_GROUP_SELECT_INTERVAL); + mu->next_group_select |= 1; +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.h new file mode 100644 index 000000000000..c24bb0396e9f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mu_group.h @@ -0,0 +1,181 @@ +/** + ****************************************************************************** + * + * @file rwnx_mu_group.h + * + * Copyright (C) RivieraWaves 2016-2019 + * + ****************************************************************************** + */ +#ifndef _RWNX_MU_GROUP_H_ +#define _RWNX_MU_GROUP_H_ + +#include <linux/workqueue.h> +#include <linux/semaphore.h> + +struct rwnx_hw; +struct rwnx_sta; + +#ifdef CONFIG_RWNX_MUMIMO_TX + +/** + * struct rwnx_sta_group_info - Group Information for a STA + * + * @active: node for @mu->active_sta list + * @update: node for @mu->update_sta list + * @cnt: Number of groups the STA belongs to + * @map: Bitfield of groups the sta belongs to + * @traffic: Number of buffers sent since previous group selection + * @group: Id of the group selected by previous group selection + * (cf @rwnx_mu_group_sta_select) + */ +struct rwnx_sta_group_info { + struct list_head active; + struct list_head update; + u16 last_update; + int cnt; + u64 map; + int traffic; + u8 group; +}; + +/** + * struct mu_group_info - Information about the users of a group + * + * @list: node for mu->active_groups + * @group_id: Group identifier + * @user_cnt: Number of the users in the group + * @users: Pointer to the sta, ordered by user position + */ +struct rwnx_mu_group { + struct list_head list; + int group_id; + int user_cnt; + struct rwnx_sta *users[CONFIG_USER_MAX]; +}; + +/** + * struct rwnx_mu_info - Information about all MU group + * + * @active_groups: List of all possible groups. Ordered from the most recently + * used one to the least one (and possibly never used) + * @active_sta: List of MU beamformee sta that have been active (since previous + * group update). Ordered from the most recently active. + * @update_sta: List of sta whose group information has changed and need to be + * updated at fw level + * @groups: Table of all groups + * @group_work: Work item used to schedule group update + * @update_count: Counter used to identify the last group formation update. + * (cf rwnx_sta_group_info.last_update) + * @lock: Lock taken during group update. If tx happens lock is taken, then tx + * will not used MU. + * @next_group_assign: Next time the group selection should be run + * (ref @rwnx_mu_group_sta_select) + * @group_cnt: Number of group created + */ +struct rwnx_mu_info { + struct list_head active_groups; + struct list_head active_sta; + struct list_head update_sta; + struct rwnx_mu_group groups[NX_MU_GROUP_MAX]; + struct delayed_work group_work; + u16 update_count; + struct semaphore lock; + unsigned long next_group_select; + u8 group_cnt; +}; + +#define RWNX_SU_GROUP BIT_ULL(0) +#define RWNX_MU_GROUP_MASK 0x7ffffffffffffffeULL +#define RWNX_MU_GROUP_INTERVAL 200 /* in ms */ +#define RWNX_MU_GROUP_SELECT_INTERVAL 100 /* in ms */ +// minimum traffic in a RWNX_MU_GROUP_SELECT_INTERVAL to consider the sta +#define RWNX_MU_GROUP_MIN_TRAFFIC 50 /* in number of packet */ + + +#define RWNX_GET_FIRST_GROUP_ID(map) (fls64(map) - 1) + +#define group_sta_for_each(sta, id, map) \ + do { \ + map = sta->group_info.map & RWNX_MU_GROUP_MASK; \ + for (id = (fls64(map) - 1) ; id > 0 ; \ + map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) \ + } while (0) + +#define group_for_each(id, map) \ + for (id = (fls64(map) - 1) ; id > 0 ; \ + map &= ~(u64)BIT_ULL(id), id = (fls64(map) - 1)) + +#define RWNX_MUMIMO_INFO_POS_ID(info) (((info) >> 6) & 0x3) +#define RWNX_MUMIMO_INFO_GROUP_ID(info) ((info) & 0x3f) + +static inline +struct rwnx_mu_group *rwnx_mu_group_from_id(struct rwnx_mu_info *mu, int id) +{ + if (id > NX_MU_GROUP_MAX) + return NULL; + + return &mu->groups[id - 1]; +} + + +void rwnx_mu_group_sta_init(struct rwnx_sta *sta, + const struct ieee80211_vht_cap *vht_cap); +void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta); +u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta); +int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, + int group_id); + +void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw); + +void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, + int traffic); +void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id); +void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw); + + +#else /* ! CONFIG_RWNX_MUMIMO_TX */ + +static inline +void rwnx_mu_group_sta_init(struct rwnx_sta *sta, + const struct ieee80211_vht_cap *vht_cap) +{} + +static inline +void rwnx_mu_group_sta_del(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta) +{} + +static inline +u64 rwnx_mu_group_sta_get_map(struct rwnx_sta *sta) +{ + return 0; +} + +static inline +int rwnx_mu_group_sta_get_pos(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, + int group_id) +{ + return 0; +} + +static inline +void rwnx_mu_group_init(struct rwnx_hw *rwnx_hw) +{} + +static inline +void rwnx_mu_set_active_sta(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, + int traffic) +{} + +static inline +void rwnx_mu_set_active_group(struct rwnx_hw *rwnx_hw, int group_id) +{} + +static inline +void rwnx_mu_group_sta_select(struct rwnx_hw *rwnx_hw) +{} + +#endif /* CONFIG_RWNX_MUMIMO_TX */ + +#endif /* _RWNX_MU_GROUP_H_ */ + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_pci.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_pci.c new file mode 100644 index 000000000000..40dac946536d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_pci.c @@ -0,0 +1,94 @@ +/** + ****************************************************************************** + * + * @file rwnx_pci.c + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#include <linux/pci.h> +#include <linux/module.h> + +#include "rwnx_defs.h" +#include "rwnx_dini.h" +#include "rwnx_v7.h" + +#define PCI_VENDOR_ID_DINIGROUP 0x17DF +#define PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE 0x1907 + +#define PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7 0x7011 + +static const struct pci_device_id rwnx_pci_ids[] = { + {PCI_DEVICE(PCI_VENDOR_ID_DINIGROUP, PCI_DEVICE_ID_DINIGROUP_DNV6_F2PCIE)}, + {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_CEVA_VIRTEX7)}, + {0,} +}; + + +/* Uncomment this for depmod to create module alias */ +/* We don't want this on development platform */ +//MODULE_DEVICE_TABLE(pci, rwnx_pci_ids); + +static int rwnx_pci_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) +{ + struct rwnx_plat *rwnx_plat = NULL; + void *drvdata; + int ret = -ENODEV; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + if (pci_id->vendor == PCI_VENDOR_ID_DINIGROUP) { + ret = rwnx_dini_platform_init(pci_dev, &rwnx_plat); + } else if (pci_id->vendor == PCI_VENDOR_ID_XILINX) { + ret = rwnx_v7_platform_init(pci_dev, &rwnx_plat); + } + + if (ret) + return ret; + + rwnx_plat->pci_dev = pci_dev; + + ret = rwnx_platform_init(rwnx_plat, &drvdata); + pci_set_drvdata(pci_dev, drvdata); + + if (ret) + rwnx_plat->deinit(rwnx_plat); + + return ret; +} + +static void rwnx_pci_remove(struct pci_dev *pci_dev) +{ + struct rwnx_hw *rwnx_hw; + struct rwnx_plat *rwnx_plat; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + rwnx_hw = pci_get_drvdata(pci_dev); + rwnx_plat = rwnx_hw->plat; + + rwnx_platform_deinit(rwnx_hw); + rwnx_plat->deinit(rwnx_plat); + + pci_set_drvdata(pci_dev, NULL); +} + +static struct pci_driver rwnx_pci_drv = { + .name = KBUILD_MODNAME, + .id_table = rwnx_pci_ids, + .probe = rwnx_pci_probe, + .remove = rwnx_pci_remove +}; + +int rwnx_pci_register_drv(void) +{ + return pci_register_driver(&rwnx_pci_drv); +} + +void rwnx_pci_unregister_drv(void) +{ + pci_unregister_driver(&rwnx_pci_drv); +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_pci.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_pci.h new file mode 100644 index 000000000000..d81578cbef48 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_pci.h @@ -0,0 +1,17 @@ +/** + ****************************************************************************** + * + * @file rwnx_pci.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_PCI_H_ +#define _RWNX_PCI_H_ + +int rwnx_pci_register_drv(void); +void rwnx_pci_unregister_drv(void); + +#endif /* _RWNX_PCI_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c new file mode 100644 index 000000000000..3dd673cf0797 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c @@ -0,0 +1,2069 @@ +/** + ****************************************************************************** + * + * @file rwnx_platform.c + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#include <linux/module.h> +#include <linux/firmware.h> +#include <linux/delay.h> +#include <linux/vmalloc.h> + +#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 <linux/firmware.h> +#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_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 LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) +#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, "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]); +} + +/** + * 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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h new file mode 100644 index 000000000000..9250612349d3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h @@ -0,0 +1,135 @@ +/** + ****************************************************************************** + * + * @file rwnx_platorm.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_PLATFORM_H_ +#define _RWNX_PLATFORM_H_ + +#include <linux/pci.h> +#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_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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_prof.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_prof.h new file mode 100644 index 000000000000..5442f588212f --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_prof.h @@ -0,0 +1,133 @@ +/** + **************************************************************************************** + * + * @file rwnx_prof.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ + +#ifndef _RWNX_PROF_H_ +#define _RWNX_PROF_H_ + +#include "reg_access.h" +#include "rwnx_platform.h" + +static inline void rwnx_prof_set(struct rwnx_hw *rwnx_hw, int val) +{ + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_SET_PROFILING_ADDR); +} + +static inline void rwnx_prof_clear(struct rwnx_hw *rwnx_hw, int val) +{ + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + RWNX_REG_WRITE(val, rwnx_plat, RWNX_ADDR_SYSTEM, NXMAC_SW_CLEAR_PROFILING_ADDR); +} + +#if 0 +/* Defines for SW Profiling registers values */ +enum { + TX_IPC_IRQ, + TX_IPC_EVT, + TX_PREP_EVT, + TX_DMA_IRQ, + TX_MAC_IRQ, + TX_PAYL_HDL, + TX_CFM_EVT, + TX_IPC_CFM, + RX_MAC_IRQ, // 8 + RX_TRIGGER_EVT, + RX_DMA_IRQ, + RX_DMA_EVT, + RX_IPC_IND, + RX_MPDU_XFER, + DBG_PROF_MAX +}; +#endif + +enum { + SW_PROF_HOSTBUF_IDX = 12, + /****** IPC IRQs related signals ******/ + /* E2A direction */ + SW_PROF_IRQ_E2A_RXDESC = 16, // to make sure we let 16 bits available for LMAC FW + SW_PROF_IRQ_E2A_TXCFM, + SW_PROF_IRQ_E2A_DBG, + SW_PROF_IRQ_E2A_MSG, + SW_PROF_IPC_MSGPUSH, + SW_PROF_MSGALLOC, + SW_PROF_MSGIND, + SW_PROF_DBGIND, + + /* A2E direction */ + SW_PROF_IRQ_A2E_TXCFM_BACK, + + /****** Driver functions related signals ******/ + SW_PROF_WAIT_QUEUE_STOP, + SW_PROF_WAIT_QUEUE_WAKEUP, + SW_PROF_RWNXDATAIND, + SW_PROF_RWNX_IPC_IRQ_HDLR, + SW_PROF_RWNX_IPC_THR_IRQ_HDLR, + SW_PROF_IEEE80211RX, + SW_PROF_RWNX_PATTERN, + SW_PROF_MAX +}; + +// [LT]For debug purpose only +#if (0) +#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (21) +#define SW_PROF_CHAN_CTXT_CFM_BIT (22) +#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (23) +#define SW_PROF_CHAN_CTXT_PUSH_BIT (24) +#define SW_PROF_CHAN_CTXT_QUEUE_BIT (25) +#define SW_PROF_CHAN_CTXT_TX_BIT (26) +#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (27) +#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (28) +#define SW_PROF_CHAN_CTXT_SWTCH_BIT (29) + +// TO DO: update this + +#define REG_SW_SET_PROFILING_CHAN(env, bit) \ + rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) + +#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) \ + rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) + +#else +#define SW_PROF_CHAN_CTXT_CFM_HDL_BIT (0) +#define SW_PROF_CHAN_CTXT_CFM_BIT (0) +#define SW_PROF_CHAN_CTXT_CFM_SWDONE_BIT (0) +#define SW_PROF_CHAN_CTXT_PUSH_BIT (0) +#define SW_PROF_CHAN_CTXT_QUEUE_BIT (0) +#define SW_PROF_CHAN_CTXT_TX_BIT (0) +#define SW_PROF_CHAN_CTXT_TX_PAUSE_BIT (0) +#define SW_PROF_CHAN_CTXT_PSWTCH_BIT (0) +#define SW_PROF_CHAN_CTXT_SWTCH_BIT (0) + +#define REG_SW_SET_PROFILING_CHAN(env, bit) do {} while (0) +#define REG_SW_CLEAR_PROFILING_CHAN(env, bit) do {} while (0) +#endif + +#ifdef CONFIG_RWNX_SW_PROFILING +/* Macros for SW PRofiling registers access */ +#define REG_SW_SET_PROFILING(env, bit) \ + rwnx_prof_set((struct rwnx_hw *)env, BIT(bit)) + +#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) \ + rwnx_prof_set((struct rwnx_hw *)env, val << (SW_PROF_HOSTBUF_IDX)) + +#define REG_SW_CLEAR_PROFILING(env, bit) \ + rwnx_prof_clear((struct rwnx_hw *)env, BIT(bit)) + +#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) \ + rwnx_prof_clear((struct rwnx_hw *)env, 0x0F << (SW_PROF_HOSTBUF_IDX)) + +#else +#define REG_SW_SET_PROFILING(env, value) do {} while (0) +#define REG_SW_CLEAR_PROFILING(env, value) do {} while (0) +#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val) do {} while (0) +#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env) do {} while (0) +#endif + +#endif /* _RWNX_PROF_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c new file mode 100644 index 000000000000..c50f2d2b16cc --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c @@ -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 <linux/list.h> +#include <linux/kernel.h> +#include <linux/ktime.h> +#include <net/mac80211.h> + +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.h new file mode 100644 index 000000000000..8bc36f527f62 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.h @@ -0,0 +1,160 @@ +/** + ****************************************************************************** + * + * @file rwnx_radar.h + * + * @brief Functions to handle radar detection + * + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#ifndef _RWNX_RADAR_H_ +#define _RWNX_RADAR_H_ + +#include <linux/nl80211.h> + +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 <linux/workqueue.h> +#include <linux/spinlock.h> + +#define RWNX_RADAR_PULSE_MAX 32 + +/** + * struct rwnx_radar_pulses - List of pulses reported by HW + * @index: write index + * @count: number of valid pulses + * @buffer: buffer of pulses + */ +struct rwnx_radar_pulses { + /* Last radar pulses received */ + int index; + int count; + u32 buffer[RWNX_RADAR_PULSE_MAX]; +}; + +/** + * struct dfs_pattern_detector - DFS pattern detector + * @region: active DFS region, NL80211_DFS_UNSET until set + * @num_radar_types: number of different radar types + * @last_pulse_ts: time stamp of last valid pulse in usecs + * @prev_jiffies: + * @radar_detector_specs: array of radar detection specs + * @channel_detectors: list connecting channel_detector elements + */ +struct dfs_pattern_detector { + u8 enabled; + enum nl80211_dfs_regions region; + u8 num_radar_types; + u64 last_pulse_ts; + u32 prev_jiffies; + const struct radar_detector_specs *radar_spec; + struct list_head detectors[]; +}; + +#define NX_NB_RADAR_DETECTED 4 + +/** + * struct rwnx_radar_detected - List of radar detected + */ +struct rwnx_radar_detected { + u16 index; + u16 count; + s64 time[NX_NB_RADAR_DETECTED]; + s16 freq[NX_NB_RADAR_DETECTED]; +}; + + +struct rwnx_radar { + struct rwnx_radar_pulses pulses[RWNX_RADAR_LAST]; + struct dfs_pattern_detector *dpd[RWNX_RADAR_LAST]; + struct rwnx_radar_detected detected[RWNX_RADAR_LAST]; + struct work_struct detection_work; /* Work used to process radar pulses */ + spinlock_t lock; /* lock for pulses processing */ + + /* In softmac cac is handled by mac80211 */ +#ifdef CONFIG_RWNX_FULLMAC + struct delayed_work cac_work; /* Work used to handle CAC */ + struct rwnx_vif *cac_vif; /* vif on which we started CAC */ +#endif +}; + +bool rwnx_radar_detection_init(struct rwnx_radar *radar); +void rwnx_radar_detection_deinit(struct rwnx_radar *radar); +bool rwnx_radar_set_domain(struct rwnx_radar *radar, + enum nl80211_dfs_regions region); +void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain); +bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, u8 chain); +void rwnx_radar_start_cac(struct rwnx_radar *radar, u32 cac_time_ms, + struct rwnx_vif *vif); +void rwnx_radar_cancel_cac(struct rwnx_radar *radar); +void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw); +int rwnx_radar_dump_pattern_detector(char *buf, size_t len, + struct rwnx_radar *radar, u8 chain); +int rwnx_radar_dump_radar_detected(char *buf, size_t len, + struct rwnx_radar *radar, u8 chain); + +#else + +struct rwnx_radar { +}; + +static inline bool rwnx_radar_detection_init(struct rwnx_radar *radar) +{return true; } + +static inline void rwnx_radar_detection_deinit(struct rwnx_radar *radar) +{} + +static inline bool rwnx_radar_set_domain(struct rwnx_radar *radar, + enum nl80211_dfs_regions region) +{return true; } + +static inline void rwnx_radar_detection_enable(struct rwnx_radar *radar, + u8 enable, u8 chain) +{} + +static inline bool rwnx_radar_detection_is_enable(struct rwnx_radar *radar, + u8 chain) +{return false; } + +static inline void rwnx_radar_start_cac(struct rwnx_radar *radar, + u32 cac_time_ms, struct rwnx_vif *vif) +{} + +static inline void rwnx_radar_cancel_cac(struct rwnx_radar *radar) +{} + +static inline void rwnx_radar_detection_enable_on_cur_channel(struct rwnx_hw *rwnx_hw) +{} + +static inline int rwnx_radar_dump_pattern_detector(char *buf, size_t len, + struct rwnx_radar *radar, + u8 chain) +{return 0; } + +static inline int rwnx_radar_dump_radar_detected(char *buf, size_t len, + struct rwnx_radar *radar, + u8 chain) +{return 0; } + +#endif /* CONFIG_RWNX_RADAR */ + +#endif // _RWNX_RADAR_H_ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c new file mode 100644 index 000000000000..02641e41bd32 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c @@ -0,0 +1,2498 @@ +/** + ****************************************************************************** + * + * @file rwnx_rx.c + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#include <linux/dma-mapping.h> +#include <linux/ieee80211.h> +#include <linux/etherdevice.h> +#include <net/ieee80211_radiotap.h> + +#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 <linux/ip.h> +#include <linux/udp.h> +#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 (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 0 + 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_KERNEL); + 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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.h new file mode 100644 index 000000000000..36635350314b --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.h @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c new file mode 100644 index 000000000000..52ffbf64c6fb --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c @@ -0,0 +1,266 @@ +/** + ****************************************************************************** + * + * @file rwnx_strs.c + * + * @brief Miscellaneous debug strings + * + * Copyright (C) RivieraWaves 2014-2019 + * + ****************************************************************************** + */ + +#include "lmac_msg.h" +static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = { + [MSG_I(MM_RESET_REQ)] = "MM_RESET_REQ", + [MSG_I(MM_RESET_CFM)] = "MM_RESET_CFM", + [MSG_I(MM_START_REQ)] = "MM_START_REQ", + [MSG_I(MM_START_CFM)] = "MM_START_CFM", + [MSG_I(MM_VERSION_REQ)] = "MM_VERSION_REQ", + [MSG_I(MM_VERSION_CFM)] = "MM_VERSION_CFM", + [MSG_I(MM_ADD_IF_REQ)] = "MM_ADD_IF_REQ", + [MSG_I(MM_ADD_IF_CFM)] = "MM_ADD_IF_CFM", + [MSG_I(MM_REMOVE_IF_REQ)] = "MM_REMOVE_IF_REQ", + [MSG_I(MM_REMOVE_IF_CFM)] = "MM_REMOVE_IF_CFM", + [MSG_I(MM_STA_ADD_REQ)] = "MM_STA_ADD_REQ", + [MSG_I(MM_STA_ADD_CFM)] = "MM_STA_ADD_CFM", + [MSG_I(MM_STA_DEL_REQ)] = "MM_STA_DEL_REQ", + [MSG_I(MM_STA_DEL_CFM)] = "MM_STA_DEL_CFM", + [MSG_I(MM_SET_FILTER_REQ)] = "MM_SET_FILTER_REQ", + [MSG_I(MM_SET_FILTER_CFM)] = "MM_SET_FILTER_CFM", + [MSG_I(MM_SET_CHANNEL_REQ)] = "MM_SET_CHANNEL_REQ", + [MSG_I(MM_SET_CHANNEL_CFM)] = "MM_SET_CHANNEL_CFM", + [MSG_I(MM_SET_DTIM_REQ)] = "MM_SET_DTIM_REQ", + [MSG_I(MM_SET_DTIM_CFM)] = "MM_SET_DTIM_CFM", + [MSG_I(MM_SET_BEACON_INT_REQ)] = "MM_SET_BEACON_INT_REQ", + [MSG_I(MM_SET_BEACON_INT_CFM)] = "MM_SET_BEACON_INT_CFM", + [MSG_I(MM_SET_BASIC_RATES_REQ)] = "MM_SET_BASIC_RATES_REQ", + [MSG_I(MM_SET_BASIC_RATES_CFM)] = "MM_SET_BASIC_RATES_CFM", + [MSG_I(MM_SET_BSSID_REQ)] = "MM_SET_BSSID_REQ", + [MSG_I(MM_SET_BSSID_CFM)] = "MM_SET_BSSID_CFM", + [MSG_I(MM_SET_EDCA_REQ)] = "MM_SET_EDCA_REQ", + [MSG_I(MM_SET_EDCA_CFM)] = "MM_SET_EDCA_CFM", + [MSG_I(MM_SET_MODE_REQ)] = "MM_SET_MODE_REQ", + [MSG_I(MM_SET_MODE_CFM)] = "MM_SET_MODE_CFM", + [MSG_I(MM_SET_VIF_STATE_REQ)] = "MM_SET_VIF_STATE_REQ", + [MSG_I(MM_SET_VIF_STATE_CFM)] = "MM_SET_VIF_STATE_CFM", + [MSG_I(MM_SET_SLOTTIME_REQ)] = "MM_SET_SLOTTIME_REQ", + [MSG_I(MM_SET_SLOTTIME_CFM)] = "MM_SET_SLOTTIME_CFM", + [MSG_I(MM_SET_IDLE_REQ)] = "MM_SET_IDLE_REQ", + [MSG_I(MM_SET_IDLE_CFM)] = "MM_SET_IDLE_CFM", + [MSG_I(MM_KEY_ADD_REQ)] = "MM_KEY_ADD_REQ", + [MSG_I(MM_KEY_ADD_CFM)] = "MM_KEY_ADD_CFM", + [MSG_I(MM_KEY_DEL_REQ)] = "MM_KEY_DEL_REQ", + [MSG_I(MM_KEY_DEL_CFM)] = "MM_KEY_DEL_CFM", + [MSG_I(MM_BA_ADD_REQ)] = "MM_BA_ADD_REQ", + [MSG_I(MM_BA_ADD_CFM)] = "MM_BA_ADD_CFM", + [MSG_I(MM_BA_DEL_REQ)] = "MM_BA_DEL_REQ", + [MSG_I(MM_BA_DEL_CFM)] = "MM_BA_DEL_CFM", + [MSG_I(MM_PRIMARY_TBTT_IND)] = "MM_PRIMARY_TBTT_IND", + [MSG_I(MM_SECONDARY_TBTT_IND)] = "MM_SECONDARY_TBTT_IND", + [MSG_I(MM_SET_POWER_REQ)] = "MM_SET_POWER_REQ", + [MSG_I(MM_SET_POWER_CFM)] = "MM_SET_POWER_CFM", + [MSG_I(MM_DBG_TRIGGER_REQ)] = "MM_DBG_TRIGGER_REQ", + [MSG_I(MM_SET_PS_MODE_REQ)] = "MM_SET_PS_MODE_REQ", + [MSG_I(MM_SET_PS_MODE_CFM)] = "MM_SET_PS_MODE_CFM", + [MSG_I(MM_CHAN_CTXT_ADD_REQ)] = "MM_CHAN_CTXT_ADD_REQ", + [MSG_I(MM_CHAN_CTXT_ADD_CFM)] = "MM_CHAN_CTXT_ADD_CFM", + [MSG_I(MM_CHAN_CTXT_DEL_REQ)] = "MM_CHAN_CTXT_DEL_REQ", + [MSG_I(MM_CHAN_CTXT_DEL_CFM)] = "MM_CHAN_CTXT_DEL_CFM", + [MSG_I(MM_CHAN_CTXT_LINK_REQ)] = "MM_CHAN_CTXT_LINK_REQ", + [MSG_I(MM_CHAN_CTXT_LINK_CFM)] = "MM_CHAN_CTXT_LINK_CFM", + [MSG_I(MM_CHAN_CTXT_UNLINK_REQ)] = "MM_CHAN_CTXT_UNLINK_REQ", + [MSG_I(MM_CHAN_CTXT_UNLINK_CFM)] = "MM_CHAN_CTXT_UNLINK_CFM", + [MSG_I(MM_CHAN_CTXT_UPDATE_REQ)] = "MM_CHAN_CTXT_UPDATE_REQ", + [MSG_I(MM_CHAN_CTXT_UPDATE_CFM)] = "MM_CHAN_CTXT_UPDATE_CFM", + [MSG_I(MM_CHAN_CTXT_SCHED_REQ)] = "MM_CHAN_CTXT_SCHED_REQ", + [MSG_I(MM_CHAN_CTXT_SCHED_CFM)] = "MM_CHAN_CTXT_SCHED_CFM", + [MSG_I(MM_BCN_CHANGE_REQ)] = "MM_BCN_CHANGE_REQ", + [MSG_I(MM_BCN_CHANGE_CFM)] = "MM_BCN_CHANGE_CFM", + [MSG_I(MM_TIM_UPDATE_REQ)] = "MM_TIM_UPDATE_REQ", + [MSG_I(MM_TIM_UPDATE_CFM)] = "MM_TIM_UPDATE_CFM", + [MSG_I(MM_CONNECTION_LOSS_IND)] = "MM_CONNECTION_LOSS_IND", + [MSG_I(MM_CHANNEL_SWITCH_IND)] = "MM_CHANNEL_SWITCH_IND", + [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = "MM_CHANNEL_PRE_SWITCH_IND", + [MSG_I(MM_REMAIN_ON_CHANNEL_REQ)] = "MM_REMAIN_ON_CHANNEL_REQ", + [MSG_I(MM_REMAIN_ON_CHANNEL_CFM)] = "MM_REMAIN_ON_CHANNEL_CFM", + [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = "MM_REMAIN_ON_CHANNEL_EXP_IND", + [MSG_I(MM_PS_CHANGE_IND)] = "MM_PS_CHANGE_IND", + [MSG_I(MM_TRAFFIC_REQ_IND)] = "MM_TRAFFIC_REQ_IND", + [MSG_I(MM_SET_PS_OPTIONS_REQ)] = "MM_SET_PS_OPTIONS_REQ", + [MSG_I(MM_SET_PS_OPTIONS_CFM)] = "MM_SET_PS_OPTIONS_CFM", + [MSG_I(MM_P2P_VIF_PS_CHANGE_IND)] = "MM_P2P_VIF_PS_CHANGE_IND", + [MSG_I(MM_CSA_COUNTER_IND)] = "MM_CSA_COUNTER_IND", + [MSG_I(MM_CHANNEL_SURVEY_IND)] = "MM_CHANNEL_SURVEY_IND", + [MSG_I(MM_SET_P2P_NOA_REQ)] = "MM_SET_P2P_NOA_REQ", + [MSG_I(MM_SET_P2P_OPPPS_REQ)] = "MM_SET_P2P_OPPPS_REQ", + [MSG_I(MM_SET_P2P_NOA_CFM)] = "MM_SET_P2P_NOA_CFM", + [MSG_I(MM_SET_P2P_OPPPS_CFM)] = "MM_SET_P2P_OPPPS_CFM", + [MSG_I(MM_CFG_RSSI_REQ)] = "MM_CFG_RSSI_REQ", + [MSG_I(MM_RSSI_STATUS_IND)] = "MM_RSSI_STATUS_IND", + [MSG_I(MM_CSA_FINISH_IND)] = "MM_CSA_FINISH_IND", + [MSG_I(MM_CSA_TRAFFIC_IND)] = "MM_CSA_TRAFFIC_IND", + [MSG_I(MM_MU_GROUP_UPDATE_REQ)] = "MM_MU_GROUP_UPDATE_REQ", + [MSG_I(MM_MU_GROUP_UPDATE_CFM)] = "MM_MU_GROUP_UPDATE_CFM", + + [MSG_I(MM_SET_ARPOFFLOAD_REQ)] = "MM_SET_ARPOFFLOAD_REQ", + [MSG_I(MM_SET_ARPOFFLOAD_CFM)] = "MM_SET_ARPOFFLOAD_CFM", + [MSG_I(MM_SET_AGG_DISABLE_REQ)] = "MM_SET_AGG_DISABLE_REQ", + [MSG_I(MM_SET_AGG_DISABLE_CFM)] = "MM_SET_AGG_DISABLE_CFM", + [MSG_I(MM_SET_COEX_REQ)] = "MM_SET_COEX_REQ", + [MSG_I(MM_SET_COEX_CFM)] = "MM_SET_COEX_CFM", + [MSG_I(MM_SET_RF_CONFIG_REQ)] = "MM_SET_RF_CONFIG_REQ", + [MSG_I(MM_SET_RF_CONFIG_CFM)] = "MM_SET_RF_CONFIG_CFM", + [MSG_I(MM_SET_RF_CALIB_REQ)] = "MM_SET_RF_CALIB_REQ", + [MSG_I(MM_SET_RF_CALIB_CFM)] = "MM_SET_RF_CALIB_CFM", + + [MSG_I(MM_GET_MAC_ADDR_REQ)] = "MM_GET_MAC_ADDR_REQ", + [MSG_I(MM_GET_MAC_ADDR_CFM)] = "MM_GET_MAC_ADDR_CFM", + [MSG_I(MM_GET_STA_INFO_REQ)] = "MM_GET_STA_INFO_REQ", + [MSG_I(MM_GET_STA_INFO_CFM)] = "MM_GET_STA_INFO_CFM", + [MSG_I(MM_SET_TXPWR_IDX_LVL_REQ)] = "MM_SET_TXPWR_IDX_LVL_REQ", + [MSG_I(MM_SET_TXPWR_IDX_LVL_CFM)] = "MM_SET_TXPWR_IDX_LVL_CFM", + [MSG_I(MM_SET_TXPWR_OFST_REQ)] = "MM_SET_TXPWR_OFST_REQ", + [MSG_I(MM_SET_TXPWR_OFST_CFM)] = "MM_SET_TXPWR_OFST_CFM", + [MSG_I(MM_SET_STACK_START_REQ)] = "MM_SET_STACK_START_REQ", + [MSG_I(MM_SET_STACK_START_CFM)] = "MM_SET_STACK_START_CFM", + [MSG_I(MM_APM_STALOSS_IND)] = "MM_APM_STALOSS_IND", + [MSG_I(MM_SET_VENDOR_HWCONFIG_REQ)] = "MM_SET_VENDOR_HWCONFIG_REQ", + [MSG_I(MM_SET_VENDOR_HWCONFIG_CFM)] = "MM_SET_VENDOR_HWCONFIG_CFM", + [MSG_I(MM_GET_FW_VERSION_REQ)] = "MM_GET_FW_VERSION_REQ", + [MSG_I(MM_GET_FW_VERSION_CFM)] = "MM_GET_FW_VERSION_CFM", + [MSG_I(MM_SET_RESUME_RESTORE_REQ)] = "MM_SET_RESUME_RESTORE_REQ", + [MSG_I(MM_SET_RESUME_RESTORE_CFM)] = "MM_SET_RESUME_RESTORE_CFM", + [MSG_I(MM_GET_WIFI_DISABLE_REQ)] = "MM_GET_WIFI_DISABLE_REQ", + [MSG_I(MM_GET_WIFI_DISABLE_CFM)] = "MM_GET_WIFI_DISABLE_CFM", + [MSG_I(MM_CFG_RSSI_CFM)] = "MM_CFG_RSSI_CFM", +}; + +static const char *const rwnx_dbgid2str[MSG_I(DBG_MAX)] = { + [MSG_I(DBG_MEM_READ_REQ)] = "DBG_MEM_READ_REQ", + [MSG_I(DBG_MEM_READ_CFM)] = "DBG_MEM_READ_CFM", + [MSG_I(DBG_MEM_WRITE_REQ)] = "DBG_MEM_WRITE_REQ", + [MSG_I(DBG_MEM_WRITE_CFM)] = "DBG_MEM_WRITE_CFM", + [MSG_I(DBG_SET_MOD_FILTER_REQ)] = "DBG_SET_MOD_FILTER_REQ", + [MSG_I(DBG_SET_MOD_FILTER_CFM)] = "DBG_SET_MOD_FILTER_CFM", + [MSG_I(DBG_SET_SEV_FILTER_REQ)] = "DBG_SET_SEV_FILTER_REQ", + [MSG_I(DBG_SET_SEV_FILTER_CFM)] = "DBG_SET_SEV_FILTER_CFM", + [MSG_I(DBG_ERROR_IND)] = "DBG_ERROR_IND", + [MSG_I(DBG_GET_SYS_STAT_REQ)] = "DBG_GET_SYS_STAT_REQ", + [MSG_I(DBG_GET_SYS_STAT_CFM)] = "DBG_GET_SYS_STAT_CFM", +}; + +static const char *const rwnx_scanid2str[MSG_I(SCAN_MAX)] = { + [MSG_I(SCAN_START_REQ)] = "SCAN_START_REQ", + [MSG_I(SCAN_START_CFM)] = "SCAN_START_CFM", + [MSG_I(SCAN_DONE_IND)] = "SCAN_DONE_IND", +}; + +static const char *const rwnx_tdlsid2str[MSG_I(TDLS_MAX)] = { + [MSG_I(TDLS_CHAN_SWITCH_CFM)] = "TDLS_CHAN_SWITCH_CFM", + [MSG_I(TDLS_CHAN_SWITCH_REQ)] = "TDLS_CHAN_SWITCH_REQ", + [MSG_I(TDLS_CHAN_SWITCH_IND)] = "TDLS_CHAN_SWITCH_IND", + [MSG_I(TDLS_CHAN_SWITCH_BASE_IND)] = "TDLS_CHAN_SWITCH_BASE_IND", + [MSG_I(TDLS_CANCEL_CHAN_SWITCH_REQ)] = "TDLS_CANCEL_CHAN_SWITCH_REQ", + [MSG_I(TDLS_CANCEL_CHAN_SWITCH_CFM)] = "TDLS_CANCEL_CHAN_SWITCH_CFM", + [MSG_I(TDLS_PEER_PS_IND)] = "TDLS_PEER_PS_IND", + [MSG_I(TDLS_PEER_TRAFFIC_IND_REQ)] = "TDLS_PEER_TRAFFIC_IND_REQ", + [MSG_I(TDLS_PEER_TRAFFIC_IND_CFM)] = "TDLS_PEER_TRAFFIC_IND_CFM", +}; + +#ifdef CONFIG_RWNX_FULLMAC + +static const char *const rwnx_scanuid2str[MSG_I(SCANU_MAX)] = { + [MSG_I(SCANU_START_REQ)] = "SCANU_START_REQ", + [MSG_I(SCANU_START_CFM)] = "SCANU_START_CFM", + [MSG_I(SCANU_JOIN_REQ)] = "SCANU_JOIN_REQ", + [MSG_I(SCANU_JOIN_CFM)] = "SCANU_JOIN_CFM", + [MSG_I(SCANU_RESULT_IND)] = "SCANU_RESULT_IND", + [MSG_I(SCANU_FAST_REQ)] = "SCANU_FAST_REQ", + [MSG_I(SCANU_FAST_CFM)] = "SCANU_FAST_CFM", + [MSG_I(SCANU_VENDOR_IE_REQ)] = "SCANU_VENDOR_IE_REQ", + [MSG_I(SCANU_VENDOR_IE_CFM)] = "SCANU_VENDOR_IE_CFM", + [MSG_I(SCANU_START_CFM_ADDTIONAL)] = "SCANU_START_CFM_ADDTIONAL", + [MSG_I(SCANU_CANCEL_REQ)] = "SCANU_CANCEL_REQ", + [MSG_I(SCANU_CANCEL_CFM)] = "SCANU_CANCEL_CFM", +}; + +static const char *const rwnx_meid2str[MSG_I(ME_MAX)] = { + [MSG_I(ME_CONFIG_REQ)] = "ME_CONFIG_REQ", + [MSG_I(ME_CONFIG_CFM)] = "ME_CONFIG_CFM", + [MSG_I(ME_CHAN_CONFIG_REQ)] = "ME_CHAN_CONFIG_REQ", + [MSG_I(ME_CHAN_CONFIG_CFM)] = "ME_CHAN_CONFIG_CFM", + [MSG_I(ME_SET_CONTROL_PORT_REQ)] = "ME_SET_CONTROL_PORT_REQ", + [MSG_I(ME_SET_CONTROL_PORT_CFM)] = "ME_SET_CONTROL_PORT_CFM", + [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = "ME_TKIP_MIC_FAILURE_IND", + [MSG_I(ME_STA_ADD_REQ)] = "ME_STA_ADD_REQ", + [MSG_I(ME_STA_ADD_CFM)] = "ME_STA_ADD_CFM", + [MSG_I(ME_STA_DEL_REQ)] = "ME_STA_DEL_REQ", + [MSG_I(ME_STA_DEL_CFM)] = "ME_STA_DEL_CFM", + [MSG_I(ME_TX_CREDITS_UPDATE_IND)]= "ME_TX_CREDITS_UPDATE_IND", + [MSG_I(ME_RC_STATS_REQ)] = "ME_RC_STATS_REQ", + [MSG_I(ME_RC_STATS_CFM)] = "ME_RC_STATS_CFM", + [MSG_I(ME_RC_SET_RATE_REQ)] = "ME_RC_SET_RATE_REQ", + [MSG_I(ME_TRAFFIC_IND_REQ)] = "ME_TRAFFIC_IND_REQ", + [MSG_I(ME_TRAFFIC_IND_CFM)] = "ME_TRAFFIC_IND_CFM", + [MSG_I(ME_SET_PS_MODE_REQ)] = "ME_SET_PS_MODE_REQ", + [MSG_I(ME_SET_PS_MODE_CFM)] = "ME_SET_PS_MODE_CFM", +}; + +static const char *const rwnx_smid2str[MSG_I(SM_MAX)] = { + [MSG_I(SM_CONNECT_REQ)] = "SM_CONNECT_REQ", + [MSG_I(SM_CONNECT_CFM)] = "SM_CONNECT_CFM", + [MSG_I(SM_CONNECT_IND)] = "SM_CONNECT_IND", + [MSG_I(SM_DISCONNECT_REQ)] = "SM_DISCONNECT_REQ", + [MSG_I(SM_DISCONNECT_CFM)] = "SM_DISCONNECT_CFM", + [MSG_I(SM_DISCONNECT_IND)] = "SM_DISCONNECT_IND", + [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_IND)] = "SM_EXTERNAL_AUTH_REQUIRED_IND", + [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP", + [MSG_I(SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM)] = "SM_EXTERNAL_AUTH_REQUIRED_RSP_CFM", +}; + +static const char *const rwnx_apmid2str[MSG_I(APM_MAX)] = { + [MSG_I(APM_START_REQ)] = "APM_START_REQ", + [MSG_I(APM_START_CFM)] = "APM_START_CFM", + [MSG_I(APM_STOP_REQ)] = "APM_STOP_REQ", + [MSG_I(APM_STOP_CFM)] = "APM_STOP_CFM", + [MSG_I(APM_START_CAC_REQ)] = "APM_START_CAC_REQ", + [MSG_I(APM_START_CAC_CFM)] = "APM_START_CAC_CFM", + [MSG_I(APM_STOP_CAC_REQ)] = "APM_STOP_CAC_REQ", + [MSG_I(APM_STOP_CAC_CFM)] = "APM_STOP_CAC_CFM", + [MSG_I(APM_SET_BEACON_IE_REQ)] = "APM_SET_BEACON_IE_REQ", + [MSG_I(APM_SET_BEACON_IE_CFM)] = "APM_SET_BEACON_IE_CFM", +}; + +static const char *const rwnx_meshid2str[MSG_I(MESH_MAX)] = { + [MSG_I(MESH_START_REQ)] = "MESH_START_REQ", + [MSG_I(MESH_START_CFM)] = "MESH_START_CFM", + [MSG_I(MESH_STOP_REQ)] = "MESH_STOP_REQ", + [MSG_I(MESH_STOP_CFM)] = "MESH_STOP_CFM", + [MSG_I(MESH_UPDATE_REQ)] = "MESH_UPDATE_REQ", + [MSG_I(MESH_UPDATE_CFM)] = "MESH_UPDATE_CFM", + [MSG_I(MESH_PATH_CREATE_REQ)] = "MESH_PATH_CREATE_REQ", + [MSG_I(MESH_PATH_CREATE_CFM)] = "MESH_PATH_CREATE_CFM", + [MSG_I(MESH_PATH_UPDATE_REQ)] = "MESH_PATH_UPDATE_REQ", + [MSG_I(MESH_PATH_UPDATE_CFM)] = "MESH_PATH_UPDATE_CFM", + [MSG_I(MESH_PROXY_ADD_REQ)] = "MESH_PROXY_ADD_REQ", + [MSG_I(MESH_PEER_UPDATE_IND)] = "MESH_PEER_UPDATE_IND", + [MSG_I(MESH_PATH_UPDATE_IND)] = "MESH_PATH_UPDATE_IND", + [MSG_I(MESH_PROXY_UPDATE_IND)] = "MESH_PROXY_UPDATE_IND", +}; + +#endif /* CONFIG_RWNX_FULLMAC */ + +const char *const *rwnx_id2str[TASK_LAST_EMB + 1] = { + [TASK_MM] = rwnx_mmid2str, + [TASK_DBG] = rwnx_dbgid2str, + [TASK_SCAN] = rwnx_scanid2str, + [TASK_TDLS] = rwnx_tdlsid2str, +#ifdef CONFIG_RWNX_FULLMAC + [TASK_SCANU] = rwnx_scanuid2str, + [TASK_ME] = rwnx_meid2str, + [TASK_SM] = rwnx_smid2str, + [TASK_APM] = rwnx_apmid2str, + [TASK_MESH] = rwnx_meshid2str, +#endif +}; diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.h new file mode 100644 index 000000000000..7dc83aba8bea --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.h @@ -0,0 +1,31 @@ +/** + **************************************************************************************** + * + * @file rwnx_strs.h + * + * @brief Miscellaneous debug strings + * + * Copyright (C) RivieraWaves 2014-2019 + * + **************************************************************************************** + */ + +#ifndef _RWNX_STRS_H_ +#define _RWNX_STRS_H_ + +#ifdef CONFIG_RWNX_FHOST + +#define RWNX_ID2STR(tag) "Cmd" + +#else +#include "lmac_msg.h" + +#define RWNX_ID2STR(tag) (((MSG_T(tag) < ARRAY_SIZE(rwnx_id2str)) && \ + (rwnx_id2str[MSG_T(tag)]) && \ + ((rwnx_id2str[MSG_T(tag)])[MSG_I(tag)])) ? \ + (rwnx_id2str[MSG_T(tag)])[MSG_I(tag)] : "unknown") + +extern const char *const *rwnx_id2str[TASK_LAST_EMB + 1]; +#endif /* CONFIG_RWNX_FHOST */ + +#endif /* _RWNX_STRS_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tdls.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tdls.c new file mode 100644 index 000000000000..34196edac508 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tdls.c @@ -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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tdls.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tdls.h new file mode 100644 index 000000000000..590b420f6ec6 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tdls.h @@ -0,0 +1,54 @@ +/** + ****************************************************************************** + * + * @file rwnx_tdls.h + * + * @brief TDLS function declarations + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#ifndef RWNX_TDLS_H_ +#define RWNX_TDLS_H_ + +#include "rwnx_defs.h" + +struct ieee_types_header { + u8 element_id; + u8 len; +} __packed; + +struct ieee_types_bss_co_2040 { + struct ieee_types_header ieee_hdr; + u8 bss_2040co; +} __packed; + +struct ieee_types_extcap { + struct ieee_types_header ieee_hdr; + u8 ext_capab[8]; +} __packed; + +struct ieee_types_vht_cap { + struct ieee_types_header ieee_hdr; + struct ieee80211_vht_cap vhtcap; +} __packed; + +struct ieee_types_vht_oper { + struct ieee_types_header ieee_hdr; + struct ieee80211_vht_operation vhtoper; +} __packed; + +struct ieee_types_aid { + struct ieee_types_header ieee_hdr; + u16 aid; +} __packed; + +int rwnx_tdls_send_mgmt_packet_data(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, bool initiator, + const u8 *extra_ies, size_t extra_ies_len, u8 oper_class, + struct cfg80211_chan_def *chandef); + +#endif /* RWNX_TDLS_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_testmode.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_testmode.c new file mode 100644 index 000000000000..ef97354d08df --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_testmode.c @@ -0,0 +1,230 @@ +/** + **************************************************************************************** + * + * @file rwnx_testmode.c + * + * @brief Test mode function definitions + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ + +#include <net/mac80211.h> +#include <net/netlink.h> + +#include "rwnx_testmode.h" +#include "rwnx_msg_tx.h" +#include "rwnx_dini.h" +#include "reg_access.h" + +/* + * This function handles the user application commands for register access. + * + * It retrieves command ID carried with RWNX_TM_ATTR_COMMAND and calls to the + * handlers respectively. + * + * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the + * mandatory fields(RWNX_TM_ATTR_REG_OFFSET,RWNX_TM_ATTR_REG_VALUE32) + * are missing; Otherwise 0 is replied indicating the success of the command execution. + * + * If RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_READ, the register read + * value is returned with RWNX_TM_ATTR_REG_VALUE32. + * + * @hw: ieee80211_hw object that represents the device + * @tb: general message fields from the user space + */ +int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct rwnx_hw *rwnx_hw = hw->priv; + u32 mem_addr, val32; + struct sk_buff *skb; + int status = 0; + + /* First check if register address is there */ + if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { + printk("Error finding register offset\n"); + return -ENOMSG; + } + + mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); + + switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { + case RWNX_TM_CMD_APP2DEV_REG_READ: + { + struct dbg_mem_read_cfm mem_read_cfm; + + /*** Send the command to the LMAC ***/ + status = rwnx_send_dbg_mem_read_req(rwnx_hw, mem_addr, &mem_read_cfm); + if (status) + return status; + + /* Allocate the answer message */ + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); + if (!skb) { + printk("Error allocating memory\n"); + return -ENOMEM; + } + + val32 = mem_read_cfm.memdata; + if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, val32)) + goto nla_put_failure; + + /* Send the answer to upper layer */ + status = cfg80211_testmode_reply(skb); + if (status < 0) + printk("Error sending msg : %d\n", status); + } + break; + + case RWNX_TM_CMD_APP2DEV_REG_WRITE: + { + if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { + printk("Error finding value to write\n"); + return -ENOMSG; + } else { + val32 = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); + /* Send the command to the LMAC */ + status = rwnx_send_dbg_mem_write_req(rwnx_hw, mem_addr, val32); + if (status) + return status; + } + } + break; + + default: + printk("Unknown testmode register command ID\n"); + return -ENOSYS; + } + + return status; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} + +/* + * This function handles the user application commands for Debug filter settings. + * + * @hw: ieee80211_hw object that represents the device + * @tb: general message fields from the user space + */ +int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct rwnx_hw *rwnx_hw = hw->priv; + u32 filter; + int status = 0; + + /* First check if the filter is there */ + if (!tb[RWNX_TM_ATTR_REG_FILTER]) { + printk("Error finding filter value\n"); + return -ENOMSG; + } + + filter = nla_get_u32(tb[RWNX_TM_ATTR_REG_FILTER]); + RWNX_DBG("testmode debug filter, setting: 0x%x\n", filter); + + switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { + case RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER: + { + /* Send the command to the LMAC */ + status = rwnx_send_dbg_set_mod_filter_req(rwnx_hw, filter); + if (status) + return status; + } + break; + case RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER: + { + /* Send the command to the LMAC */ + status = rwnx_send_dbg_set_sev_filter_req(rwnx_hw, filter); + if (status) + return status; + } + break; + + default: + printk("Unknown testmode register command ID\n"); + return -ENOSYS; + } + + return status; +} + +/* + * This function handles the user application commands for register access without using + * the normal LMAC messaging way. + * This time register access will be done through direct PCI BAR windows. This can be used + * to access registers even when the :AMC FW is stuck. + * + * @hw: ieee80211_hw object that represents the device + * @tb: general message fields from the user space + */ +int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb) +{ + struct rwnx_hw *rwnx_hw = hw->priv; + struct rwnx_plat *rwnx_plat = rwnx_hw->plat; + u32 mem_addr; + struct sk_buff *skb; + int status = 0; + volatile unsigned int reg_value = 0; + unsigned int offset; + + /* First check if register address is there */ + if (!tb[RWNX_TM_ATTR_REG_OFFSET]) { + printk("Error finding register offset\n"); + return -ENOMSG; + } + + mem_addr = nla_get_u32(tb[RWNX_TM_ATTR_REG_OFFSET]); + offset = mem_addr & 0x00FFFFFF; + + switch (nla_get_u32(tb[RWNX_TM_ATTR_COMMAND])) { + case RWNX_TM_CMD_APP2DEV_REG_READ_DBG: + { + /*** Send the command to the LMAC ***/ + reg_value = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, offset); + + /* Allocate the answer message */ + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); + if (!skb) { + printk("Error allocating memory\n"); + return -ENOMEM; + } + + if (nla_put_u32(skb, RWNX_TM_ATTR_REG_VALUE32, reg_value)) + goto nla_put_failure; + + /* Send the answer to upper layer */ + status = cfg80211_testmode_reply(skb); + if (status < 0) + printk("Error sending msg : %d\n", status); + } + break; + + case RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG: + { + if (!tb[RWNX_TM_ATTR_REG_VALUE32]) { + printk("Error finding value to write\n"); + return -ENOMSG; + } else { + reg_value = nla_get_u32(tb[RWNX_TM_ATTR_REG_VALUE32]); + + /* Send the command to the LMAC */ + RWNX_REG_WRITE(reg_value, rwnx_plat, RWNX_ADDR_SYSTEM, + offset); + } + } + break; + + default: + printk("Unknown testmode register command ID\n"); + return -ENOSYS; + } + + return status; + +nla_put_failure: + kfree_skb(skb); + return -EMSGSIZE; +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_testmode.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_testmode.h new file mode 100644 index 000000000000..9d1bca47eb50 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_testmode.h @@ -0,0 +1,64 @@ +/** + **************************************************************************************** + * + * @file rwnx_testmode.h + * + * @brief Test mode function declarations + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ + +#ifndef RWNX_TESTMODE_H_ +#define RWNX_TESTMODE_H_ + +#include <net/mac80211.h> +#include <net/netlink.h> + +/* Commands from user space to kernel space(RWNX_TM_CMD_APP2DEV_XX) and + * from and kernel space to user space(RWNX_TM_CMD_DEV2APP_XX). + * The command ID is carried with RWNX_TM_ATTR_COMMAND. + */ +enum rwnx_tm_cmd_t { + /* commands from user application to access register */ + RWNX_TM_CMD_APP2DEV_REG_READ = 1, + RWNX_TM_CMD_APP2DEV_REG_WRITE, + + /* commands from user application to select the Debug levels */ + RWNX_TM_CMD_APP2DEV_SET_DBGMODFILTER, + RWNX_TM_CMD_APP2DEV_SET_DBGSEVFILTER, + + /* commands to access registers without sending messages to LMAC layer, + * this must be used when LMAC FW is stuck. */ + RWNX_TM_CMD_APP2DEV_REG_READ_DBG, + RWNX_TM_CMD_APP2DEV_REG_WRITE_DBG, + + RWNX_TM_CMD_MAX, +}; + +enum rwnx_tm_attr_t { + RWNX_TM_ATTR_NOT_APPLICABLE = 0, + + RWNX_TM_ATTR_COMMAND, + + /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_REG_XXX, + * The mandatory fields are: + * RWNX_TM_ATTR_REG_OFFSET for the offset of the target register; + * RWNX_TM_ATTR_REG_VALUE32 for value */ + RWNX_TM_ATTR_REG_OFFSET, + RWNX_TM_ATTR_REG_VALUE32, + + /* When RWNX_TM_ATTR_COMMAND is RWNX_TM_CMD_APP2DEV_SET_DBGXXXFILTER, + * The mandatory field is RWNX_TM_ATTR_REG_FILTER. */ + RWNX_TM_ATTR_REG_FILTER, + + RWNX_TM_ATTR_MAX, +}; + +/***********************************************************************/ +int rwnx_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb); +int rwnx_testmode_dbg_filter(struct ieee80211_hw *hw, struct nlattr **tb); +int rwnx_testmode_reg_dbg(struct ieee80211_hw *hw, struct nlattr **tb); + +#endif /* RWNX_TESTMODE_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c new file mode 100644 index 000000000000..7be91e061cf3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c @@ -0,0 +1,1948 @@ +/** + ****************************************************************************** + * + * @file rwnx_tx.c + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#include <linux/dma-mapping.h> +#include <linux/etherdevice.h> +#include <net/sock.h> + +#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) { + printk("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; + } + +#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 + + 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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.h new file mode 100644 index 000000000000..a4036dc0c2b0 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.h @@ -0,0 +1,188 @@ +/** + ****************************************************************************** + * + * @file rwnx_tx.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ +#ifndef _RWNX_TX_H_ +#define _RWNX_TX_H_ + +#include <linux/ieee80211.h> +#include <net/cfg80211.h> +#include <linux/netdevice.h> +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c new file mode 100644 index 000000000000..a776e31e9a09 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c @@ -0,0 +1,1351 @@ +/** + ****************************************************************************** + * + * @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}; + +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 + /* 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)) { + 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 */ + if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && + skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART) { + txq->status &= ~RWNX_TXQ_NDEV_FLOW_CTRL; + netif_wake_subqueue(txq->ndev, txq->ndev_idx); +#ifdef CREATE_TRACE_POINTS + trace_txq_flowctrl_restart(txq); +#endif + } +#endif /* CONFIG_ONE_TXQ */ +#endif /* CONFIG_RWNX_FULLMAC */ + } + + + if (mu_enable) + rwnx_txq_release_mu_lock(rwnx_hw); +} + +/** + * rwnx_hwq_process_all - Process all HW queue list + * + * @rwnx_hw: Driver main data + * + * Loop over all HWQ, and process them if needed + * To be called with tx_lock hold + */ +void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw) +{ + int id; + + rwnx_mu_group_sta_select(rwnx_hw); + + for (id = ARRAY_SIZE(rwnx_hw->hwq) - 1; id >= 0 ; id--) { + if (rwnx_hw->hwq[id].need_processing) { + rwnx_hwq_process(rwnx_hw, &rwnx_hw->hwq[id]); + } + } +} + +/** + * rwnx_hwq_init - Initialize all hwq structures + * + * @rwnx_hw: Driver main data + * + */ +void rwnx_hwq_init(struct rwnx_hw *rwnx_hw) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(rwnx_hw->hwq); i++) { + struct rwnx_hwq *hwq = &rwnx_hw->hwq[i]; + + hwq->id = i; + hwq->size = nx_txdesc_cnt[i]; + INIT_LIST_HEAD(&hwq->list); + + } +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.h new file mode 100644 index 000000000000..47de68f8b9f3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.h @@ -0,0 +1,402 @@ +/** + **************************************************************************************** + * + * @file rwnx_txq.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + **************************************************************************************** + */ +#ifndef _RWNX_TXQ_H_ +#define _RWNX_TXQ_H_ + +#include <linux/types.h> +#include <linux/bitops.h> +#include <linux/ieee80211.h> + +#ifdef CONFIG_RWNX_FULLMAC +/** + * Fullmac TXQ configuration: + * - STA: 1 TXQ per TID (limited to 8) + * 1 TXQ for bufferable MGT frames + * - VIF: 1 TXQ for Multi/Broadcast + + * 1 TXQ for MGT for unknown STAs or non-bufferable MGT frames + * - 1 TXQ for offchannel transmissions + * + * + * Txq mapping looks like + * for NX_REMOTE_STA_MAX=10 and NX_VIRT_DEV_MAX=4 + * + * | TXQ | NDEV_ID | VIF | STA | TID | HWQ | + * |-----+---------+-----+-------+------+-----|- + * | 0 | 0 | | 0 | 0 | 1 | 9 TXQ per STA + * | 1 | 1 | | 0 | 1 | 0 | (8 data + 1 mgmt) + * | 2 | 2 | | 0 | 2 | 0 | + * | 3 | 3 | | 0 | 3 | 1 | + * | 4 | 4 | | 0 | 4 | 2 | + * | 5 | 5 | | 0 | 5 | 2 | + * | 6 | 6 | | 0 | 6 | 3 | + * | 7 | 7 | | 0 | 7 | 3 | + * | 8 | N/A | | 0 | MGMT | 3 | + * |-----+---------+-----+-------+------+-----|- + * | ... | | | | | | Same for all STAs + * |-----+---------+-----+-------+------+-----|- + * | 90 | 80 | 0 | BC/MC | 0 | 1/4 | 1 TXQ for BC/MC per VIF + * | ... | | | | | | + * | 93 | 80 | 3 | BC/MC | 0 | 1/4 | + * |-----+---------+-----+-------+------+-----|- + * | 94 | N/A | 0 | N/A | MGMT | 3 | 1 TXQ for unknown STA per VIF + * | ... | | | | | | + * | 97 | N/A | 3 | N/A | MGMT | 3 | + * |-----+---------+-----+-------+------+-----|- + * | 98 | N/A | | N/A | MGMT | 3 | 1 TXQ for offchannel frame + */ +#define NX_NB_TID_PER_STA 8 +#define NX_NB_TXQ_PER_STA (NX_NB_TID_PER_STA + 1) +#define NX_NB_TXQ_PER_VIF 2 +#define NX_NB_TXQ ((NX_NB_TXQ_PER_STA * NX_REMOTE_STA_MAX) + \ + (NX_NB_TXQ_PER_VIF * NX_VIRT_DEV_MAX) + 1) + +#define NX_FIRST_VIF_TXQ_IDX (NX_REMOTE_STA_MAX * NX_NB_TXQ_PER_STA) +#define NX_FIRST_BCMC_TXQ_IDX NX_FIRST_VIF_TXQ_IDX +#define NX_FIRST_UNK_TXQ_IDX (NX_FIRST_BCMC_TXQ_IDX + NX_VIRT_DEV_MAX) + +#define NX_OFF_CHAN_TXQ_IDX (NX_FIRST_VIF_TXQ_IDX + \ + (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) + +#define NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC (NX_REMOTE_STA_MAX_FOR_OLD_IC * NX_NB_TXQ_PER_STA) +#define NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC +#define NX_FIRST_UNK_TXQ_IDX_FOR_OLD_IC (NX_FIRST_BCMC_TXQ_IDX_FOR_OLD_IC + NX_VIRT_DEV_MAX) + +#define NX_OFF_CHAN_TXQ_IDX_FOR_OLD_IC (NX_FIRST_VIF_TXQ_IDX_FOR_OLD_IC + \ + (NX_VIRT_DEV_MAX * NX_NB_TXQ_PER_VIF)) + + +#define NX_BCMC_TXQ_TYPE 0 +#define NX_UNK_TXQ_TYPE 1 + +/** + * Each data TXQ is a netdev queue. TXQ to send MGT are not data TXQ as + * they did not recieved buffer from netdev interface. + * Need to allocate the maximum case. + * AP : all STAs + 1 BC/MC + */ +#define NX_NB_NDEV_TXQ ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) + 1) +#define NX_NB_NDEV_TXQ_FOR_OLD_IC ((NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) + 1) + +#define NX_BCMC_TXQ_NDEV_IDX (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX) +#define NX_BCMC_TXQ_NDEV_IDX_FOR_OLD_IC (NX_NB_TID_PER_STA * NX_REMOTE_STA_MAX_FOR_OLD_IC) +#define NX_STA_NDEV_IDX(tid, sta_idx) ((tid) + (sta_idx) * NX_NB_TID_PER_STA) +#define NDEV_NO_TXQ 0xffff +#if (NX_NB_NDEV_TXQ >= NDEV_NO_TXQ) +#error("Need to increase struct rwnx_txq->ndev_idx size") +#endif + +/* stop netdev queue when number of queued buffers if greater than this */ +#define RWNX_NDEV_FLOW_CTRL_STOP 64 +/* restart netdev queue when number of queued buffers is lower than this */ +#define RWNX_NDEV_FLOW_CTRL_RESTART 64 + +#endif /* CONFIG_RWNX_FULLMAC */ + +#define TXQ_INACTIVE 0xffff +#if (NX_NB_TXQ >= TXQ_INACTIVE) +#error("Need to increase struct rwnx_txq->idx size") +#endif + +#define NX_TXQ_INITIAL_CREDITS 64 + +/** + * TXQ tid sorted by decreasing priority + */ +extern const int nx_tid_prio[NX_NB_TID_PER_STA]; + +/** + * struct rwnx_hwq - Structure used to save information relative to + * an AC TX queue (aka HW queue) + * @list: List of TXQ, that have buffers ready for this HWQ + * @credits: available credit for the queue (i.e. nb of buffers that + * can be pushed to FW ) + * @id Id of the HWQ among RWNX_HWQ_.... + * @size size of the queue + * @need_processing Indicate if hwq should be processed + * @len number of packet ready to be pushed to fw for this HW queue + * @len_stop threshold to stop mac80211(i.e. netdev) queues. Stop queue when + * driver has more than @len_stop packets ready. + * @len_start threshold to wake mac8011 queues. Wake queue when driver has + * less than @len_start packets ready. + */ +struct rwnx_hwq { + struct list_head list; + u8 size; + u8 id; + bool need_processing; +}; + +/** + * enum rwnx_push_flags - Flags of pushed buffer + * + * @RWNX_PUSH_RETRY Pushing a buffer for retry + * @RWNX_PUSH_IMMEDIATE Pushing a buffer without queuing it first + */ +enum rwnx_push_flags { + RWNX_PUSH_RETRY = BIT(0), + RWNX_PUSH_IMMEDIATE = BIT(1), +}; + +/** + * enum rwnx_txq_flags - TXQ status flag + * + * @RWNX_TXQ_IN_HWQ_LIST: The queue is scheduled for transmission + * @RWNX_TXQ_STOP_FULL: No more credits for the queue + * @RWNX_TXQ_STOP_CSA: CSA is in progress + * @RWNX_TXQ_STOP_STA_PS: Destiniation sta is currently in power save mode + * @RWNX_TXQ_STOP_VIF_PS: Vif owning this queue is currently in power save mode + * @RWNX_TXQ_STOP_CHAN: Channel of this queue is not the current active channel + * @RWNX_TXQ_STOP_MU_POS: TXQ is stopped waiting for all the buffers pushed to + * fw to be confirmed + * @RWNX_TXQ_STOP: All possible reason to have a txq stopped + * @RWNX_TXQ_NDEV_FLOW_CTRL: associated netdev queue is currently stopped. + * Note: when a TXQ is flowctrl it is NOT stopped + */ +enum rwnx_txq_flags { + RWNX_TXQ_IN_HWQ_LIST = BIT(0), + RWNX_TXQ_STOP_FULL = BIT(1), + RWNX_TXQ_STOP_CSA = BIT(2), + RWNX_TXQ_STOP_STA_PS = BIT(3), + RWNX_TXQ_STOP_VIF_PS = BIT(4), + RWNX_TXQ_STOP_CHAN = BIT(5), + RWNX_TXQ_STOP_MU_POS = BIT(6), + RWNX_TXQ_STOP = (RWNX_TXQ_STOP_FULL | RWNX_TXQ_STOP_CSA | + RWNX_TXQ_STOP_STA_PS | RWNX_TXQ_STOP_VIF_PS | + RWNX_TXQ_STOP_CHAN), + RWNX_TXQ_NDEV_FLOW_CTRL = BIT(7), +}; + + +/** + * struct rwnx_txq - Structure used to save information relative to + * a RA/TID TX queue + * + * @idx: Unique txq idx. Set to TXQ_INACTIVE if txq is not used. + * @status: bitfield of @rwnx_txq_flags. + * @credits: available credit for the queue (i.e. nb of buffers that + * can be pushed to FW). + * @pkt_sent: number of consecutive pkt sent without leaving HW queue list + * @pkt_pushed: number of pkt currently pending for transmission confirmation + * @sched_list: list node for HW queue schedule list (rwnx_hwq.list) + * @sk_list: list of buffers to push to fw + * @last_retry_skb: pointer on the last skb in @sk_list that is a retry. + * (retry skb are stored at the beginning of the list) + * NULL if no retry skb is queued in @sk_list + * @nb_retry: Number of retry packet queued. + * @hwq: Pointer on the associated HW queue. + * @push_limit: number of packet to push before removing the txq from hwq list. + * (we always have push_limit < skb_queue_len(sk_list)) + * @tid: TID + * + * SOFTMAC specific: + * @baw: Block Ack window information + * @amsdu_anchor: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. + * NULL if no A-MSDU frame is in construction + * @amsdu_ht_len_cap: + * @amsdu_vht_len_cap: + * @nb_ready_mac80211: Number of buffer ready in mac80211 txq + * + * FULLMAC specific + * @ps_id: Index to use for Power save mode (LEGACY or UAPSD) + * @ndev_idx: txq idx from netdev point of view (0xFF for non netdev queue) + * @ndev: pointer to ndev of the corresponding vif + * @amsdu: pointer to rwnx_sw_txhdr of the first subframe of the A-MSDU. + * NULL if no A-MSDU frame is in construction + * @amsdu_len: Maximum size allowed for an A-MSDU. 0 means A-MSDU not allowed + */ +struct rwnx_txq { + u16 idx; + u8 status; + s8 credits; + u8 pkt_sent; + u8 pkt_pushed[CONFIG_USER_MAX]; + struct list_head sched_list; + struct sk_buff_head sk_list; + struct sk_buff *last_retry_skb; + struct rwnx_hwq *hwq; + int nb_retry; + u8 push_limit; + u8 tid; +#ifdef CONFIG_MAC80211_TXQ + unsigned long nb_ready_mac80211; +#endif +#ifdef CONFIG_RWNX_FULLMAC + struct rwnx_sta *sta; + u8 ps_id; + u16 ndev_idx; + struct net_device *ndev; +#ifdef CONFIG_RWNX_AMSDUS_TX + struct rwnx_sw_txhdr *amsdu; + u16 amsdu_len; +#endif /* CONFIG_RWNX_AMSDUS_TX */ +#endif /* CONFIG_RWNX_FULLMAC */ +#ifdef CONFIG_RWNX_MUMIMO_TX + u8 mumimo_info; +#endif +}; + +struct rwnx_sta; +struct rwnx_vif; +struct rwnx_hw; +struct rwnx_sw_txhdr; + +#ifdef CONFIG_RWNX_MUMIMO_TX +#define RWNX_TXQ_GROUP_ID(txq) ((txq)->mumimo_info & 0x3f) +#define RWNX_TXQ_POS_ID(txq) (((txq)->mumimo_info >> 6) & 0x3) +#else +#define RWNX_TXQ_GROUP_ID(txq) 0 +#define RWNX_TXQ_POS_ID(txq) 0 +#endif /* CONFIG_RWNX_MUMIMO_TX */ + +static inline bool rwnx_txq_is_stopped(struct rwnx_txq *txq) +{ + return (txq->status & RWNX_TXQ_STOP); +} + +static inline bool rwnx_txq_is_full(struct rwnx_txq *txq) +{ + return (txq->status & RWNX_TXQ_STOP_FULL); +} + +static inline bool rwnx_txq_is_scheduled(struct rwnx_txq *txq) +{ + return (txq->status & RWNX_TXQ_IN_HWQ_LIST); +} + +/** + * foreach_sta_txq - Macro to iterate over all TXQ of a STA in increasing + * TID order + * + * @sta: pointer to rwnx_sta + * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration + * @tid: int updated with the TXQ tid at each iteration + * @rwnx_hw: main driver data + */ +#ifdef CONFIG_MAC80211_TXQ +#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ + for (tid = 0, txq = rwnx_txq_sta_get(sta, 0); \ + tid < NX_NB_TXQ_PER_STA; \ + tid++, txq = rwnx_txq_sta_get(sta, tid)) + +#elif defined(CONFIG_RWNX_FULLMAC) /* CONFIG_RWNX_FULLMAC */ +#define foreach_sta_txq(sta, txq, tid, rwnx_hw) \ + for (tid = 0, txq = rwnx_txq_sta_get(sta, 0, rwnx_hw); \ + tid < (is_multicast_sta(sta->sta_idx) ? 1 : NX_NB_TXQ_PER_STA); \ + tid++, txq++) + +#endif + +/** + * foreach_sta_txq_prio - Macro to iterate over all TXQ of a STA in + * decreasing priority order + * + * @sta: pointer to rwnx_sta + * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration + * @tid: int updated with the TXQ tid at each iteration + * @i: int updated with ieration count + * @rwnx_hw: main driver data + * + * Note: For fullmac txq for mgmt frame is skipped + */ +#ifdef CONFIG_RWNX_FULLMAC +#define foreach_sta_txq_prio(sta, txq, tid, i, rwnx_hw) \ + for (i = 0, tid = nx_tid_prio[0], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw); \ + i < NX_NB_TID_PER_STA; \ + i++, tid = nx_tid_prio[i], txq = rwnx_txq_sta_get(sta, tid, rwnx_hw)) +#endif + +/** + * foreach_vif_txq - Macro to iterate over all TXQ of a VIF (in AC order) + * + * @vif: pointer to rwnx_vif + * @txq: pointer to rwnx_txq updated with the next TXQ at each iteration + * @ac: int updated with the TXQ ac at each iteration + */ +#ifdef CONFIG_MAC80211_TXQ +#define foreach_vif_txq(vif, txq, ac) \ + for (ac = RWNX_HWQ_BK, txq = rwnx_txq_vif_get(vif, ac); \ + ac < NX_NB_TXQ_PER_VIF; \ + ac++, txq = rwnx_txq_vif_get(vif, ac)) + +#else +#define foreach_vif_txq(vif, txq, ac) \ + for (ac = RWNX_HWQ_BK, txq = &vif->txqs[0]; \ + ac < NX_NB_TXQ_PER_VIF; \ + ac++, txq++) +#endif + +#ifdef CONFIG_RWNX_FULLMAC +struct rwnx_txq *rwnx_txq_sta_get(struct rwnx_sta *sta, u8 tid, + struct rwnx_hw *rwnx_hw); +struct rwnx_txq *rwnx_txq_vif_get(struct rwnx_vif *vif, u8 type); +#endif /* CONFIG_RWNX_FULLMAC */ + +/** + * rwnx_txq_vif_get_status - return status bits related to the vif + * + * @rwnx_vif: Pointer to vif structure + */ +static inline u8 rwnx_txq_vif_get_status(struct rwnx_vif *rwnx_vif) +{ + struct rwnx_txq *txq = rwnx_txq_vif_get(rwnx_vif, 0); + return (txq->status & (RWNX_TXQ_STOP_CHAN | RWNX_TXQ_STOP_VIF_PS)); +} + +void rwnx_txq_vif_init(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif, + u8 status); +void rwnx_txq_vif_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_vif *vif); +void rwnx_txq_sta_init(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta, + u8 status); +void rwnx_txq_sta_deinit(struct rwnx_hw *rwnx_hw, struct rwnx_sta *rwnx_sta); +#ifdef CONFIG_RWNX_FULLMAC +void rwnx_txq_unk_vif_init(struct rwnx_vif *rwnx_vif); +void rwnx_txq_unk_vif_deinit(struct rwnx_vif *vif); +void rwnx_txq_offchan_init(struct rwnx_vif *rwnx_vif); +void rwnx_txq_offchan_deinit(struct rwnx_vif *rwnx_vif); +void rwnx_txq_tdls_vif_init(struct rwnx_vif *rwnx_vif); +void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *vif); +void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, + struct rwnx_hw *rwnx_hw); +void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, + struct rwnx_hw *rwnx_hw); +#endif + + +void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq); +void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq); +void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason); +void rwnx_txq_start(struct rwnx_txq *txq, u16 reason); +void rwnx_txq_vif_start(struct rwnx_vif *vif, u16 reason, + struct rwnx_hw *rwnx_hw); +void rwnx_txq_vif_stop(struct rwnx_vif *vif, u16 reason, + struct rwnx_hw *rwnx_hw); + +#ifdef CONFIG_RWNX_FULLMAC +void rwnx_txq_sta_start(struct rwnx_sta *sta, u16 reason, + struct rwnx_hw *rwnx_hw); +void rwnx_txq_sta_stop(struct rwnx_sta *sta, u16 reason, + struct rwnx_hw *rwnx_hw); +void rwnx_txq_offchan_start(struct rwnx_hw *rwnx_hw); +void rwnx_txq_sta_switch_vif(struct rwnx_sta *sta, struct rwnx_vif *old_vif, + struct rwnx_vif *new_vif); + +#endif /* CONFIG_RWNX_FULLMAC */ + +int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, + struct rwnx_hw *rwnx_hw, bool retry); +void rwnx_txq_confirm_any(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq, + struct rwnx_hwq *hwq, struct rwnx_sw_txhdr *sw_txhdr); + + +void rwnx_hwq_init(struct rwnx_hw *rwnx_hw); +void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq); +void rwnx_hwq_process_all(struct rwnx_hw *rwnx_hw); + +#endif /* _RWNX_TXQ_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_utils.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_utils.c new file mode 100644 index 000000000000..6b3c6f29bf10 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_utils.c @@ -0,0 +1,39 @@ +/** + * rwnx_utils.c + * + * IPC utility function definitions + * + * Copyright (C) RivieraWaves 2012-2019 + */ +#include "rwnx_utils.h" +#include "rwnx_defs.h" +#include "rwnx_rx.h" +#include "rwnx_tx.h" +#include "rwnx_msg_rx.h" +#include "rwnx_debugfs.h" +#include "rwnx_prof.h" +#include "ipc_host.h" + +extern int get_testmode(void); +extern void get_fw_path(char* fw_path); +extern int testmode; +extern char aic_fw_path[200]; + + +int rwnx_init_aic(struct rwnx_hw *rwnx_hw) +{ + RWNX_DBG(RWNX_FN_ENTRY_STR); +#ifdef AICWF_SDIO_SUPPORT + aicwf_sdio_host_init(&(rwnx_hw->sdio_env), NULL, NULL, rwnx_hw); +#else + aicwf_usb_host_init(&(rwnx_hw->usb_env), NULL, NULL, rwnx_hw); +#endif + rwnx_cmd_mgr_init(rwnx_hw->cmd_mgr); + + testmode = get_testmode(); + memset(aic_fw_path, 0, 200); + get_fw_path(aic_fw_path); + + return 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_utils.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_utils.h new file mode 100644 index 000000000000..f71a601c2af3 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_utils.h @@ -0,0 +1,133 @@ +/** + * rwnx_ipc_utils.h + * + * IPC utility function declarations + * + * Copyright (C) RivieraWaves 2012-2019 + */ +#ifndef _RWNX_IPC_UTILS_H_ +#define _RWNX_IPC_UTILS_H_ + +#include <linux/dma-mapping.h> +#include <linux/dmapool.h> +#include <linux/skbuff.h> +#include "aicwf_debug.h" + + +#include "lmac_msg.h" +#if 0 +#ifdef CONFIG_RWNX_DBG +/* #define RWNX_DBG(format, arg...) pr_warn(format, ## arg) */ +#define RWNX_DBG printk +#else +#define RWNX_DBG(a...) do {} while (0) +#endif + +#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__ +#endif +enum rwnx_dev_flag { + RWNX_DEV_RESTARTING, + RWNX_DEV_STACK_RESTARTING, + RWNX_DEV_STARTED, +}; + +struct rwnx_hw; +struct rwnx_sta; + +/** + * struct rwnx_ipc_elem - Generic IPC buffer of fixed size + * + * @addr: Host address of the buffer. + * @dma_addr: DMA address of the buffer. + */ +struct rwnx_ipc_elem { + void *addr; + dma_addr_t dma_addr; +}; + +/** + * struct rwnx_ipc_elem_pool - Generic pool of IPC buffers of fixed size + * + * @nb: Number of buffers currenlty allocated in the pool + * @buf: Array of buffers (size of array is @nb) + * @pool: DMA pool in which buffers have been allocated + */ +struct rwnx_ipc_elem_pool { + int nb; + struct rwnx_ipc_elem *buf; + struct dma_pool *pool; +}; + +/** + * struct rwnx_ipc_elem - Generic IPC buffer of variable size + * + * @addr: Host address of the buffer. + * @dma_addr: DMA address of the buffer. + * @size: Size, in bytes, of the buffer + */ +struct rwnx_ipc_elem_var { + void *addr; + dma_addr_t dma_addr; + size_t size; +}; + +/** + * struct rwnx_ipc_dbgdump_elem - IPC buffer for debug dump + * + * @mutex: Mutex to protect access to debug dump + * @buf: IPC buffer + */ +struct rwnx_ipc_dbgdump_elem { + struct mutex mutex; + struct rwnx_ipc_elem_var buf; +}; + +static const u32 rwnx_rxbuff_pattern = 0xCAFEFADE; + +/* + * Maximum Length of Radiotap header vendor specific data(in bytes) + */ +#define RADIOTAP_HDR_VEND_MAX_LEN 16 + +/* + * Maximum Radiotap Header Length without vendor specific data (in bytes) + */ +#define RADIOTAP_HDR_MAX_LEN 80 + +/* + * Unsupported HT Frame data length (in bytes) + */ +#define UNSUP_RX_VEC_DATA_LEN 2 + +/** + * struct rwnx_ipc_skb_elem - IPC buffer for SKB element + * + * @skb: Pointer to the skb buffer allocated + * @dma_addr: DMA address of the data buffer fo skb + * + */ +struct rwnx_ipc_skb_elem { + struct sk_buff *skb; + dma_addr_t dma_addr; +}; + +#ifdef CONFIG_RWNX_FULLMAC + +/* Maximum number of rx buffer the fw may use at the same time */ +#define RWNX_RXBUFF_MAX (64 * NX_REMOTE_STA_MAX) + +/** + * struct rwnx_ipc_rxbuf_elems - IPC buffers for RX + * + * @skb: Array of buffer push to FW. + * @idx: Index of the last pushed skb.(Use to find the next free entry quicker) + * + * Note: contrary to softmac version, dma_addr are stored inside skb->cb. + */ +struct rwnx_ipc_rxbuf_elems { + struct sk_buff *skb[RWNX_RXBUFF_MAX]; + int idx; +}; + +#endif /* CONFIG_RWNX_FULLMAC */ +#endif /* _RWNX_IPC_UTILS_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_v7.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_v7.c new file mode 100644 index 000000000000..72e3c850b48e --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_v7.c @@ -0,0 +1,195 @@ +/** + ****************************************************************************** + * + * @file rwnx_v7.c - Support for v7 platform + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#include "rwnx_v7.h" +#include "rwnx_defs.h" +#include "rwnx_irqs.h" +#include "reg_access.h" +#include "hal_desc.h" + +struct rwnx_v7 { + u8 *pci_bar0_vaddr; + u8 *pci_bar1_vaddr; +}; + +static int rwnx_v7_platform_enable(struct rwnx_hw *rwnx_hw) +{ + int ret; + + /* sched_setscheduler on ONESHOT threaded irq handler for BCNs ? */ + ret = request_irq(rwnx_hw->plat->pci_dev->irq, rwnx_irq_hdlr, 0, + "rwnx", rwnx_hw); + return ret; +} + +static int rwnx_v7_platform_disable(struct rwnx_hw *rwnx_hw) +{ + free_irq(rwnx_hw->plat->pci_dev->irq, rwnx_hw); + return 0; +} + +static void rwnx_v7_platform_deinit(struct rwnx_plat *rwnx_plat) +{ + #ifdef CONFIG_PCI + struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; + + pci_disable_device(rwnx_plat->pci_dev); + iounmap(rwnx_v7->pci_bar0_vaddr); + iounmap(rwnx_v7->pci_bar1_vaddr); + pci_release_regions(rwnx_plat->pci_dev); + pci_clear_master(rwnx_plat->pci_dev); + pci_disable_msi(rwnx_plat->pci_dev); + #endif + kfree(rwnx_plat); +} + +static u8 *rwnx_v7_get_address(struct rwnx_plat *rwnx_plat, int addr_name, + unsigned int offset) +{ + struct rwnx_v7 *rwnx_v7 = (struct rwnx_v7 *)rwnx_plat->priv; + + if (WARN(addr_name >= RWNX_ADDR_MAX, "Invalid address %d", addr_name)) + return NULL; + + if (addr_name == RWNX_ADDR_CPU) + return rwnx_v7->pci_bar0_vaddr + offset; + else + return rwnx_v7->pci_bar1_vaddr + offset; +} + +static void rwnx_v7_ack_irq(struct rwnx_plat *rwnx_plat) +{ + +} + +static const u32 rwnx_v7_config_reg[] = { + NXMAC_DEBUG_PORT_SEL_ADDR, + SYSCTRL_DIAG_CONF_ADDR, + SYSCTRL_PHYDIAG_CONF_ADDR, + SYSCTRL_RIUDIAG_CONF_ADDR, + RF_V7_DIAGPORT_CONF1_ADDR, +}; + +static const u32 rwnx_v7_he_config_reg[] = { + SYSCTRL_DIAG_CONF0, + SYSCTRL_DIAG_CONF1, + SYSCTRL_DIAG_CONF2, + SYSCTRL_DIAG_CONF3, +}; + +static int rwnx_v7_get_config_reg(struct rwnx_plat *rwnx_plat, const u32 **list) +{ + u32 fpga_sign; + + if (!list) + return 0; + + fpga_sign = RWNX_REG_READ(rwnx_plat, RWNX_ADDR_SYSTEM, SYSCTRL_SIGNATURE_ADDR); + if (__FPGA_TYPE(fpga_sign) == 0xc0ca) { + *list = rwnx_v7_he_config_reg; + return ARRAY_SIZE(rwnx_v7_he_config_reg); + } else { + *list = rwnx_v7_config_reg; + return ARRAY_SIZE(rwnx_v7_config_reg); + } +} + + +/** + * rwnx_v7_platform_init - Initialize the DINI platform + * + * @pci_dev PCI device + * @rwnx_plat Pointer on struct rwnx_stat * to be populated + * + * @return 0 on success, < 0 otherwise + * + * Allocate and initialize a rwnx_plat structure for the dini platform. + */ +int rwnx_v7_platform_init(struct pci_dev *pci_dev, struct rwnx_plat **rwnx_plat) +{ + struct rwnx_v7 *rwnx_v7; + u16 pci_cmd; + int ret = 0; + + *rwnx_plat = kzalloc(sizeof(struct rwnx_plat) + sizeof(struct rwnx_v7), + GFP_KERNEL); + if (!*rwnx_plat) + return -ENOMEM; + + rwnx_v7 = (struct rwnx_v7 *)(*rwnx_plat)->priv; + + /* Hotplug fixups */ + pci_read_config_word(pci_dev, PCI_COMMAND, &pci_cmd); + pci_cmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + pci_write_config_word(pci_dev, PCI_COMMAND, pci_cmd); + //pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES >> 2); + + ret = pci_enable_device(pci_dev); + if (ret) { + dev_err(&(pci_dev->dev), "pci_enable_device failed\n"); + goto out_enable; + } + + pci_set_master(pci_dev); + +#if 0 + ret = pci_request_regions(pci_dev, KBUILD_MODNAME); + if (ret) { + dev_err(&(pci_dev->dev), "pci_request_regions failed\n"); + goto out_request; + } +#endif + #ifdef CONFIG_PCI + if (pci_enable_msi(pci_dev)) { + dev_err(&(pci_dev->dev), "pci_enable_msi failed\n"); + goto out_msi; + + } + #endif + + rwnx_v7->pci_bar0_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 0); + if (!rwnx_v7->pci_bar0_vaddr) { + dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 0); + ret = -ENOMEM; + goto out_bar0; + } + rwnx_v7->pci_bar1_vaddr = (u8 *)pci_ioremap_bar(pci_dev, 1); + if (!rwnx_v7->pci_bar1_vaddr) { + dev_err(&(pci_dev->dev), "pci_ioremap_bar(%d) failed\n", 1); + ret = -ENOMEM; + goto out_bar1; + } + + (*rwnx_plat)->enable = rwnx_v7_platform_enable; + (*rwnx_plat)->disable = rwnx_v7_platform_disable; + (*rwnx_plat)->deinit = rwnx_v7_platform_deinit; + (*rwnx_plat)->get_address = rwnx_v7_get_address; + (*rwnx_plat)->ack_irq = rwnx_v7_ack_irq; + (*rwnx_plat)->get_config_reg = rwnx_v7_get_config_reg; + + return 0; + +out_bar1: + iounmap(rwnx_v7->pci_bar0_vaddr); +out_bar0: +#ifdef CONFIG_PCI + pci_disable_msi(pci_dev); +out_msi: +#endif + pci_release_regions(pci_dev); +//out_request: +#ifdef CONFIG_PCI + pci_clear_master(pci_dev); +#endif + pci_disable_device(pci_dev); +out_enable: + kfree(*rwnx_plat); + return ret; +} diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_v7.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_v7.h new file mode 100644 index 000000000000..c2e39765ae1c --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_v7.h @@ -0,0 +1,20 @@ +/** + ****************************************************************************** + * + * @file rwnx_v7.h + * + * Copyright (C) RivieraWaves 2012-2019 + * + ****************************************************************************** + */ + +#ifndef _RWNX_V7_H_ +#define _RWNX_V7_H_ + +#include <linux/pci.h> +#include "rwnx_platform.h" + +int rwnx_v7_platform_init(struct pci_dev *pci_dev, + struct rwnx_plat **rwnx_plat); + +#endif /* _RWNX_V7_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h new file mode 100644 index 000000000000..46ecb5de1ca5 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h @@ -0,0 +1,12 @@ +#ifndef _RWNX_VERSION_H_ +#define _RWNX_VERSION_H_ + +#include "rwnx_version_gen.h" + +static inline void rwnx_print_version(void) +{ + AICWFDBG(LOGINFO, RWNX_VERS_BANNER"\n"); + AICWFDBG(LOGINFO, "RELEASE_DATE:%s \r\n", RELEASE_DATE); +} + +#endif /* _RWNX_VERSION_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h new file mode 100644 index 000000000000..e2d038e8802e --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h @@ -0,0 +1,4 @@ +#define RWNX_VERS_REV "241c091M (master)" +#define RWNX_VERS_MOD "6.4.3.0" +#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)" +#define RELEASE_DATE "2023_1212_15dcf017" diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.c new file mode 100644 index 000000000000..69bcf3f5d784 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.c @@ -0,0 +1,86 @@ +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/platform_device.h> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +#include <linux/pm_wakeirq.h> +#else +#include <linux/pm_wakeup.h> +#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 --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.h new file mode 100644 index 000000000000..9c9655a46be2 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.h @@ -0,0 +1,21 @@ +#ifndef __RWNX_WAKELOCK_H +#define __RWNX_WAKELOCK_H + +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/platform_device.h> + +struct wakeup_source *rwnx_wakeup_init(const char *name); +void rwnx_wakeup_deinit(struct wakeup_source *ws); + +struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name); +void rwnx_wakeup_unregister(struct wakeup_source *ws); + +void rwnx_wakeup_lock(struct wakeup_source *ws); +void rwnx_wakeup_unlock(struct wakeup_source *ws); +void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec); + +void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw); +void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw); + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/sdio_host.c b/drivers/net/wireless/aic8800/aic8800_fdrv/sdio_host.c new file mode 100644 index 000000000000..f59409946e39 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/sdio_host.c @@ -0,0 +1,137 @@ +/** + * sdio_host.c + * + * SDIO host function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + + +#include "sdio_host.h" +//#include "ipc_compat.h" +#include "rwnx_tx.h" +#include "rwnx_platform.h" +#include "aicwf_debug.h" + +/** + **************************************************************************************** + */ +void aicwf_sdio_host_init(struct sdio_host_env_tag *env, + void *cb, + void *shared_env_ptr, + void *pthis) +{ + // Reset the environments + + // Reset the Host environment + memset(env, 0, sizeof(struct sdio_host_env_tag)); + // Save the pointer to the register base + env->pthis = pthis; +} + +/** + **************************************************************************************** + */ +volatile struct txdesc_host *aicwf_sdio_host_txdesc_get(struct sdio_host_env_tag *env, const int queue_idx) +{ + // struct ipc_shared_env_tag *shared_env_ptr = env->shared; + volatile struct txdesc_host *txdesc_free = NULL; + uint32_t used_idx = env->txdesc_used_idx[queue_idx]; + uint32_t free_idx = env->txdesc_free_idx[queue_idx]; + + // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); + // ASSERT_ERR((free_idx - used_idx) <= SDIO_TXDESC_CNT); + + // Check if a free descriptor is available + if (free_idx != (used_idx + SDIO_TXDESC_CNT)) { + // Get the pointer to the first free descriptor + // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); + } else { + txdesc_free = NULL; + } + + return txdesc_free; +} + +/** + **************************************************************************************** + */ +void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id) +{ + //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); + // Save the host id in the environment + env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % SDIO_TXDESC_CNT] = host_id; + + // Increment the index + env->txdesc_free_idx[queue_idx]++; + if (env->txdesc_free_idx[queue_idx] == 0x80000000) + env->txdesc_free_idx[queue_idx] = 0; +} + +/** + **************************************************************************************** + */ +void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data) +{ + u32 queue_idx = 0;// data[0]; + //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; + struct sk_buff *skb = NULL; + struct rwnx_txhdr *txhdr; + + // TX confirmation descriptors have been received + // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); + //while (1) + { + // Get the used index and increase it. We do the increase before knowing if the + // current buffer is confirmed because the callback function may call the + // ipc_host_txdesc_get() in case flow control was enabled and the index has to be + // already at the good value to ensure that the test of FIFO full is correct + //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; + uint32_t used_idx = data[1]; + unsigned long host_id = env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT]; + + // Reset the host id in the array + env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = 0; + + // call the external function to indicate that a TX packet is freed + if (host_id == 0) { + // No more confirmations, so put back the used index at its initial value + env->txdesc_used_idx[queue_idx] = used_idx; + AICWFDBG(LOGERROR, "ERROR:No more confirmations\r\n"); + //break; + } + // set the cfm status + skb = (struct sk_buff *)host_id; + txhdr = (struct rwnx_txhdr *)skb->data; + txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; + AICWFDBG(LOGINFO, "sdio_host_tx_cfm_handler:used_idx=%d, 0x%p, status=%x\r\n", used_idx, env->pthis, txhdr->hw_hdr.cfm.status.value); + //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) + if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { + // No more confirmations, so put back the used index at its initial value + env->txdesc_used_idx[queue_idx] = used_idx; + env->tx_host_id[queue_idx][used_idx % SDIO_TXDESC_CNT] = host_id; + // and exit the loop + AICWFDBG(LOGERROR, "ERROR:rwnx_txdatacfm,\r\n"); + // break; + } + } +} + +int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev) +{ + struct rwnx_plat *rwnx_plat = NULL; + void *drvdata; + int ret = -ENODEV; + + rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); + + if (!rwnx_plat) { + return -ENOMEM; + } + + rwnx_plat->sdiodev = sdiodev; + ret = rwnx_platform_init(rwnx_plat, &drvdata); + + return ret; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/sdio_host.h b/drivers/net/wireless/aic8800/aic8800_fdrv/sdio_host.h new file mode 100644 index 000000000000..670e9e08663d --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/sdio_host.h @@ -0,0 +1,41 @@ +/** + * sdio_host.h + * + * SDIO host function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + + +#ifndef _SDIO_HOST_H_ +#define _SDIO_HOST_H_ + +#include "lmac_types.h" +#include "aicwf_sdio.h" + +#define SDIO_TXQUEUE_CNT NX_TXQ_CNT +#define SDIO_TXDESC_CNT NX_TXDESC_CNT + + +/// Definition of the IPC Host environment structure. +struct sdio_host_env_tag { + // Index used that points to the first free TX desc + uint32_t txdesc_free_idx[SDIO_TXQUEUE_CNT]; + // Index used that points to the first used TX desc + uint32_t txdesc_used_idx[SDIO_TXQUEUE_CNT]; + // Array storing the currently pushed host ids, per IPC queue + uint64_t tx_host_id[SDIO_TXQUEUE_CNT][SDIO_TXDESC_CNT]; + + /// Pointer to the attached object (used in callbacks and register accesses) + void *pthis; +}; + +extern void aicwf_sdio_host_init(struct sdio_host_env_tag *env, + void *cb, void *shared_env_ptr, void *pthis); + +extern void aicwf_sdio_host_txdesc_push(struct sdio_host_env_tag *env, const int queue_idx, const uint64_t host_id); + +extern void aicwf_sdio_host_tx_cfm_handler(struct sdio_host_env_tag *env, u32 *data); +extern int aicwf_rwnx_sdio_platform_init(struct aic_sdio_dev *sdiodev); + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/usb_host.c b/drivers/net/wireless/aic8800/aic8800_fdrv/usb_host.c new file mode 100644 index 000000000000..c5c86d0de27b --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/usb_host.c @@ -0,0 +1,146 @@ +/** + * usb_host.c + * + * USB host function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + + +#include "usb_host.h" +//#include "ipc_compat.h" +#include "rwnx_tx.h" +#include "rwnx_platform.h" + +/** + **************************************************************************************** + */ +void aicwf_usb_host_init(struct usb_host_env_tag *env, + void *cb, + void *shared_env_ptr, + void *pthis) +{ + // Reset the environments + + // Reset the Host environment + memset(env, 0, sizeof(struct usb_host_env_tag)); + //printk("[Gaofx]rwnx_init_aic pthis %p !\n", pthis); + // Save the pointer to the register base + env->pthis = pthis; +} + +/** + **************************************************************************************** + */ +volatile struct txdesc_host *aicwf_usb_host_txdesc_get(struct usb_host_env_tag *env, const int queue_idx) +{ + // struct ipc_shared_env_tag *shared_env_ptr = env->shared; + volatile struct txdesc_host *txdesc_free = NULL; + uint32_t used_idx = env->txdesc_used_idx[queue_idx]; + uint32_t free_idx = env->txdesc_free_idx[queue_idx]; + + // ASSERT_ERR(queue_idx < SDIO_TXQUEUE_CNT); + // ASSERT_ERR((free_idx - used_idx) <= USB_TXDESC_CNT); + + // Check if a free descriptor is available + if (free_idx != (used_idx + USB_TXDESC_CNT)) { + // Get the pointer to the first free descriptor + // txdesc_free = shared_env_ptr->txdesc[queue_idx] + (free_idx % IPC_TXDESC_CNT); + } else { + txdesc_free = NULL; + } + + return txdesc_free; +} + +/** + **************************************************************************************** + */ +void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id) +{ + //printk("push, %d, %d, 0x%llx \r\n", queue_idx, env->txdesc_free_idx[queue_idx], host_id); + // Save the host id in the environment + env->tx_host_id[queue_idx][env->txdesc_free_idx[queue_idx] % USB_TXDESC_CNT] = host_id; + + // Increment the index + env->txdesc_free_idx[queue_idx]++; + if (env->txdesc_free_idx[queue_idx] == 0x80000000) + env->txdesc_free_idx[queue_idx] = 0; +} + +/** + **************************************************************************************** + */ +void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data) +{ + u32 queue_idx = 0;//data[0]; + //struct rwnx_hw *rwnx_hw = (struct rwnx_hw *)env->pthis; + struct sk_buff *skb = NULL; + struct rwnx_txhdr *txhdr; + printk("%s enter \n", __func__); + //printk("sdio_host_tx_cfm_handler, %d, 0x%08x\r\n", queue_idx, data[1]); + // TX confirmation descriptors have been received + // REG_SW_SET_PROFILING(env->pthis, SW_PROF_IRQ_E2A_TXCFM); + //while (1) + { + // Get the used index and increase it. We do the increase before knowing if the + // current buffer is confirmed because the callback function may call the + // ipc_host_txdesc_get() in case flow control was enabled and the index has to be + // already at the good value to ensure that the test of FIFO full is correct + //uint32_t used_idx = env->txdesc_used_idx[queue_idx]++; + uint32_t used_idx = data[1]; + uint64_t host_id = env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT]; + + // Reset the host id in the array + env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = 0; + + // call the external function to indicate that a TX packet is freed + if (host_id == 0) { + // No more confirmations, so put back the used index at its initial value + env->txdesc_used_idx[queue_idx] = used_idx; + printk("ERROR:No more confirmations\r\n"); + return; + //break; + } + // set the cfm status + skb = (struct sk_buff *)(uint64_t)host_id; + txhdr = (struct rwnx_txhdr *)skb->data; + txhdr->hw_hdr.cfm.status = (union rwnx_hw_txstatus)data[0]; + //txhdr->hw_hdr.status = data[1]; + //printk("sdio_host_tx_cfm_handler, 0x%p\r\n", env->pthis); + //if (env->cb.send_data_cfm(env->pthis, host_id) != 0) + if (rwnx_txdatacfm(env->pthis, (void *)host_id) != 0) { + // No more confirmations, so put back the used index at its initial value + env->txdesc_used_idx[queue_idx] = used_idx; + env->tx_host_id[queue_idx][used_idx % USB_TXDESC_CNT] = host_id; + // and exit the loop + printk("ERROR:rwnx_txdatacfm,\r\n"); + // break; + } + } +} + +int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev) +{ + struct rwnx_plat *rwnx_plat = NULL; + void *drvdata; + int ret = -ENODEV; + + rwnx_plat = kzalloc(sizeof(struct rwnx_plat), GFP_KERNEL); + + if (!rwnx_plat) + return -ENOMEM; + +// rwnx_plat->pci_dev = pci_dev; + rwnx_plat->usbdev = usbdev; + + ret = rwnx_platform_init(rwnx_plat, &drvdata); +#if 0 + pci_set_drvdata(pci_dev, drvdata); + + if (ret) + rwnx_plat->deinit(rwnx_plat); +#endif + return ret; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/usb_host.h b/drivers/net/wireless/aic8800/aic8800_fdrv/usb_host.h new file mode 100644 index 000000000000..012b90c9770a --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/usb_host.h @@ -0,0 +1,41 @@ +/** + * usb_host.h + * + * USB host function declarations + * + * Copyright (C) AICSemi 2018-2020 + */ + + +#ifndef _USB_HOST_H_ +#define _USB_HOST_H_ + +#include "lmac_types.h" +#include "aicwf_usb.h" + +#define USB_TXQUEUE_CNT NX_TXQ_CNT +#define USB_TXDESC_CNT NX_TXDESC_CNT + + +/// Definition of the IPC Host environment structure. +struct usb_host_env_tag { + // Index used that points to the first free TX desc + uint32_t txdesc_free_idx[USB_TXQUEUE_CNT]; + // Index used that points to the first used TX desc + uint32_t txdesc_used_idx[USB_TXQUEUE_CNT]; + // Array storing the currently pushed host ids, per IPC queue + uint64_t tx_host_id[USB_TXQUEUE_CNT][USB_TXDESC_CNT]; + + /// Pointer to the attached object (used in callbacks and register accesses) + void *pthis; +}; + +extern void aicwf_usb_host_init(struct usb_host_env_tag *env, + void *cb, void *shared_env_ptr, void *pthis); + +extern void aicwf_usb_host_txdesc_push(struct usb_host_env_tag *env, const int queue_idx, const uint64_t host_id); + +extern void aicwf_usb_host_tx_cfm_handler(struct usb_host_env_tag *env, u32 *data); +extern int aicwf_rwnx_usb_platform_init(struct aic_usb_dev *usbdev); + +#endif |