From df36cb419bd92a285d8cf885ef8715ede29a418e Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sun, 2 Jun 2024 21:22:03 +0800 Subject: [PATCH 01/12] [driver] add basic mmc_v2 sdhci driver --- board/avaota-a1/board.c | 46 +- cmake/board/avaota-a1.cmake | 2 + include/drivers/mmc/sys-mmc.h | 310 +++++++++ include/drivers/mmc/sys-sdcard.h | 39 ++ include/drivers/mmc/sys-sdhci.h | 160 +++++ include/drivers/sys-sdcard.h | 6 + include/drivers/sys-sdhci.h | 16 +- src/drivers/CMakeLists.txt | 16 +- src/drivers/mmc/sys-mmc.c | 0 src/drivers/mmc/sys-sdcard.c | 22 + src/drivers/mmc/sys-sdhci.c | 1016 ++++++++++++++++++++++++++++++ src/drivers/sys-sdhci.c | 2 +- 12 files changed, 1586 insertions(+), 49 deletions(-) create mode 100644 include/drivers/mmc/sys-mmc.h create mode 100644 include/drivers/mmc/sys-sdcard.h create mode 100644 include/drivers/mmc/sys-sdhci.h create mode 100644 src/drivers/mmc/sys-mmc.c create mode 100644 src/drivers/mmc/sys-sdcard.c create mode 100644 src/drivers/mmc/sys-sdhci.c diff --git a/board/avaota-a1/board.c b/board/avaota-a1/board.c index c2d72d58..ed186501 100644 --- a/board/avaota-a1/board.c +++ b/board/avaota-a1/board.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -51,49 +51,7 @@ sunxi_spi_t sunxi_spi0 = { }; sdhci_t sdhci0 = { - .name = "sdhci0", - .id = 0, - .reg = (sdhci_reg_t *) SUNXI_SMHC0_BASE, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_100M, - .sdio_type = SDHCI_TYPE_SD, - .removable = 0, - .isspi = FALSE, - .skew_auto_mode = TRUE, - .sdhci_pll = CCU_MMC_CTRL_PLL6X2, - .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, - .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, - .gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2}, - .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, - .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, - .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, -}; - -sdhci_t sdhci2 = { - .name = "sdhci2", - .id = 2, - .reg = (sdhci_reg_t *) SUNXI_SMHC2_BASE, - .voltage = MMC_VDD_27_36, - .width = MMC_BUS_WIDTH_4, - .clock = MMC_CLK_50M, - .sdio_type = SDHCI_TYPE_MMC, - .removable = 0, - .isspi = FALSE, - .skew_auto_mode = TRUE, - .sdhci_pll = CCU_MMC_CTRL_PLL6X2, - .gpio_clk = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX3}, - .gpio_cmd = {GPIO_PIN(GPIO_PORTC, 6), GPIO_PERIPH_MUX3}, - .gpio_d0 = {GPIO_PIN(GPIO_PORTC, 10), GPIO_PERIPH_MUX3}, - .gpio_d1 = {GPIO_PIN(GPIO_PORTC, 13), GPIO_PERIPH_MUX3}, - .gpio_d2 = {GPIO_PIN(GPIO_PORTC, 15), GPIO_PERIPH_MUX3}, - .gpio_d3 = {GPIO_PIN(GPIO_PORTC, 8), GPIO_PERIPH_MUX3}, - .gpio_d4 = {GPIO_PIN(GPIO_PORTC, 9), GPIO_PERIPH_MUX3}, - .gpio_d5 = {GPIO_PIN(GPIO_PORTC, 11), GPIO_PERIPH_MUX3}, - .gpio_d6 = {GPIO_PIN(GPIO_PORTC, 14), GPIO_PERIPH_MUX3}, - .gpio_d7 = {GPIO_PIN(GPIO_PORTC, 16), GPIO_PERIPH_MUX3}, - .gpio_ds = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX3}, - .gpio_rst = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX3}, + }; sunxi_i2c_t i2c_pmu = { diff --git a/cmake/board/avaota-a1.cmake b/cmake/board/avaota-a1.cmake index 1b2c3f47..06b0ac35 100644 --- a/cmake/board/avaota-a1.cmake +++ b/cmake/board/avaota-a1.cmake @@ -5,12 +5,14 @@ set(CONFIG_ARCH_ARM32_ARM64 True) set(CONFIG_CHIP_SUN55IW3 True) set(CONFIG_CHIP_WITHPMU True) set(CONFIG_CHIP_DCACHE True) +set(CONFIG_CHIP_MMC_V2 True) set(CONFIG_BOARD_AVAOTA-A1 True) set(CONIFG_SPECIAL_LD_PATH "${CMAKE_SOURCE_DIR}/board/avaota-a1/") add_definitions(-DCONFIG_CHIP_SUN55IW3) add_definitions(-DCONFIG_CHIP_DCACHE) +add_definitions(-DCONFIG_CHIP_MMC_V2) add_definitions(-DCONFIG_FATFS_CACHE_SIZE=0x2000000) add_definitions(-DCONFIG_FATFS_CACHE_ADDR=0x60000000) diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h new file mode 100644 index 00000000..84d57165 --- /dev/null +++ b/include/drivers/mmc/sys-mmc.h @@ -0,0 +1,310 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* MMC driver for General mmc operations + * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ + */ + +#ifndef _SYS_MMC_H_ +#define _SYS_MMC_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif// __cplusplus + +enum { + SD_VERSION_SD = 0x20000, + SD_VERSION_3 = (SD_VERSION_SD | 0x300), + SD_VERSION_2 = (SD_VERSION_SD | 0x200), + SD_VERSION_1_0 = (SD_VERSION_SD | 0x100), + SD_VERSION_1_10 = (SD_VERSION_SD | 0x10a), + + MMC_VERSION_MMC = 0x10000, + MMC_VERSION_UNKNOWN = (MMC_VERSION_MMC), + MMC_VERSION_1_2 = (MMC_VERSION_MMC | 0x102), + MMC_VERSION_1_4 = (MMC_VERSION_MMC | 0x104), + MMC_VERSION_2_2 = (MMC_VERSION_MMC | 0x202), + MMC_VERSION_3 = (MMC_VERSION_MMC | 0x300), + MMC_VERSION_4 = (MMC_VERSION_MMC | 0x400), + MMC_VERSION_4_1 = (MMC_VERSION_MMC | 0x401), + MMC_VERSION_4_2 = (MMC_VERSION_MMC | 0x402), + MMC_VERSION_4_3 = (MMC_VERSION_MMC | 0x403), + MMC_VERSION_4_41 = (MMC_VERSION_MMC | 0x429), + MMC_VERSION_4_5 = (MMC_VERSION_MMC | 0x405), + MMC_VERSION_5_0 = (MMC_VERSION_MMC | 0x500), + MMC_VERSION_5_1 = (MMC_VERSION_MMC | 0x501), +}; + +#define MMC_MODE_HS (1 << 0) /* can run at 26MHz -- DS26_SDR12 */ +#define MMC_MODE_HS_52MHz (1 << 1) /* can run at 52MHz with SDR mode -- HSSDR52_SDR25 */ +#define MMC_MODE_4BIT (1 << 2) +#define MMC_MODE_8BIT (1 << 3) +#define MMC_MODE_SPI (1 << 4) +#define MMC_MODE_HC (1 << 5) +#define MMC_MODE_DDR_52MHz (1 << 6) /* can run at 52Mhz with DDR mode -- HSDDR52_DDR50 */ +#define MMC_MODE_HS200 (1 << 7) /* can run at 200/208MHz with SDR mode -- HS200_SDR104 */ +#define MMC_MODE_HS400 (1 << 8) /* can run at 200MHz with DDR mode -- HS400 */ + +#define SD_DATA_4BIT 0x00040000 + +#define IS_SD(x) (x->version & SD_VERSION_SD) + +#define MMC_DATA_READ (1U << 0) +#define MMC_DATA_WRITE (1U << 1) + +#define MMC_CMD_MANUAL 1//add by sunxi.not sent stop when read/write multi block,and sent stop when sent cmd12 + +#define NO_CARD_ERR -16 /* No SD/MMC card inserted */ +#define UNUSABLE_ERR -17 /* Unusable Card */ +#define COMM_ERR -18 /* Communications Error */ +#define TIMEOUT -19 + +#define MMC_CMD_CMDVAL_MASK 0x80000000 + +#define MMC_CMD_GO_IDLE_STATE 0 +#define MMC_CMD_SEND_OP_COND 1 +#define MMC_CMD_ALL_SEND_CID 2 +#define MMC_CMD_SET_RELATIVE_ADDR 3 +#define MMC_CMD_SET_DSR 4 +#define MMC_CMD_SWITCH 6 +#define MMC_CMD_SELECT_CARD 7 +#define MMC_CMD_SEND_EXT_CSD 8 +#define MMC_CMD_SEND_CSD 9 +#define MMC_CMD_SEND_CID 10 +#define MMC_CMD_STOP_TRANSMISSION 12 +#define MMC_CMD_SEND_STATUS 13 +#define MMC_CMD_SET_BLOCKLEN 16 +#define MMC_CMD_READ_SINGLE_BLOCK 17 +#define MMC_CMD_READ_MULTIPLE_BLOCK 18 +#define MMC_CMD_WRITE_SINGLE_BLOCK 24 +#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25 +#define MMC_CMD_ERASE_GROUP_START 35 +#define MMC_CMD_ERASE_GROUP_END 36 +#define MMC_CMD_ERASE 38 +#define MMC_CMD_APP_CMD 55 +#define MMC_CMD_SPI_READ_OCR 58 +#define MMC_CMD_SPI_CRC_ON_OFF 59 + +#define SD_CMD_SEND_RELATIVE_ADDR 3 +#define SD_CMD_SWITCH_FUNC 6 +#define SD_CMD_SEND_IF_COND 8 + +#define SD_CMD_APP_SET_BUS_WIDTH 6 +#define SD_CMD_ERASE_WR_BLK_START 32 +#define SD_CMD_ERASE_WR_BLK_END 33 +#define SD_CMD_APP_SEND_OP_COND 41 +#define SD_CMD_APP_SEND_SCR 51 + +/* SCR definitions in different words */ +#define SD_HIGHSPEED_BUSY 0x00020000 +#define SD_HIGHSPEED_SUPPORTED 0x00020000 + +#define MMC_HS_TIMING 0x00000100 +#define MMC_HS_52MHZ 0x2 +#define MMC_DDR_52MHZ 0x4 + +#define OCR_BUSY 0x80000000 +#define OCR_HCS 0x40000000 +#define OCR_VOLTAGE_MASK 0x007FFF80 +#define OCR_ACCESS_MODE 0x60000000 + +#define SECURE_ERASE 0x80000000 + +#define MMC_STATUS_MASK (~0x0206BF7F) +#define MMC_STATUS_RDY_FOR_DATA (1 << 8) +#define MMC_STATUS_CURR_STATE (0xf << 9) +#define MMC_STATUS_ERROR (1 << 19) + +#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ +#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ +#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ +#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ +#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ +#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ +#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ +#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ +#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ +#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ +#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ +#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ +#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ +#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ +#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ +#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ +#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ + +#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ +#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in EXT_CSD byte addressed by index which are 1 in value field */ +#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in EXT_CSD byte addressed by index, which are 1 in value field */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target byte to value */ + +#define SD_SWITCH_CHECK 0 +#define SD_SWITCH_SWITCH 1 + +/* + * EXT_CSD fields + */ + +#define EXT_CSD_PART_CONF 179 /* R/W */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_CMD_SET_NORMAL (1 << 0) +#define EXT_CSD_CMD_SET_SECURE (1 << 1) +#define EXT_CSD_CMD_SET_CPSECURE (1 << 2) + +/* -- EXT_CSD[196] DEVICE_TYPE */ +#define EXT_CSD_CARD_TYPE_HS_26 (1 << 0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_HS_52 (1 << 1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | EXT_CSD_CARD_TYPE_HS_52) +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1 << 2) /* Card can run at 52MHz */ /* DDR mode @1.8V or 3V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1 << 3) /* Card can run at 52MHz */ /* DDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_DDR_1_2V) +#define EXT_CSD_CARD_TYPE_HS200_1_8V (1 << 4) /* Card can run at 200MHz */ +#define EXT_CSD_CARD_TYPE_HS200_1_2V (1 << 5) /* Card can run at 200MHz */ /* SDR mode @1.2V I/O */ +#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | EXT_CSD_CARD_TYPE_HS200_1_2V) +#define EXT_CSD_CARD_TYPE_HS400_1_8V (1 << 6) /* Card can run at 200MHz DDR, 1.8V */ +#define EXT_CSD_CARD_TYPE_HS400_1_2V (1 << 7) /* Card can run at 200MHz DDR, 1.2V */ +#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | EXT_CSD_CARD_TYPE_HS400_1_2V) + +/* -- EXT_CSD[183] BUS_WIDTH */ +#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ +#define EXT_CSD_BUS_DDR_4 5 /* Card is in 4 bit ddr mode */ +#define EXT_CSD_BUS_DDR_8 6 /* Card is in 8 bit ddr mode */ + +/* -- EXT_CSD[185] HS_TIMING */ +#define EXT_CSD_TIMING_BC 0 /* Backwards compatibility */ +#define EXT_CSD_TIMING_HS 1 /* High speed */ +#define EXT_CSD_TIMING_HS200 2 /* HS200 */ +#define EXT_CSD_TIMING_HS400 3 /* HS400 */ + +#define R1_ILLEGAL_COMMAND (1 << 22) +#define R1_APP_CMD (1 << 5) + +#define MMC_RSP_PRESENT (1 << 0) +#define MMC_RSP_136 (1 << 1) /* 136 bit response */ +#define MMC_RSP_CRC (1 << 2) /* expect valid crc */ +#define MMC_RSP_BUSY (1 << 3) /* card may send busy */ +#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */ + +#define MMC_RSP_NONE (0) +#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R1b (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | \ + MMC_RSP_BUSY) +#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC) +#define MMC_RSP_R3 (MMC_RSP_PRESENT) +#define MMC_RSP_R4 (MMC_RSP_PRESENT) +#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) + +#define MMCPART_NOAVAILABLE (0xff) +#define PART_ACCESS_MASK (0x7) +#define PART_SUPPORT (0x1) + +typedef enum { + MMC_DS26_SDR12 = 0, + MMC_HSSDR52_SDR25 = 1, + MMC_HSDDR52_DDR50 = 2, + MMC_HS200_SDR104 = 3, + MMC_HS400 = 4, + MMC_MAX_SPD_MD_NUM = 5, +} sdhci_speed_mode_t; + +typedef enum { + MMC_CLK_400K = 0, + MMC_CLK_25M = 1, + MMC_CLK_50M = 2, + MMC_CLK_100M = 3, + MMC_CLK_150M = 4, + MMC_CLK_200M = 5, + MMC_MAX_CLK_FREQ_NUM = 8, +} sdhci_freq_point_t; + +/* + * timing mode + * 1: output and input are both based on phase + * 3: output is based on phase, input is based on delay chain + * 4: output is based on phase, input is based on delay chain. + * it also support to use delay chain on data strobe signal. + */ +typedef enum { + MMC_TIMING_MODE_1 = 1, + MMC_TIMING_MODE_3 = 3, + MMC_TIMING_MODE_4 = 4, +} sdhci_timing_mode; + +#define SUNXI_MMC_1X_2X_MODE_CONTROL_REG (0x03000024) + +typedef struct tune_sdly { + uint32_t tm4_smx_fx[12]; +} tune_sdly_t; + +typedef struct mmc_cmd { + uint32_t cmdidx; + uint32_t resp_type; + uint32_t cmdarg; + uint32_t response[4]; + uint32_t flags; +} mmc_cmd_t; + +typedef struct mmc_data { + union { + char *dest; + const char *src; + } b; + uint32_t flags; + uint32_t blocks; + uint32_t blocksize; +} mmc_data_t; + +typedef struct mmc { + uint32_t voltages; + uint32_t version; + uint32_t has_init; + uint32_t f_min; + uint32_t f_max; + uint32_t f_max_ddr; + int high_capacity; + uint32_t clock; + uint32_t card_caps; + uint32_t host_caps; + uint32_t ocr; + uint32_t scr[2]; + uint32_t csd[4]; + uint32_t cid[4]; + uint32_t rca; + uint32_t part_config; + uint32_t part_num; + uint32_t tran_speed; + uint32_t read_bl_len; + uint32_t write_bl_len; + uint32_t erase_grp_size; + uint64_t capacity; + tune_sdly_t tune_sdly; + uint32_t b_max; + uint32_t lba; /* number of blocks */ + uint32_t blksz; /* block size */ + char revision[8 + 8]; /* CID: PRV */ + uint32_t speed_mode; +} mmc_t; + +#ifdef __cplusplus +} +#endif// __cplusplus + +#endif// _SYS_MMC_H_ \ No newline at end of file diff --git a/include/drivers/mmc/sys-sdcard.h b/include/drivers/mmc/sys-sdcard.h new file mode 100644 index 00000000..2dc4931e --- /dev/null +++ b/include/drivers/mmc/sys-sdcard.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* MMC driver for General mmc operations + * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ + */ + +#ifndef _SYS_SDCARD_H_ +#define _SYS_SDCARD_H_ + +#include +#include +#include +#include +#include +#include + +#include "sys-mmc.h" +#include "sys-sdhci.h" + +#ifdef __cplusplus +extern "C" { +#endif// __cplusplus + +typedef struct { + mmc_t card; + sdhci_t *hci; + uint8_t buf[512]; + bool online; +} sdmmc_pdata_t; + +/** + * External declaration of the 'card0' SDMMC platform data structure. + */ +extern sdmmc_pdata_t card0; + +#ifdef __cplusplus +} +#endif// __cplusplus + +#endif// _SYS_SDCARD_H_ \ No newline at end of file diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h new file mode 100644 index 00000000..7f92899b --- /dev/null +++ b/include/drivers/mmc/sys-sdhci.h @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* MMC driver for General mmc operations + * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ + */ + +#ifndef _SYS_SDHCI_H_ +#define _SYS_SDHCI_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "sys-mmc.h" + +#ifdef __cplusplus +extern "C" { +#endif// __cplusplus + +#define SMHC_DES_NUM_SHIFT 12 /* smhc2!! */ +#define SMHC_DES_BUFFER_MAX_LEN (1 << SMHC_DES_NUM_SHIFT) + +#define MMC_REG_FIFO_OS (0x200) + +#define SMHC_TIMEOUT 0xfffff +#define SMHC_DMA_TIMEOUT 0xffffff +#define SMHC_WAITBUSY_TIMEOUT 0x4ffffff +#define SMHC_DATA_TIMEOUT 0xffffff +#define SMHC_RESP_TIMEOUT 0xff + +enum { + MMC_CONTROLLER_0 = 0, + MMC_CONTROLLER_1 = 1, + MMC_CONTROLLER_2 = 2, +}; + +typedef enum { + MMC_TYPE_SD, + MMC_TYPE_EMMC, +} sunxi_sdhci_type_t; + +typedef struct sunxi_sdhci_desc { + uint32_t : 1, dic : 1, /* disable interrupt on completion */ + last_desc : 1, /* 1-this data buffer is the last buffer */ + first_desc : 1, /* 1-data buffer is the first buffer, 0-data buffer contained in the next descriptor is 1st buffer */ + des_chain : 1, /* 1-the 2nd address in the descriptor is the next descriptor address */ + end_of_ring : 1, /* 1-last descriptor flag when using dual data buffer in descriptor */ + : 24, /* Reserved */ + err_flag : 1, /* transfer error flag */ + own : 1; /* des owner:1-idma owns it, 0-host owns it */ + + uint32_t data_buf_sz : 16, data_buf_dummy : 16; + uint32_t buf_addr; + uint32_t next_desc_addr; +} sunxi_sdhci_desc_t __attribute__((aligned(8))); + +typedef struct sunxi_sdhci_host { + sdhci_reg_t *reg; + uint32_t mclk; + uint32_t hclkrst; + uint32_t hclkbase; + uint32_t mclkbase; + uint32_t database; + uint32_t commreg; + uint32_t fatal_err; + sunxi_sdhci_desc_t sdhci_desc[32]; + uint32_t timing_mode; + mmc_t *mmc; + uint32_t mod_clk; + uint32_t clock; +} sunxi_sdhci_host_t; + +typedef struct sunxi_sdhci_pinctrl { + gpio_mux_t gpio_d0; + gpio_mux_t gpio_d1; + gpio_mux_t gpio_d2; + gpio_mux_t gpio_d3; + gpio_mux_t gpio_d4; + gpio_mux_t gpio_d5; + gpio_mux_t gpio_d6; + gpio_mux_t gpio_d7; + gpio_mux_t gpio_cmd; + gpio_mux_t gpio_clk; + gpio_mux_t gpio_ds; + gpio_mux_t gpio_rst; +} sunxi_sdhci_pinctrl_t; + +typedef struct sunxi_sdhci_timing { + uint32_t odly; + uint32_t sdly; + uint32_t spd_md_id; + uint32_t freq_id; +} sunxi_sdhci_timing_t; + +typedef struct sdhci { + char *name; + uint32_t reg_base; + uint32_t id; + uint32_t width; + uint32_t clk_ctrl_base; + uint32_t clk_base; + uint32_t max_clk; + sunxi_sdhci_type_t type; + sunxi_sdhci_host_t *mmc_host; + sunxi_sdhci_pinctrl_t *pinctrl; + sunxi_sdhci_timing_t *timing_data; +} sdhci_t; + +/** + * @brief Initialize the SDHC controller. + * + * This function initializes the given SDHC controller. + * + * @param sdhci Pointer to the SDHC controller to initialize. + * @return Returns 0 on success, -1 on failure. + */ +int sunxi_sdhci_init(sdhci_t *sdhci); + +/** + * @brief Initialize the core functionality of the SDHC. + * + * This function initializes the core functionality of the given SDHC controller. + * + * @param sdhci Pointer to the SDHC controller to initialize. + */ +int sunxi_sdhci_core_init(sdhci_t *sdhci); + +/** + * @brief Set the I/O parameters of the SDHC controller. + * + * This function sets the I/O parameters of the given SDHC controller. + * + * @param sdhci Pointer to the SDHC controller to set I/O parameters for. + */ +void sunxi_sdhci_set_ios(sdhci_t *sdhci); + +/** + * @brief Perform data transfer operation for the SDHC controller. + * + * This function performs the data transfer operation for the given SDHC controller. + * + * @param sdhci Pointer to the SDHC controller to perform data transfer operation. + * @param cmd Pointer to the MMC command structure. + * @param data Pointer to the MMC data structure. + * @return Returns 0 on success, -1 on failure. + */ +int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data); + +#ifdef __cplusplus +} +#endif// __cplusplus + +#endif// _SYS_SDHCI_H_ \ No newline at end of file diff --git a/include/drivers/sys-sdcard.h b/include/drivers/sys-sdcard.h index 0beeb944..9db1c18b 100644 --- a/include/drivers/sys-sdcard.h +++ b/include/drivers/sys-sdcard.h @@ -3,6 +3,10 @@ #ifndef __SDCARD_H__ #define __SDCARD_H__ +#ifdef CONFIG_CHIP_MMC_V2 +#include +#else + #include #include #include @@ -227,4 +231,6 @@ uint64_t sdmmc_blk_read(sdmmc_pdata_t *data, uint8_t *buf, uint64_t blkno, uint6 } #endif // __cplusplus +#endif /* CONFIG_CHIP_MMC_V2 */ + #endif /* __SDCARD_H__ */ diff --git a/include/drivers/sys-sdhci.h b/include/drivers/sys-sdhci.h index 01a48ec0..6d23e269 100644 --- a/include/drivers/sys-sdhci.h +++ b/include/drivers/sys-sdhci.h @@ -3,6 +3,10 @@ #ifndef __SDHCI_H__ #define __SDHCI_H__ +#ifdef CONFIG_CHIP_MMC_V2 +#include +#else + #include #include #include @@ -15,6 +19,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif// __cplusplus + typedef enum { MMC_CLK_400K = 0, MMC_CLK_25M, @@ -51,8 +59,7 @@ typedef struct { : 25, err_flag : 1, /* transfer error flag */ own : 1; /* des owner:1-idma owns it, 0-host owns it */ - uint32_t data_buf_sz : SMHC_DES_NUM_SHIFT, - data_buf_dummy : (32 - SMHC_DES_NUM_SHIFT); + uint32_t data_buf_sz : SMHC_DES_NUM_SHIFT, data_buf_dummy : (32 - SMHC_DES_NUM_SHIFT); uint32_t buf_addr; uint32_t next_desc_addr; @@ -154,5 +161,10 @@ bool sdhci_transfer(sdhci_t *hci, sdhci_cmd_t *cmd, sdhci_data_t *dat); */ int sunxi_sdhci_init(sdhci_t *sdhci); +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* CONFIG_CHIP_MMC_V2 */ #endif /* __SDHCI_H__ */ diff --git a/src/drivers/CMakeLists.txt b/src/drivers/CMakeLists.txt index be2ede04..8ce2fcfc 100644 --- a/src/drivers/CMakeLists.txt +++ b/src/drivers/CMakeLists.txt @@ -48,6 +48,19 @@ if (CONFIG_CHIP_WITHPMU) ) endif() +if (CONFIG_CHIP_MMC_V2) + set(DRIVER_MMC + mmc/sys-mmc.c + mmc/sys-sdhci.c + mmc/sys-sdcard.c + ) +else() + set(DRIVER_MMC + sys-sdcard.c + sys-sdhci.c + ) +endif() + if (NOT CONFIG_CHIP_CLK_V1) set(COMMON_DRIVER ${COMMON_DRIVER} @@ -56,13 +69,12 @@ if (NOT CONFIG_CHIP_CLK_V1) sys-rtc.c sys-spi-nand.c sys-spi.c - sys-sdcard.c sys-dma.c sys-i2c.c - sys-sdhci.c ${USB_DRIVER} ${GIC_DRIVER} + ${DRIVER_MMC} ) endif() diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c new file mode 100644 index 00000000..e69de29b diff --git a/src/drivers/mmc/sys-sdcard.c b/src/drivers/mmc/sys-sdcard.c new file mode 100644 index 00000000..3a95dca9 --- /dev/null +++ b/src/drivers/mmc/sys-sdcard.c @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* MMC driver for General mmc operations + * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +sdmmc_pdata_t card0; \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c new file mode 100644 index 00000000..72d1c301 --- /dev/null +++ b/src/drivers/mmc/sys-sdhci.c @@ -0,0 +1,1016 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* MMC driver for General mmc operations + * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +static int sunxi_sdhci_clk_enable(sdhci_t *sdhci) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + uint32_t rval; + /* config ahb clock */ + rval = readl(mmc_host->hclkbase); + rval |= (1 << (sdhci->id)); + writel(rval, mmc_host->hclkbase); + + rval = readl(mmc_host->hclkrst); + rval |= (1 << (16 + sdhci->id)); + writel(rval, mmc_host->hclkrst); + + /* config mod clock */ + writel(0x80000000, mmc_host->mclkbase); + mmc_host->mod_clk = 24000000; + return 0; +} + +static int sunxi_sdhci_update_clk(sdhci_t *sdhci) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + uint32_t cmd = 0x0; + uint32_t timeout = time_us() + SMHC_TIMEOUT; + + mmc_host->reg->clkcr |= (0x1U << 31); + mmc_host->reg->cmd = (1U << 31) | (1 << 21) | (1 << 13); + + /* Wait for process done */ + while ((mmc_host->reg->cmd & MMC_CMD_CMDVAL_MASK) && (time_us() < timeout)) { + } + + /* Check status */ + if (mmc_host->reg->cmd & MMC_CMD_CMDVAL_MASK) { + printk_error("SMHC: mmc %d update clk failed\n", sdhci->id); + return -1; + } + + mmc_host->reg->clkcr &= (~(0x1U << 31)); + mmc_host->reg->rint = mmc_host->reg->rint; + return 0; +} + +static int sunxi_sdhci_update_phase(sdhci_t *sdhci) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { + printk_trace("SMHC: mmc update phase.\n"); + return sunxi_sdhci_update_clk(sdhci); + } + return 0; +} + +static int sunxi_sdhci_get_timing_config_timing_4(sdhci_t *sdhci) { + /* TODO: eMMC Timing set */ +} + +static int sunxi_sdhci_get_timing_config(sdhci_t *sdhci) { + int ret = 0; + + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + + if ((sdhci->id == 2) && mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { + /* When using eMMC and SMHC2, we config it as timging 4 */ + ret = sunxi_sdhci_get_timing_config_timing_4(sdhci); + } else if ((sdhci->id == 0) && (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1)) { + if ((timing_data->spd_md_id <= MMC_HSSDR52_SDR25) && (timing_data->freq_id <= MMC_CLK_50M)) { + /* if timing less then SDR25 using default odly */ + timing_data->odly = 0; + timing_data->sdly = 0; + ret = 0; + } else { + printk_warning("SMHC: SMHC0 do not support input spd mode %d\n", timing_data->spd_md_id); + ret = -1; + } + } else { + printk_error("SMHC: timing setting fail, param error\n"); + ret = -1; + } + return ret; +} + +static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { + uint32_t n, m, src; + uint32_t reg_val = 0x0; + + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + if (clk_hz <= 4000000) { + src = 0; /* SCLK = 24000000 OSC CLK */ + } else { + src = 2; /* SCLK = AHB PLL */ + } + + switch (clk_hz) { + case 400000: + n = 1; + m = 0xe; + break; + case 25000000: + case 26000000: + n = (sdhci->id == 2) ? 2 : 1; + m = (sdhci->id == 2) ? 3 : 2; + break; + case 50000000: + case 52000000: + n = (sdhci->id == 2) ? 1 : 0; + m = 2; + break; + case 200000000: + src = 1;// PERI0_800M + n = 0; + m = 1; + break; + default: + n = 0; + m = 0; + printk_error("SMHC: request freq not match freq=%d\n", clk_hz); + break; + } + + reg_val = (src << 24) | (n << 8) | m; + writel(reg_val, mmc_host->mclkbase); + + return 0; +} + +static uint32_t sunxi_sdhci_get_mclk(sdhci_t *sdhci) { + uint32_t n, m, src, clk_hz; + uint32_t reg_val = 0x0; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + reg_val = readl(mmc_host->mclkbase); + + m = reg_val & 0xf; + n = (reg_val >> 8) & 0x3; + src = (reg_val >> 24) & 0x3; + + switch (src) { + case 0: + clk_hz = 24000000; + break; + case 1: + case 3: + clk_hz = (sdhci->id == 2) ? 800000000 : 400000000; + break; + case 2: + case 4: + clk_hz = (sdhci->id == 2) ? 600000000 : 300000000; + break; + default: + printk_error("SMHC: wrong clock source %u\n", src); + break; + } + + return clk_hz / (n + 1) / (m + 1); +} + +static int sunxi_sdhci_config_delay(sdhci_t *sdhci) { + int ret = 0; + uint32_t reg_val = 0x0; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + + if (mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_1) { + timing_data->odly = 0; + timing_data->sdly = 0; + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_1, odly %d, sldy %d\n", timing_data->odly, timing_data->sdly); + + reg_val = mmc_host->reg->drv_dl; + reg_val &= (~(0x3 << 16)); + reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); + writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); + mmc_host->reg->drv_dl = reg_val; + writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); + + reg_val = mmc_host->reg->ntsr; + reg_val &= (~(0x3 << 4)); + reg_val |= ((timing_data->sdly & 0x3) << 4); + mmc_host->reg->ntsr = reg_val; + } else if (mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_3) { + timing_data->odly = 0; + timing_data->sdly = 0; + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_3, odly %d, sldy %d\n", timing_data->odly, timing_data->sdly); + + reg_val = mmc_host->reg->drv_dl; + reg_val &= (~(0x3 << 16)); + reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); + writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); + mmc_host->reg->drv_dl = reg_val; + writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); + + reg_val = mmc_host->reg->samp_dl; + reg_val &= (~SDXC_NTDC_CFG_DLY); + reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + mmc_host->reg->samp_dl = reg_val; + } else if (mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_4) { + uint32_t spd_md_orig = timing_data->spd_md_id; + + if (timing_data->spd_md_id == MMC_HS400) + timing_data->spd_md_id = MMC_HS200_SDR104; + + timing_data->odly = 0xff; + timing_data->sdly = 0xff; + + if ((ret = sunxi_sdhci_get_timing_config(sdhci)) != 0) { + printk_error("SMHC: getting timing param error %d\n", ret); + return -1; + } + + if ((timing_data->odly == 0xff) || (timing_data->sdly = 0xff)) { + printk_error("SMHC: getting timing config error\n"); + return -1; + } + + reg_val = mmc_host->reg->drv_dl; + reg_val &= (~(0x3 << 16)); + reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); + writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); + mmc_host->reg->drv_dl = reg_val; + writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); + + reg_val = mmc_host->reg->samp_dl; + reg_val &= (~SDXC_NTDC_CFG_DLY); + reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + mmc_host->reg->samp_dl = reg_val; + + /* Reset to orig md id */ + timing_data->spd_md_id = spd_md_orig; + if (timing_data->spd_md_id = MMC_HS400) { + timing_data->odly = 0xff; + timing_data->sdly = 0xff; + if ((ret = sunxi_sdhci_get_timing_config(sdhci)) != 0) { + printk_error("SMHC: getting timing param error %d\n", ret); + return -1; + } + + if ((timing_data->odly == 0xff) || (timing_data->sdly = 0xff)) { + printk_error("SMHC: getting timing config error\n"); + return -1; + } + + reg_val = mmc_host->reg->ds_dl; + reg_val &= (~SDXC_NTDC_CFG_DLY); + reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + mmc_host->reg->ds_dl = reg_val; + } + printk_trace("SMHC: config delay freq = %d, odly = %d," + "sdly = %d, spd_md_id = %d\n", + timing_data->freq_id, timing_data->odly, + timing_data->sdly, timing_data->spd_md_id); + } +} + +static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { + int ret = 0; + uint32_t reg_val = 0x0; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + mmc_t *mmc = mmc_host->mmc; + + /* disable mclk */ + writel(0x0, mmc_host->mclkbase); + if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { + mmc_host->reg->ntsr |= (1 << 31); + } else { + mmc_host->reg->ntsr = 0x0; + } + + if ((mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3)) { + /* If using DDR mod to 4 */ + if (mmc->speed_mode == MMC_HSDDR52_DDR50) { + mmc_host->mod_clk = clk * 4; + } else { + mmc_host->mod_clk = clk * 2; + } + } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { + /* If using DDR mod to 4 */ + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (sdhci->width == SMHC_WIDTH_8BIT)) { + mmc_host->mod_clk = clk * 4; + } else { + mmc_host->mod_clk = clk * 2; + } + } + + /* Now set mclk */ + sunxi_sdhci_set_mclk(sdhci, clk); + + /* Now set clock by mclk we get */ + if ((mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3)) { + if (mmc->speed_mode == MMC_HSDDR52_DDR50) { + mmc->clock = sunxi_sdhci_get_mclk(sdhci) / 4; + } else { + mmc->clock = sunxi_sdhci_get_mclk(sdhci) / 2; + } + } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { + /* If using DDR mod to 4 */ + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (sdhci->width == SMHC_WIDTH_8BIT)) { + mmc->clock = sunxi_sdhci_get_mclk(sdhci) / 4; + } else { + mmc->clock = sunxi_sdhci_get_mclk(sdhci) / 2; + } + } + /* Set host clock */ + mmc_host->clock = mmc->clock; + printk_trace("SMHC: get round clk %lu, mod_clk %lu", mmc->clock, mmc_host->mod_clk); + + /* enable mclk */ + writel(readl(mmc_host->mclkbase) | (1U << 31), mmc_host->mclkbase); + + /* Configure SMHC_CLKDIV to open clock for devices */ + reg_val = mmc_host->reg->clkcr; + reg_val &= ~(0xff); + if ((mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3)) { + if (mmc->speed_mode == MMC_HSDDR52_DDR50) { + reg_val |= 0x1; + } + } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { + /* If using DDR mod to 4 */ + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (sdhci->width == SMHC_WIDTH_8BIT)) { + reg_val |= 0x1; + } + } + mmc_host->reg->clkcr = reg_val; + + if (sunxi_sdhci_update_clk(sdhci)) { + return -1; + } + + /* config delay for mmc device */ + timing_data->freq_id = MMC_CLK_25M; + switch (clk) { + case 0 ... 400000: + timing_data->freq_id = MMC_CLK_400K; + break; + case 400001 ... 26000000: + timing_data->freq_id = MMC_CLK_25M; + break; + case 26000001 ... 52000000: + timing_data->freq_id = MMC_CLK_50M; + break; + case 52000001 ... 100000000: + timing_data->freq_id = MMC_CLK_100M; + break; + case 100000001 ... 150000000: + timing_data->freq_id = MMC_CLK_150M; + break; + case 150000001 ... 200000000: + timing_data->freq_id = MMC_CLK_200M; + break; + default: + timing_data->freq_id = MMC_CLK_25M; + break; + } + sunxi_sdhci_config_delay(sdhci); + + return 0; +} + +static int sunxi_sdhci_config_clock(sdhci_t *sdhci, uint32_t clk) { + uint32_t reg_val = 0x0; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + mmc_t *mmc = mmc_host->mmc; + + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) || (mmc->speed_mode == MMC_HS400)) { + if (clk > mmc->f_max_ddr) { + clk = mmc->f_max_ddr; + } + } + + /* disable clock */ + mmc_host->reg->clkcr &= ~(0x1 << 16); + + if (sunxi_sdhci_update_clk(sdhci)) { + return -1; + } + + if ((mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4)) { + sunxi_sdhci_clock_mode(sdhci, clk); + } else { + printk_error("SMHC: Timing mode not supported!\n"); + return -1; + } + + /* enable clock */ + mmc_host->reg->clkcr |= (0x1 << 16); + + if (sunxi_sdhci_update_clk(sdhci)) { + printk_error("SMHC: reconfigure clk failed\n"); + return -1; + } + + return 0; +} + +static void sunxi_sdhci_ddr_mode_set(sdhci_t *sdhci, bool status) { + uint32_t reg_val = 0x0; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + reg_val = mmc_host->reg->gctrl; + reg_val &= ~(0x1 << 10); + /* disable ccu clock */ + writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); + + if (status) { + reg_val |= (0x1 << 10); + } + + mmc_host->reg->gctrl = reg_val; + + /* enable ccu clock */ + writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); + + printk_trace("SMHC: set to %s ddr mode\n", status ? "enable" : "disable"); +} + +static void sunxi_sdhci_hs400_mode_set(sdhci_t *sdhci, bool status) { + uint32_t reg_dsbd_val = 0x0, reg_csdc_val = 0x0; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + if (sdhci->id != 2) { + return; + } + + reg_dsbd_val = mmc_host->reg->dsbd; + reg_dsbd_val &= ~(0x1 << 31); + + reg_csdc_val = mmc_host->reg->csdc; + reg_csdc_val &= ~0xf; + + if (status) { + reg_dsbd_val |= (0x1 << 31); + reg_csdc_val |= 0x6; + } else { + reg_csdc_val |= 0x3; + } + + mmc_host->reg->dsbd = reg_dsbd_val; + mmc_host->reg->csdc = reg_csdc_val; + + printk_trace("SMHC: set to %s HS400 mode\n", status ? "enable" : "disable"); +} + +static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { + sunxi_sdhci_pinctrl_t *sdhci_pins = sdhci->pinctrl; + + sunxi_gpio_init(sdhci_pins->gpio_clk.pin, sdhci_pins->gpio_clk.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_clk.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_cmd.pin, sdhci_pins->gpio_cmd.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_cmd.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_d0.pin, sdhci_pins->gpio_d0.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d0.pin, GPIO_PULL_UP); + + /* Init GPIO for 4bit MMC */ + if (sdhci->width > SMHC_WIDTH_1BIT) { + sunxi_gpio_init(sdhci_pins->gpio_d1.pin, sdhci_pins->gpio_d1.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d1.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_d2.pin, sdhci_pins->gpio_d2.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d2.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_d3.pin, sdhci_pins->gpio_d3.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d3.pin, GPIO_PULL_UP); + } + + /* Init GPIO for 8bit MMC */ + if (sdhci->width > SMHC_WIDTH_4BIT) { + sunxi_gpio_init(sdhci_pins->gpio_d4.pin, sdhci_pins->gpio_d4.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d4.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_d5.pin, sdhci_pins->gpio_d5.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d5.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_d6.pin, sdhci_pins->gpio_d6.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d6.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_d7.pin, sdhci_pins->gpio_d7.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_d7.pin, GPIO_PULL_UP); + + sunxi_gpio_init(sdhci_pins->gpio_ds.pin, sdhci_pins->gpio_ds.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_ds.pin, GPIO_PULL_DOWN); + + sunxi_gpio_init(sdhci_pins->gpio_rst.pin, sdhci_pins->gpio_rst.mux); + sunxi_gpio_set_pull(sdhci_pins->gpio_rst.pin, GPIO_PULL_UP); + } +} + +static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + uint32_t timeout = time_us() + SMHC_TIMEOUT; + uint32_t *buff; + + if (data->flags * MMC_DATA_READ) { + buff = (uint32_t *) data->b.dest; + for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { + while ((mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) && (time_us() < timeout)) { + } + if (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) { + if (time_us() >= timeout) { + printk_error("SMHC: tranfer read by cpu failed, timeout\n"); + return -1; + } + } + buff[i] = readl(mmc_host->database); + timeout = time_us() + SMHC_TIMEOUT; + } + } else { + buff = (uint32_t *) data->b.src; + for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { + while (((mmc_host->reg->status) & SMHC_STATUS_FIFO_FULL) && (time_us() < timeout)) { + } + if (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL) { + if (time_us() >= timeout) { + printk_error("SMHC: tranfer write by cpu failed, timeout\n"); + return -1; + } + } + writel(buff[i], mmc_host->database); + timeout = time_us() + SMHC_TIMEOUT; + } + } + return 0; +} + +static int sunxi_sdhci_trans_data_dma(sdhci_t *sdhci, mmc_data_t *data) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + sunxi_sdhci_desc_t *pdes = mmc_host->sdhci_desc; + uint8_t *buff; + uint32_t des_idx = 0, buff_frag_num = 0, remain = 0; + uint32_t reg_val = 0; + uint32_t timeout = time_us() + SMHC_TIMEOUT; + + buff = data->flags & MMC_DATA_READ ? (uint8_t *) data->b.dest : (uint8_t *) data->b.src; + buff_frag_num = (data->blocksize * data->blocks) >> SMHC_DES_NUM_SHIFT; + remain = (data->blocksize * data->blocks) & (SMHC_DES_BUFFER_MAX_LEN - 1); + if (remain) { + buff_frag_num++; + } else { + remain = SMHC_DES_BUFFER_MAX_LEN; + } + + for (size_t i = 0; i < buff_frag_num; i++, des_idx++) { + memset((void *) &pdes[des_idx], 0, sizeof(sunxi_sdhci_desc_t)); + pdes[des_idx].des_chain = 1; + pdes[des_idx].own = 1; + pdes[des_idx].dic = 1; + + if (buff_frag_num > 1 && i != buff_frag_num - 1) { + pdes[des_idx].data_buf_sz = SMHC_DES_BUFFER_MAX_LEN; + } else { + pdes[des_idx].data_buf_sz = remain; + } + + pdes[des_idx].buf_addr = ((size_t) buff + i * SMHC_DES_BUFFER_MAX_LEN) >> 2; + if (i == 0) { + pdes[des_idx].first_desc = 1; + } + + if (i == buff_frag_num - 1) { + pdes[des_idx].dic = 0; + pdes[des_idx].last_desc = 1; + pdes[des_idx].end_of_ring = 1; + pdes[des_idx].next_desc_addr = 0; + } else { + pdes[des_idx].next_desc_addr = ((size_t) &pdes[des_idx + 1]) >> 2; + } + printk_trace("SMHC: frag %d, remain %d, des[%d] = 0x%08x:" + " [0] = 0x%08x, [1] = 0x%08x, [2] = 0x%08x, [3] = 0x%08x\n", + i, remain, des_idx, (uint32_t) (&pdes[des_idx]), + (uint32_t) ((uint32_t *) &pdes[des_idx])[0], + (uint32_t) ((uint32_t *) &pdes[des_idx])[1], + (uint32_t) ((uint32_t *) &pdes[des_idx])[2], + (uint32_t) ((uint32_t *) &pdes[des_idx])[3]); + } + + dsb(); + isb(); + + /* + * GCTRLREG + * GCTRL[2] : DMA reset + * GCTRL[5] : DMA enable + * + * IDMACREG + * IDMAC[0] : IDMA soft reset + * IDMAC[1] : IDMA fix burst flag + * IDMAC[7] : IDMA on + * + * IDIECREG + * IDIE[0] : IDMA transmit interrupt flag + * IDIE[1] : IDMA receive interrupt flag + */ + + + /* Enable DMA */ + mmc_host->reg->gctrl |= (SMHC_GCTRL_DMA_ENABLE | SMHC_GCTRL_DMA_RESET); + + timeout = time_us() + SMHC_TIMEOUT; + while (mmc_host->reg->gctrl & SMHC_GCTRL_DMA_RESET) { + if (time_us() > timeout) { + printk_error("SMHC: wait for dma rst timeout\n"); + return -1; + } + } + + /* DMA Reset */ + mmc_host->reg->dmac = SMHC_IDMAC_SOFT_RESET; + timeout = time_us() + SMHC_TIMEOUT; + while (mmc_host->reg->dmac & SMHC_IDMAC_SOFT_RESET) { + if (time_us() > timeout) { + printk_error("SMHC: wait for dma soft rst timeout\n"); + return -1; + } + } + + /* DMA on */ + mmc_host->reg->dmac = (SMHC_IDMAC_FIX_BURST | SMHC_IDMAC_IDMA_ON); + + /* Set DMA INTERRUPT */ + mmc_host->reg->idie &= ~(SMHC_IDMAC_TRANSMIT_INTERRUPT | SMHC_IDMAC_RECEIVE_INTERRUPT); + if (data->flags & MMC_DATA_WRITE) { + mmc_host->reg->idie |= SMHC_IDMAC_TRANSMIT_INTERRUPT; + } else { + mmc_host->reg->idie |= SMHC_IDMAC_RECEIVE_INTERRUPT; + } + + mmc_host->reg->dlba = (uint32_t) pdes >> 2; + + /* burst-16, rx/tx trigger level=15/240 */ + mmc_host->reg->ftrglevel = ((0x3 << 28) | (15 << 16) | 240); + + return 0; +} + +void sunxi_sdhci_set_ios(sdhci_t *sdhci) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + mmc_t *mmc = mmc_host->mmc; + + if (mmc->clock && sunxi_sdhci_config_clock(sdhci, mmc->clock)) { + printk_error("SMHC: update clock failed\n"); + mmc_host->fatal_err = 1; + return; + } + + /* change bus width */ + switch (sdhci->width) { + case SMHC_WIDTH_8BIT: + mmc_host->reg->width = 2; + break; + case SMHC_WIDTH_4BIT: + mmc_host->reg->width = 1; + break; + default: + mmc_host->reg->width = 0; + break; + } + + /* Set DDR mode */ + if (mmc->speed_mode == MMC_HSDDR52_DDR50) { + sunxi_sdhci_ddr_mode_set(sdhci, true); + sunxi_sdhci_hs400_mode_set(sdhci, false); + + } else if (mmc->speed_mode == MMC_HS400) { + sunxi_sdhci_ddr_mode_set(sdhci, false); + sunxi_sdhci_hs400_mode_set(sdhci, true); + } else { + sunxi_sdhci_ddr_mode_set(sdhci, false); + sunxi_sdhci_hs400_mode_set(sdhci, false); + } +} + +int sunxi_sdhci_core_init(sdhci_t *sdhci) { + uint32_t reg_val = 0x0; + uint32_t timeout = time_us() + SMHC_TIMEOUT; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + mmc_t *mmc = mmc_host->mmc; + + /* Reset controller */ + mmc_host->reg->gctrl = 0x7; + while (mmc_host->reg->gctrl & 0x7) { + if (time_us() > timeout) { + printk_error("SMHC: controller reset timeout\n"); + return -1; + } + } + + /* Set Data & Response Timeout Value */ + mmc_host->reg->timeout = (SMHC_DATA_TIMEOUT << 8) | SMHC_RESP_TIMEOUT; + + mmc_host->reg->thldc = ((512 << 16) | (0x1 << 2) | (0x1 << 0)); + mmc_host->reg->csdc = 0x3; + mmc_host->reg->dbgc = 0xdeb; + + /* Release emmc RST */ + mmc_host->reg->hwrst = 1; + mmc_host->reg->hwrst = 0; + mdelay(1); + mmc_host->reg->hwrst = 1; + mdelay(1); + + if (sdhci->id == 0) { + /* enable 2xclk mode, and use default input phase */ + mmc_host->reg->ntsr |= (0x1 << 31); + } else { + /* configure input delay time to 0, use default input phase */ + reg_val = mmc_host->reg->samp_dl; + reg_val &= ~(0x3f); + reg_val |= (0x1 << 7); + mmc_host->reg->samp_dl = reg_val; + } + + return 0; +} + +int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + uint32_t cmdval = MMC_CMD_CMDVAL_MASK; + uint32_t timeout = time_us() + SMHC_TIMEOUT; + uint32_t status; + int ret = 0, error_code = 0; + uint8_t use_dma_status; + + printk_trace("SMHC: CMD%u 0x%x dlen:%u\n", cmd->cmdidx, cmd->cmdarg, data ? data->blkcnt * data->blksz : 0); + + /* Check if have fatal error */ + if (mmc_host->fatal_err) { + printk_error("SMHC: SMHC into error, cmd send failed\n"); + return -1; + } + + /* check card busy*/ + if (cmd->resp_type & MMC_RSP_BUSY) { + printk_debug("SMHC: Card busy"); + } + + /* Check if stop or manual */ + if ((cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) && !(cmd->flags & MMC_CMD_MANUAL)) { + return 0; + } + + /* + * CMDREG + * CMD[5:0] : Command index + * CMD[6] : Has response + * CMD[7] : Long response + * CMD[8] : Check response CRC + * CMD[9] : Has data + * CMD[10] : Write + * CMD[11] : Steam mode + * CMD[12] : Auto stop + * CMD[13] : Wait previous over + * CMD[14] : About cmd + * CMD[15] : Send initialization + * CMD[21] : Update clock + * CMD[31] : Load cmd + */ + + if (cmd->cmdidx) { + cmdval |= SMHC_CMD_SEND_INIT_SEQUENCE; + } + + + if (cmd->resp_type & MMC_RSP_PRESENT) { + cmdval |= SMHC_CMD_RESP_EXPIRE; + if (cmd->resp_type & MMC_RSP_136) + cmdval |= SMHC_CMD_LONG_RESPONSE; + if (cmd->resp_type & MMC_RSP_CRC) + cmdval |= SMHC_CMD_CHECK_RESPONSE_CRC; + } + + if (data) { + /* Check data desc align */ + if ((uint32_t) data->b.dest & 0x3) { + printk_error("SMHC: data dest is not 4 byte align\n"); + error_code = -1; + goto out; + } + + cmdval |= SMHC_CMD_DATA_EXPIRE | SMHC_CMD_WAIT_PRE_OVER; + if (data->flags & MMC_DATA_WRITE) { + cmdval |= SMHC_CMD_WRITE; + } + if (data->blocks > 1) { + cmdval |= SMHC_CMD_SEND_AUTO_STOP; + } + mmc_host->reg->blksz = data->blocksize; + mmc_host->reg->bytecnt = data->blocks * data->blocksize; + } else { + if ((cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) && (cmd->flags & MMC_CMD_MANUAL)) { + cmdval |= SMHC_CMD_STOP_ABORT_CMD;//stop current data transferin progress. + cmdval &= ~SMHC_CMD_WAIT_PRE_OVER;//Send command at once, even if previous data transfer has notcompleted + } + } + + mmc_host->reg->arg = cmd->cmdarg; + + if (!data) { + mmc_host->reg->cmd = (cmdval | cmd->cmdidx); + } + + /* + * transfer data and check status + * STATREG[2] : FIFO empty + * STATREG[3] : FIFO full + */ + + if (data) { + printk_trace("SMHC: transfer data %lu bytes\n", data->blocksize * data->blocks); + if (data->blocksize * data->blocks > 512) { + use_dma_status = true; + mmc_host->reg->gctrl &= (~MMC_CMD_CMDVAL_MASK); + ret = sunxi_sdhci_trans_data_dma(sdhci, data); + mmc_host->reg->cmd = (cmdval & cmd->cmdidx); + } else { + mmc_host->reg->gctrl |= MMC_CMD_CMDVAL_MASK; + mmc_host->reg->cmd = (cmdval & cmd->cmdidx); + ret = sunxi_sdhci_trans_data_cpu(sdhci, data); + } + + if (ret) { + error_code = mmc_host->reg->rint & SMHC_RINT_INTERRUPT_ERROR_BIT; + printk_warning("SMHC: error 0x%x status 0x%x\n", error_code & SMHC_RINT_INTERRUPT_ERROR_BIT, error_code & ~SMHC_RINT_INTERRUPT_ERROR_BIT); + if (!error_code) { + error_code = 0xffffffff; + } + goto out; + } + } + + timeout = time_us() + SMHC_TIMEOUT; + do { + status = mmc_host->reg->rint; + if ((time_us() > timeout) || (status & SMHC_RINT_INTERRUPT_ERROR_BIT)) { + error_code = status & SMHC_RINT_INTERRUPT_ERROR_BIT; + if (!error_code) { + error_code = 0xffffffff; + } + printk_error("SMHC: cmd 0x%08x timeout, error %08x", cmd->cmdidx, error_code); + goto out; + } + } while (!(status & SMHC_RINT_COMMAND_DONE)); + + if (data) { + uint32_t done = false; + timeout = time_us() + (use_dma_status ? SMHC_DMA_TIMEOUT : SMHC_TIMEOUT); + do { + status = mmc_host->reg->rint; + if ((time_us() > timeout) || (status & SMHC_RINT_INTERRUPT_ERROR_BIT)) { + error_code = status & SMHC_RINT_INTERRUPT_ERROR_BIT; + if (!error_code) { + error_code = 0xffffffff; + } + printk_error("SMHC: data timeout, error %08x", error_code); + goto out; + } + + if (data->blocks > 1) { + done = status & SMHC_RINT_AUTO_COMMAND_DONE; + } else { + done = status & SMHC_RINT_DATA_OVER; + } + } while (!done); + + if ((data->flags & MMC_DATA_READ) && use_dma_status) { + timeout = time_us() + SMHC_DMA_TIMEOUT; + done = 0; + status = 0; + do { + status = mmc_host->reg->idst; + if ((time_us() > timeout) || (status & 0x234)) { + error_code = status & 0x1e34; + if (!error_code) { + error_code = 0xffffffff; + } + printk_error("SMHC: wait dma timeout, error %08x", error_code); + goto out; + } + done = status & BIT(1); + } while (!done); + } + } + + if (cmd->resp_type & MMC_RSP_BUSY) { + timeout = time_us() + SMHC_WAITBUSY_TIMEOUT; + do { + status = mmc_host->reg->status; + if ((time_us() > timeout)) { + error_code = -1; + if (!error_code) { + error_code = 0xffffffff; + } + printk_error("SMHC: busy timeout, status %08x", status); + goto out; + } + } while (status & SMHC_STATUS_CARD_DATA_BUSY); + } + + if (cmd->resp_type & MMC_RSP_136) { + cmd->response[0] = mmc_host->reg->resp3; + cmd->response[1] = mmc_host->reg->resp2; + cmd->response[2] = mmc_host->reg->resp1; + cmd->response[3] = mmc_host->reg->resp0; + } else { + cmd->response[0] = mmc_host->reg->resp0; + } + +out: + if (data && use_dma_status) { + /* IDMASTAREG + * IDST[0] : idma tx int + * IDST[1] : idma rx int + * IDST[2] : idma fatal bus error + * IDST[4] : idma descriptor invalid + * IDST[5] : idma error summary + * IDST[8] : idma normal interrupt sumary + * IDST[9] : idma abnormal interrupt sumary + */ + status = mmc_host->reg->idst; + mmc_host->reg->idst = status; + mmc_host->reg->idie = 0; + mmc_host->reg->dmac = 0; + mmc_host->reg->gctrl &= ~SMHC_GCTRL_DMA_ENABLE; + } + + if (error_code) { + mmc_host->reg->gctrl = SMHC_GCTRL_HARDWARE_RESET; + timeout = time_us() + SMHC_TIMEOUT; + while (mmc_host->reg->gctrl & SMHC_GCTRL_HARDWARE_RESET) { + if (time_us() > timeout) { + printk_error("SMHC: controller error reset timeout\n"); + return -1; + } + } + sunxi_sdhci_update_clk(sdhci); + printk_error("SMHC: CMD 0x%08x, error 0x%08x", cmd->cmdidx, error_code); + } + + mmc_host->reg->rint = 0xffffffff; + + if (error_code) { + return -1; + } + + return 0; +} + +int sunxi_sdhci_init(sdhci_t *sdhci) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + mmc_t *mmc = mmc_host->mmc; + + /* Check controller id correct */ + if (sdhci->id > MMC_CONTROLLER_2) { + printk_error("SMHC: Unsupported MAX Controller reached\n"); + return -1; + } + + memset(mmc_host, 0, sizeof(sunxi_sdhci_host_t)); + memset(mmc, 0, sizeof(mmc_t)); + if (sdhci->id == MMC_CONTROLLER_0) { + mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_1; + } else if (sdhci->id == MMC_CONTROLLER_2) { + mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_4; + } + + mmc->voltages = MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | + MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_34_35 | + MMC_VDD_35_36; + mmc->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; + + if (sdhci->width >= SMHC_WIDTH_4BIT) { + mmc->host_caps |= MMC_MODE_4BIT; + } + + if ((sdhci->id == MMC_CONTROLLER_2) && (sdhci->width == SMHC_WIDTH_8BIT)) { + mmc->host_caps |= MMC_MODE_8BIT | MMC_MODE_4BIT; + } + + mmc->f_min = 400000; + mmc->f_max = sdhci->max_clk; + mmc->f_max_ddr = sdhci->max_clk; + + mmc_host->reg = (sdhci_reg_t *) sdhci->reg_base; + mmc_host->database = (uint32_t) sdhci->reg_base + MMC_REG_FIFO_OS; + mmc_host->hclkbase = sdhci->clk_ctrl_base; + mmc_host->hclkrst = sdhci->clk_ctrl_base; + mmc_host->mclkbase = sdhci->clk_base; + + sunxi_sdhci_pin_config(sdhci); + sunxi_sdhci_clk_enable(sdhci); + + return 0; +} \ No newline at end of file diff --git a/src/drivers/sys-sdhci.c b/src/drivers/sys-sdhci.c index f9006654..0095f2d7 100644 --- a/src/drivers/sys-sdhci.c +++ b/src/drivers/sys-sdhci.c @@ -337,7 +337,7 @@ bool sdhci_transfer(sdhci_t *sdhci, sdhci_cmd_t *cmd, sdhci_data_t *dat) { return FALSE; } - if (dat && wait_done(sdhci, dat, 6000, dat->blkcnt > 1 ? SMHC_RINT_AUTO_COMMAND_DONE : SMHC_RINT_DATA_OVER, dma)) { + if (dat && wait_done(sdhci, dat, 8000, dat->blkcnt > 1 ? SMHC_RINT_AUTO_COMMAND_DONE : SMHC_RINT_DATA_OVER, dma)) { printk_warning("SMHC: data timeout\n"); return FALSE; } From 7e3f17139bb3a3e6274aebddec597824b233196d Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sun, 2 Jun 2024 21:35:18 +0800 Subject: [PATCH 02/12] [driver] update comment --- include/drivers/mmc/sys-sdhci.h | 33 ++- src/drivers/mmc/sys-sdhci.c | 365 +++++++++++++++++++++++++------- 2 files changed, 310 insertions(+), 88 deletions(-) diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index 7f92899b..45f93f21 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -116,37 +116,48 @@ typedef struct sdhci { /** * @brief Initialize the SDHC controller. * - * This function initializes the given SDHC controller. + * This function initializes the SDHC controller by configuring its parameters, + * capabilities, and features based on the provided SDHC structure. It sets up + * the controller's timing mode, supported voltages, host capabilities, clock + * frequency limits, and register addresses. Additionally, it configures pin + * settings and enables clocks for the SDHC controller. * - * @param sdhci Pointer to the SDHC controller to initialize. + * @param sdhci Pointer to the SDHC structure. * @return Returns 0 on success, -1 on failure. */ int sunxi_sdhci_init(sdhci_t *sdhci); /** - * @brief Initialize the core functionality of the SDHC. + * @brief Initialize the core functionality of the SDHC controller. * - * This function initializes the core functionality of the given SDHC controller. + * This function initializes the core functionality of the SDHC controller, + * including resetting the controller, setting timeout values, configuring + * thresholds and debug parameters, and releasing the eMMC reset signal. * - * @param sdhci Pointer to the SDHC controller to initialize. + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success, -1 on failure. */ int sunxi_sdhci_core_init(sdhci_t *sdhci); /** - * @brief Set the I/O parameters of the SDHC controller. + * @brief Set the I/O settings for the SDHC controller. * - * This function sets the I/O parameters of the given SDHC controller. + * This function configures the I/O settings for the SDHC controller based on the + * provided MMC clock, bus width, and speed mode. * - * @param sdhci Pointer to the SDHC controller to set I/O parameters for. + * @param sdhci Pointer to the SDHC controller structure. + * @return void */ void sunxi_sdhci_set_ios(sdhci_t *sdhci); /** - * @brief Perform data transfer operation for the SDHC controller. + * @brief Perform a data transfer operation on the SDHC controller. * - * This function performs the data transfer operation for the given SDHC controller. + * This function performs a data transfer operation on the SDHC controller, + * including sending a command and managing data transfer if present. It also + * handles error conditions such as fatal errors and card busy status. * - * @param sdhci Pointer to the SDHC controller to perform data transfer operation. + * @param sdhci Pointer to the SDHC controller structure. * @param cmd Pointer to the MMC command structure. * @param data Pointer to the MMC data structure. * @return Returns 0 on success, -1 on failure. diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index 72d1c301..2fc3c32f 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -20,34 +20,49 @@ #include #include - +/** + * @brief Enable clock for the SDHC controller. + * + * This function enables clock for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success. + */ static int sunxi_sdhci_clk_enable(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - uint32_t rval; - /* config ahb clock */ - rval = readl(mmc_host->hclkbase); - rval |= (1 << (sdhci->id)); - writel(rval, mmc_host->hclkbase); + uint32_t reg_val; + /* Configure AHB clock */ + reg_val = readl(mmc_host->hclkbase); + reg_val |= (1 << (sdhci->id)); + writel(reg_val, mmc_host->hclkbase); - rval = readl(mmc_host->hclkrst); - rval |= (1 << (16 + sdhci->id)); - writel(rval, mmc_host->hclkrst); + reg_val = readl(mmc_host->hclkrst); + reg_val |= (1 << (16 + sdhci->id)); + writel(reg_val, mmc_host->hclkrst); - /* config mod clock */ + /* Configure module clock */ writel(0x80000000, mmc_host->mclkbase); mmc_host->mod_clk = 24000000; return 0; } +/** + * @brief Update clock for the SDHC controller. + * + * This function updates the clock for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success, -1 on failure. + */ static int sunxi_sdhci_update_clk(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; uint32_t cmd = 0x0; uint32_t timeout = time_us() + SMHC_TIMEOUT; - mmc_host->reg->clkcr |= (0x1U << 31); - mmc_host->reg->cmd = (1U << 31) | (1 << 21) | (1 << 13); + mmc_host->reg->clkcr |= SMHC_CLKCR_MASK_D0; + mmc_host->reg->cmd = SMHC_CMD_START | SMHC_CMD_UPCLK_ONLY | SMHC_CMD_WAIT_PRE_OVER; /* Wait for process done */ while ((mmc_host->reg->cmd & MMC_CMD_CMDVAL_MASK) && (time_us() < timeout)) { @@ -59,62 +74,97 @@ static int sunxi_sdhci_update_clk(sdhci_t *sdhci) { return -1; } - mmc_host->reg->clkcr &= (~(0x1U << 31)); + mmc_host->reg->clkcr &= ~SMHC_CLKCR_MASK_D0; mmc_host->reg->rint = mmc_host->reg->rint; return 0; } +/** + * @brief Update phase for the SDHC controller. + * + * This function updates the phase for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success. + */ static int sunxi_sdhci_update_phase(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + // Check if timing mode is mode 1 if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { printk_trace("SMHC: mmc update phase.\n"); + // Call function to update clock return sunxi_sdhci_update_clk(sdhci); } + return 0; } + static int sunxi_sdhci_get_timing_config_timing_4(sdhci_t *sdhci) { /* TODO: eMMC Timing set */ } +/** + * @brief Get timing configuration for the SDHC controller. + * + * This function retrieves the timing configuration for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success, -1 on failure. + */ static int sunxi_sdhci_get_timing_config(sdhci_t *sdhci) { int ret = 0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + // Check for specific conditions based on the controller ID and timing mode if ((sdhci->id == 2) && mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { - /* When using eMMC and SMHC2, we config it as timging 4 */ + /* When using eMMC and SMHC2, config it as timing 4 */ ret = sunxi_sdhci_get_timing_config_timing_4(sdhci); } else if ((sdhci->id == 0) && (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1)) { + // Check timing data and adjust configuration if necessary if ((timing_data->spd_md_id <= MMC_HSSDR52_SDR25) && (timing_data->freq_id <= MMC_CLK_50M)) { - /* if timing less then SDR25 using default odly */ + /* if timing less than SDR25, use default odly */ timing_data->odly = 0; timing_data->sdly = 0; ret = 0; } else { - printk_warning("SMHC: SMHC0 do not support input spd mode %d\n", timing_data->spd_md_id); + printk_warning("SMHC: SMHC0 does not support input spd mode %d\n", timing_data->spd_md_id); ret = -1; } } else { - printk_error("SMHC: timing setting fail, param error\n"); + printk_error("SMHC: timing setting failed, parameter error\n"); ret = -1; } + return ret; } +/** + * @brief Set the SDHC controller's clock frequency. + * + * This function sets the clock frequency for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param clk_hz Desired clock frequency in Hertz. + * @return Returns 0 on success, -1 on failure. + */ static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { uint32_t n, m, src; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + // Determine the clock source based on the requested frequency if (clk_hz <= 4000000) { - src = 0; /* SCLK = 24000000 OSC CLK */ + src = 0; // SCLK = 24000000 OSC CLK } else { - src = 2; /* SCLK = AHB PLL */ + src = 2; // SCLK = AHB PLL } + // Set the clock divider values based on the requested frequency switch (clk_hz) { case 400000: n = 1; @@ -131,34 +181,46 @@ static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { m = 2; break; case 200000000: - src = 1;// PERI0_800M + src = 1; // PERI0_800M n = 0; m = 1; break; default: n = 0; m = 0; - printk_error("SMHC: request freq not match freq=%d\n", clk_hz); + printk_error("SMHC: requested frequency does not match: freq=%d\n", clk_hz); break; } + // Configure the clock register value reg_val = (src << 24) | (n << 8) | m; writel(reg_val, mmc_host->mclkbase); return 0; } +/** + * @brief Get the current clock frequency of the SDHC controller. + * + * This function retrieves the current clock frequency of the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Current clock frequency in Hertz. + */ static uint32_t sunxi_sdhci_get_mclk(sdhci_t *sdhci) { uint32_t n, m, src, clk_hz; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + // Read the clock register value reg_val = readl(mmc_host->mclkbase); + // Extract the divider values and clock source from the register value m = reg_val & 0xf; n = (reg_val >> 8) & 0x3; src = (reg_val >> 24) & 0x3; + // Calculate the current clock frequency based on the source and divider values switch (src) { case 0: clk_hz = 24000000; @@ -176,9 +238,18 @@ static uint32_t sunxi_sdhci_get_mclk(sdhci_t *sdhci) { break; } + // Calculate the actual clock frequency based on the divider values return clk_hz / (n + 1) / (m + 1); } +/** + * @brief Configure the delay for the SDHC controller based on timing mode. + * + * This function configures the delay for the SDHC controller based on the timing mode. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return 0 on success, -1 on failure. + */ static int sunxi_sdhci_config_delay(sdhci_t *sdhci) { int ret = 0; uint32_t reg_val = 0x0; @@ -275,6 +346,15 @@ static int sunxi_sdhci_config_delay(sdhci_t *sdhci) { } } +/** + * @brief Set the clock mode for the SDHC controller based on timing mode and other parameters. + * + * This function sets the clock mode for the SDHC controller based on the timing mode and other parameters. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param clk Clock frequency. + * @return 0 on success, -1 on failure. + */ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { int ret = 0; uint32_t reg_val = 0x0; @@ -380,92 +460,148 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { return 0; } +/** + * @brief Configure the clock for the SDHC controller. + * + * This function configures the clock for the SDHC controller based on the specified clock frequency + * and other parameters. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param clk Clock frequency. + * @return 0 on success, -1 on failure. + */ static int sunxi_sdhci_config_clock(sdhci_t *sdhci, uint32_t clk) { - uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = mmc_host->mmc; - if ((mmc->speed_mode == MMC_HSDDR52_DDR50) || (mmc->speed_mode == MMC_HS400)) { - if (clk > mmc->f_max_ddr) { - clk = mmc->f_max_ddr; - } + // Adjust clock frequency if it exceeds the maximum supported frequency for certain speed modes + if ((mmc->speed_mode == MMC_HSDDR52_DDR50 || mmc->speed_mode == MMC_HS400) && clk > mmc->f_max_ddr) { + clk = mmc->f_max_ddr; } - /* disable clock */ - mmc_host->reg->clkcr &= ~(0x1 << 16); + // Disable clock before configuration + mmc_host->reg->clkcr &= ~SMHC_CLKCR_CARD_CLOCK_ON; + // Update clock settings if (sunxi_sdhci_update_clk(sdhci)) { + printk_error("SMHC: Failed to update clock settings\n"); return -1; } - if ((mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3) || (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4)) { - sunxi_sdhci_clock_mode(sdhci, clk); + // Configure clock mode based on timing mode + if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1 || mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3 || + mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { + if (sunxi_sdhci_clock_mode(sdhci, clk)) { + printk_error("SMHC: Failed to configure clock mode\n"); + return -1; + } } else { - printk_error("SMHC: Timing mode not supported!\n"); + printk_error("SMHC: Timing mode not supported\n"); return -1; } - /* enable clock */ + // Enable clock after configuration mmc_host->reg->clkcr |= (0x1 << 16); + // Check if clock update after configuration fails if (sunxi_sdhci_update_clk(sdhci)) { - printk_error("SMHC: reconfigure clk failed\n"); + printk_error("SMHC: Failed to update clock settings after configuration\n"); return -1; } - return 0; + return 0; // Success } +/** + * @brief Set DDR mode for the SDHC controller. + * + * This function sets the DDR mode for the SDHC controller based on the specified status. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param status Boolean indicating whether to enable (true) or disable (false) DDR mode. + */ static void sunxi_sdhci_ddr_mode_set(sdhci_t *sdhci, bool status) { uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + // Read current value of gctrl register reg_val = mmc_host->reg->gctrl; - reg_val &= ~(0x1 << 10); - /* disable ccu clock */ + + // Disable CCU clock writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); + // Set or clear DDR mode bit based on status if (status) { - reg_val |= (0x1 << 10); + reg_val |= SMHC_GCTRL_DDR_MODE; // Set DDR mode bit + } else { + reg_val &= ~SMHC_GCTRL_DDR_MODE; // Clear DDR mode bit } + // Write updated value back to gctrl register mmc_host->reg->gctrl = reg_val; - /* enable ccu clock */ + // Enable CCU clock writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); - printk_trace("SMHC: set to %s ddr mode\n", status ? "enable" : "disable"); + // Log DDR mode status + printk_trace("SMHC: DDR mode %s\n", status ? "enabled" : "disabled"); } +/** + * @brief Set HS400 mode for the SDHC controller. + * + * This function sets the HS400 mode for the SDHC controller based on the specified status. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param status Boolean indicating whether to enable (true) or disable (false) HS400 mode. + */ static void sunxi_sdhci_hs400_mode_set(sdhci_t *sdhci, bool status) { uint32_t reg_dsbd_val = 0x0, reg_csdc_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + // Check if the SDHC controller ID is 2 if (sdhci->id != 2) { + // HS400 mode setting is not applicable, return return; } + // Read current values of dsbd and csdc registers reg_dsbd_val = mmc_host->reg->dsbd; - reg_dsbd_val &= ~(0x1 << 31); - reg_csdc_val = mmc_host->reg->csdc; - reg_csdc_val &= ~0xf; + // Clear existing bits related to HS400 mode + reg_dsbd_val &= ~(0x1 << 31); // Clear HS400EN bit + reg_csdc_val &= ~0xf; // Clear HSSDR bit and HS400DS bit + + // Configure HS400 mode based on status if (status) { + // Set HS400EN bit and configure HS400DS to 6 (HS400 mode) reg_dsbd_val |= (0x1 << 31); reg_csdc_val |= 0x6; } else { + // Configure HS400DS to 3 (backward compatibility mode) reg_csdc_val |= 0x3; } + // Write updated values back to dsbd and csdc registers mmc_host->reg->dsbd = reg_dsbd_val; mmc_host->reg->csdc = reg_csdc_val; - printk_trace("SMHC: set to %s HS400 mode\n", status ? "enable" : "disable"); + // Log HS400 mode status + printk_trace("SMHC: HS400 mode %s\n", status ? "enabled" : "disabled"); } +/** + * @brief Configure GPIO pins for the SDHC controller. + * + * This function initializes and configures the GPIO pins used by the SDHC controller based on the provided configuration. + * + * @param sdhci Pointer to the SDHC controller structure. + */ static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { sunxi_sdhci_pinctrl_t *sdhci_pins = sdhci->pinctrl; + // Initialize and configure GPIO pins for clock, command, and data lines sunxi_gpio_init(sdhci_pins->gpio_clk.pin, sdhci_pins->gpio_clk.mux); sunxi_gpio_set_pull(sdhci_pins->gpio_clk.pin, GPIO_PULL_UP); @@ -475,7 +611,7 @@ static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { sunxi_gpio_init(sdhci_pins->gpio_d0.pin, sdhci_pins->gpio_d0.mux); sunxi_gpio_set_pull(sdhci_pins->gpio_d0.pin, GPIO_PULL_UP); - /* Init GPIO for 4bit MMC */ + // Initialize and configure GPIO pins for 4-bit MMC data bus if applicable if (sdhci->width > SMHC_WIDTH_1BIT) { sunxi_gpio_init(sdhci_pins->gpio_d1.pin, sdhci_pins->gpio_d1.mux); sunxi_gpio_set_pull(sdhci_pins->gpio_d1.pin, GPIO_PULL_UP); @@ -487,7 +623,7 @@ static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { sunxi_gpio_set_pull(sdhci_pins->gpio_d3.pin, GPIO_PULL_UP); } - /* Init GPIO for 8bit MMC */ + // Initialize and configure GPIO pins for 8-bit MMC data bus if applicable if (sdhci->width > SMHC_WIDTH_4BIT) { sunxi_gpio_init(sdhci_pins->gpio_d4.pin, sdhci_pins->gpio_d4.mux); sunxi_gpio_set_pull(sdhci_pins->gpio_d4.pin, GPIO_PULL_UP); @@ -501,6 +637,7 @@ static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { sunxi_gpio_init(sdhci_pins->gpio_d7.pin, sdhci_pins->gpio_d7.mux); sunxi_gpio_set_pull(sdhci_pins->gpio_d7.pin, GPIO_PULL_UP); + // Additional GPIO pins for 8-bit MMC configuration sunxi_gpio_init(sdhci_pins->gpio_ds.pin, sdhci_pins->gpio_ds.mux); sunxi_gpio_set_pull(sdhci_pins->gpio_ds.pin, GPIO_PULL_DOWN); @@ -509,43 +646,67 @@ static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { } } +/** + * @brief Transfer data between SDHC controller and host CPU. + * + * This function handles the data transfer between the SDHC controller and the host CPU. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param data Pointer to the MMC data structure containing transfer information. + * @return 0 on success, -1 on failure. + */ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; uint32_t timeout = time_us() + SMHC_TIMEOUT; uint32_t *buff; + // Determine the buffer based on the direction of data transfer if (data->flags * MMC_DATA_READ) { - buff = (uint32_t *) data->b.dest; - for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { - while ((mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) && (time_us() < timeout)) { - } - if (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) { - if (time_us() >= timeout) { - printk_error("SMHC: tranfer read by cpu failed, timeout\n"); - return -1; - } - } - buff[i] = readl(mmc_host->database); - timeout = time_us() + SMHC_TIMEOUT; - } + buff = (uint32_t *) data->b.dest; // Destination buffer for read operation } else { - buff = (uint32_t *) data->b.src; - for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { - while (((mmc_host->reg->status) & SMHC_STATUS_FIFO_FULL) && (time_us() < timeout)) { - } - if (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL) { - if (time_us() >= timeout) { - printk_error("SMHC: tranfer write by cpu failed, timeout\n"); - return -1; - } + buff = (uint32_t *) data->b.src; // Source buffer for write operation + } + + // Iterate over blocks of data to be transferred + for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { + // Wait until FIFO is empty for read operation, or full for write operation + while (((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : + (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) && (time_us() < timeout)) { + } + + // Check for timeout + if ((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : + (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) { + if (time_us() >= timeout) { + printk_error("SMHC: transfer %s by CPU failed, timeout\n", + (data->flags * MMC_DATA_READ) ? "read" : "write"); + return -1; // Return failure indication } - writel(buff[i], mmc_host->database); - timeout = time_us() + SMHC_TIMEOUT; } + + // Perform read or write operation based on the direction of data transfer + if (data->flags * MMC_DATA_READ) { + buff[i] = readl(mmc_host->database); // Read data from FIFO to buffer + } else { + writel(buff[i], mmc_host->database); // Write data from buffer to FIFO + } + + timeout = time_us() + SMHC_TIMEOUT; // Update timeout for next iteration } - return 0; + + return 0; // Return success indication } +/** + * @brief Transfer data between SDHC controller and host CPU using DMA. + * + * This function handles the data transfer between the SDHC controller and the host CPU + * using Direct Memory Access (DMA). + * + * @param sdhci Pointer to the SDHC controller structure. + * @param data Pointer to the MMC data structure containing transfer information. + * @return void + */ static int sunxi_sdhci_trans_data_dma(sdhci_t *sdhci, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; sunxi_sdhci_desc_t *pdes = mmc_host->sdhci_desc; @@ -656,17 +817,27 @@ static int sunxi_sdhci_trans_data_dma(sdhci_t *sdhci, mmc_data_t *data) { return 0; } +/** + * @brief Set the I/O settings for the SDHC controller. + * + * This function configures the I/O settings for the SDHC controller based on the + * provided MMC clock, bus width, and speed mode. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return void + */ void sunxi_sdhci_set_ios(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = mmc_host->mmc; + // Configure clock and handle errors if (mmc->clock && sunxi_sdhci_config_clock(sdhci, mmc->clock)) { printk_error("SMHC: update clock failed\n"); mmc_host->fatal_err = 1; return; } - /* change bus width */ + /* Change bus width */ switch (sdhci->width) { case SMHC_WIDTH_8BIT: mmc_host->reg->width = 2; @@ -693,6 +864,16 @@ void sunxi_sdhci_set_ios(sdhci_t *sdhci) { } } +/** + * @brief Initialize the core functionality of the SDHC controller. + * + * This function initializes the core functionality of the SDHC controller, + * including resetting the controller, setting timeout values, configuring + * thresholds and debug parameters, and releasing the eMMC reset signal. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success, -1 on failure. + */ int sunxi_sdhci_core_init(sdhci_t *sdhci) { uint32_t reg_val = 0x0; uint32_t timeout = time_us() + SMHC_TIMEOUT; @@ -715,7 +896,7 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci) { mmc_host->reg->csdc = 0x3; mmc_host->reg->dbgc = 0xdeb; - /* Release emmc RST */ + /* Release eMMC RST */ mmc_host->reg->hwrst = 1; mmc_host->reg->hwrst = 0; mdelay(1); @@ -723,10 +904,10 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci) { mdelay(1); if (sdhci->id == 0) { - /* enable 2xclk mode, and use default input phase */ + /* Enable 2xclk mode, and use default input phase */ mmc_host->reg->ntsr |= (0x1 << 31); } else { - /* configure input delay time to 0, use default input phase */ + /* Configure input delay time to 0, use default input phase */ reg_val = mmc_host->reg->samp_dl; reg_val &= ~(0x3f); reg_val |= (0x1 << 7); @@ -736,6 +917,18 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci) { return 0; } +/** + * @brief Perform a data transfer operation on the SDHC controller. + * + * This function performs a data transfer operation on the SDHC controller, + * including sending a command and managing data transfer if present. It also + * handles error conditions such as fatal errors and card busy status. + * + * @param sdhci Pointer to the SDHC controller structure. + * @param cmd Pointer to the MMC command structure. + * @param data Pointer to the MMC data structure. + * @return Returns 0 on success, -1 on failure. + */ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; uint32_t cmdval = MMC_CMD_CMDVAL_MASK; @@ -968,11 +1161,23 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { return 0; } +/** + * @brief Initialize the SDHC controller. + * + * This function initializes the SDHC controller by configuring its parameters, + * capabilities, and features based on the provided SDHC structure. It sets up + * the controller's timing mode, supported voltages, host capabilities, clock + * frequency limits, and register addresses. Additionally, it configures pin + * settings and enables clocks for the SDHC controller. + * + * @param sdhci Pointer to the SDHC structure. + * @return Returns 0 on success, -1 on failure. + */ int sunxi_sdhci_init(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = mmc_host->mmc; - /* Check controller id correct */ + /* Check if controller ID is correct */ if (sdhci->id > MMC_CONTROLLER_2) { printk_error("SMHC: Unsupported MAX Controller reached\n"); return -1; @@ -980,37 +1185,43 @@ int sunxi_sdhci_init(sdhci_t *sdhci) { memset(mmc_host, 0, sizeof(sunxi_sdhci_host_t)); memset(mmc, 0, sizeof(mmc_t)); + + /* Set timing mode based on controller ID */ if (sdhci->id == MMC_CONTROLLER_0) { mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_1; } else if (sdhci->id == MMC_CONTROLLER_2) { mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_4; } + /* Set supported voltages and host capabilities */ mmc->voltages = MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_34_35 | MMC_VDD_35_36; mmc->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HC; + /* Set host capabilities for bus width */ if (sdhci->width >= SMHC_WIDTH_4BIT) { mmc->host_caps |= MMC_MODE_4BIT; } - if ((sdhci->id == MMC_CONTROLLER_2) && (sdhci->width == SMHC_WIDTH_8BIT)) { mmc->host_caps |= MMC_MODE_8BIT | MMC_MODE_4BIT; } + /* Set clock frequency limits */ mmc->f_min = 400000; mmc->f_max = sdhci->max_clk; mmc->f_max_ddr = sdhci->max_clk; + /* Set register addresses */ mmc_host->reg = (sdhci_reg_t *) sdhci->reg_base; mmc_host->database = (uint32_t) sdhci->reg_base + MMC_REG_FIFO_OS; mmc_host->hclkbase = sdhci->clk_ctrl_base; mmc_host->hclkrst = sdhci->clk_ctrl_base; mmc_host->mclkbase = sdhci->clk_base; + /* Configure pins and enable clocks */ sunxi_sdhci_pin_config(sdhci); sunxi_sdhci_clk_enable(sdhci); return 0; -} \ No newline at end of file +} From a3627f38d1f1b9c7f911ed08e37f07e1b65cf592 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sun, 2 Jun 2024 21:51:08 +0800 Subject: [PATCH 03/12] [driver] back port to mmc v1 --- include/drivers/mmc/sys-mmc.h | 3 --- include/drivers/mmc/sys-sdcard.h | 3 --- include/drivers/mmc/sys-sdhci.h | 5 +---- src/drivers/mmc/sys-mmc.c | 21 +++++++++++++++++++++ src/drivers/mmc/sys-sdcard.c | 3 --- src/drivers/mmc/sys-sdhci.c | 13 +++++-------- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h index 84d57165..b9a30daa 100644 --- a/include/drivers/mmc/sys-mmc.h +++ b/include/drivers/mmc/sys-mmc.h @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* MMC driver for General mmc operations - * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ - */ #ifndef _SYS_MMC_H_ #define _SYS_MMC_H_ diff --git a/include/drivers/mmc/sys-sdcard.h b/include/drivers/mmc/sys-sdcard.h index 2dc4931e..8a81c8c9 100644 --- a/include/drivers/mmc/sys-sdcard.h +++ b/include/drivers/mmc/sys-sdcard.h @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* MMC driver for General mmc operations - * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ - */ #ifndef _SYS_SDCARD_H_ #define _SYS_SDCARD_H_ diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index 45f93f21..d203a807 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* MMC driver for General mmc operations - * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ - */ #ifndef _SYS_SDHCI_H_ #define _SYS_SDHCI_H_ @@ -72,7 +69,6 @@ typedef struct sunxi_sdhci_host { uint32_t fatal_err; sunxi_sdhci_desc_t sdhci_desc[32]; uint32_t timing_mode; - mmc_t *mmc; uint32_t mod_clk; uint32_t clock; } sunxi_sdhci_host_t; @@ -107,6 +103,7 @@ typedef struct sdhci { uint32_t clk_ctrl_base; uint32_t clk_base; uint32_t max_clk; + mmc_t *mmc; sunxi_sdhci_type_t type; sunxi_sdhci_host_t *mmc_host; sunxi_sdhci_pinctrl_t *pinctrl; diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index e69de29b..eb737cf8 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +static int sunxi_mmc_send_status() { +} \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdcard.c b/src/drivers/mmc/sys-sdcard.c index 3a95dca9..85bc12e5 100644 --- a/src/drivers/mmc/sys-sdcard.c +++ b/src/drivers/mmc/sys-sdcard.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* MMC driver for General mmc operations - * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ - */ #include #include diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index 2fc3c32f..4673c18a 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -1,7 +1,4 @@ /* SPDX-License-Identifier: GPL-2.0+ */ -/* MMC driver for General mmc operations - * Original https://github.com/smaeul/sun20i_d1_spl/blob/mainline/drivers/mmc/sun20iw1p1/ - */ #include #include @@ -360,7 +357,7 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; - mmc_t *mmc = mmc_host->mmc; + mmc_t *mmc = sdhci->mmc; /* disable mclk */ writel(0x0, mmc_host->mclkbase); @@ -472,7 +469,7 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { */ static int sunxi_sdhci_config_clock(sdhci_t *sdhci, uint32_t clk) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - mmc_t *mmc = mmc_host->mmc; + mmc_t *mmc = sdhci->mmc; // Adjust clock frequency if it exceeds the maximum supported frequency for certain speed modes if ((mmc->speed_mode == MMC_HSDDR52_DDR50 || mmc->speed_mode == MMC_HS400) && clk > mmc->f_max_ddr) { @@ -828,7 +825,7 @@ static int sunxi_sdhci_trans_data_dma(sdhci_t *sdhci, mmc_data_t *data) { */ void sunxi_sdhci_set_ios(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - mmc_t *mmc = mmc_host->mmc; + mmc_t *mmc = sdhci->mmc; // Configure clock and handle errors if (mmc->clock && sunxi_sdhci_config_clock(sdhci, mmc->clock)) { @@ -878,7 +875,7 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci) { uint32_t reg_val = 0x0; uint32_t timeout = time_us() + SMHC_TIMEOUT; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - mmc_t *mmc = mmc_host->mmc; + mmc_t *mmc = sdhci->mmc; /* Reset controller */ mmc_host->reg->gctrl = 0x7; @@ -1175,7 +1172,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { */ int sunxi_sdhci_init(sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - mmc_t *mmc = mmc_host->mmc; + mmc_t *mmc = sdhci->mmc; /* Check if controller ID is correct */ if (sdhci->id > MMC_CONTROLLER_2) { From ddb225e7c59e7b217153d33e74e06e6cb309d41d Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sun, 2 Jun 2024 23:50:59 +0800 Subject: [PATCH 04/12] [driver] add basic mmc driver WIP 1/3 --- include/drivers/mmc/sys-mmc.h | 2 + include/drivers/mmc/sys-sdhci.h | 10 + src/drivers/mmc/sys-mmc.c | 784 +++++++++++++++++++++++++++++++- src/drivers/mmc/sys-sdhci.c | 136 ++++-- 4 files changed, 895 insertions(+), 37 deletions(-) diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h index b9a30daa..f905e805 100644 --- a/include/drivers/mmc/sys-mmc.h +++ b/include/drivers/mmc/sys-mmc.h @@ -213,6 +213,8 @@ enum { #define PART_ACCESS_MASK (0x7) #define PART_SUPPORT (0x1) +#define be32_to_cpu(x) ((0x000000ff & ((x) >> 24)) | (0x0000ff00 & ((x) >> 8)) | (0x00ff0000 & ((x) << 8)) | (0xff000000 & ((x) << 24))) + typedef enum { MMC_DS26_SDR12 = 0, MMC_HSSDR52_SDR25 = 1, diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index d203a807..3d9c0d4c 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -147,6 +147,16 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci); */ void sunxi_sdhci_set_ios(sdhci_t *sdhci); +/** + * @brief Update phase for the SDHC controller. + * + * This function updates the phase for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success. + */ +int sunxi_sdhci_update_phase(sdhci_t *sdhci); + /** * @brief Perform a data transfer operation on the SDHC controller. * diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index eb737cf8..e4bcd4b6 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -17,5 +17,787 @@ #include #include -static int sunxi_mmc_send_status() { +static inline int sunxi_mmc_host_is_spi(mmc_t *mmc) { + return (mmc->host_caps & MMC_MODE_SPI); +} + +static int sunxi_mmc_send_status(sdhci_t *sdhci, uint32_t timeout) { + mmc_t *mmc = sdhci->mmc; + int err = 0; + + mmc_cmd_t cmd; + cmd.cmdidx = MMC_CMD_SEND_STATUS; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = mmc->rca << 16; + cmd.flags = 0; + + do { + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + if (err) { + printk_error("SMHC%u: Send status failed\n", sdhci->id); + return err; + } else if (cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) + break; + mdelay(1); + if (cmd.response[0] & MMC_STATUS_MASK) { + printk_error("SMHC%u: Status Error: 0x%08X\n", sdhci->id, cmd.response[0]); + return COMM_ERR; + } + } while (timeout--); + + if (!timeout) { + printk_error("SMHC%u: Timeout waiting card ready\n", sdhci->id); + return TIMEOUT; + } + + return 0; +} + +static int sunxi_mmc_set_block_len(sdhci_t *sdhci, uint32_t len) { + mmc_t *mmc = sdhci->mmc; + mmc_cmd_t cmd; + /* don't set blocklen at ddr mode */ + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) || (mmc->speed_mode == MMC_HS400)) { + return 0; + } + cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = len; + cmd.flags = 0; + + return sunxi_sdhci_xfer(sdhci, &cmd, NULL); +} + +static uint64_t sunxi_mmc_read_blocks(sdhci_t *sdhci, void *dst, uint64_t start, uint64_t blkcnt) { + mmc_t *mmc = sdhci->mmc; + + mmc_cmd_t cmd; + mmc_data_t data; + + int timeout = 1000; + + if (blkcnt > 1) + cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; + else + cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; + + if (mmc->high_capacity) + cmd.cmdarg = start; + else + cmd.cmdarg = start * mmc->read_bl_len; + + cmd.resp_type = MMC_RSP_R1; + cmd.flags = 0; + + data.b.dest = dst; + data.blocks = blkcnt; + data.blocksize = mmc->read_bl_len; + data.flags = MMC_DATA_READ; + + if (sunxi_sdhci_xfer(sdhci, &cmd, &data)) { + printk_error("SMHC: read blcok failed\n"); + return 0; + } + + if (blkcnt > 1) { + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1b; + cmd.flags = 0; + if (sunxi_sdhci_xfer(sdhci, &cmd, NULL)) { + printk_error("SMHC: fail to send stop cmd\n"); + return 0; + } + + /* Waiting for the ready status */ + sunxi_mmc_send_status(sdhci, timeout); + } + + return blkcnt; +} + +static int sunxi_mmc_go_idle(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + mmc_cmd_t cmd; + + int err = 0; + + cmd.cmdidx = MMC_CMD_GO_IDLE_STATE; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_NONE; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: idle failed\n"); + return err; + } + mdelay(2); + return 0; +} + +static int sunxi_mmc_sd_send_op_cond(sdhci_t *sdhci) { + int timeout = 1000; + int err; + + mmc_t *mmc = sdhci->mmc; + mmc_cmd_t cmd; + + do { + cmd.cmdidx = MMC_CMD_APP_CMD; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 0; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: send app cmd failed\n"); + return err; + } + + cmd.cmdidx = SD_CMD_APP_SEND_OP_COND; + cmd.resp_type = MMC_RSP_R3; + + /* + * Most cards do not answer if some reserved bits + * in the ocr are set. However, Some controller + * can set bit 7 (reserved for low voltages), but + * how to manage low voltages SD card is not yet + * specified. + */ + cmd.cmdarg = sunxi_mmc_host_is_spi(mmc) ? 0 : (mmc->voltages & 0xff8000); + + if (mmc->version == SD_VERSION_2) + cmd.cmdarg |= OCR_HCS; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: send cmd41 failed\n"); + return err; + } + + mdelay(1); + } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--); + + if (timeout <= 0) { + printk_error("SMHC: wait card init failed\n"); + return UNUSABLE_ERR; + } + + if (mmc->version != SD_VERSION_2) + mmc->version = SD_VERSION_1_0; + + if (mmc_host_is_spi(mmc)) { /* read OCR for spi */ + cmd.cmdidx = MMC_CMD_SPI_READ_OCR; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = 0; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: spi read ocr failed\n"); + return err; + } + } + + mmc->ocr = cmd.response[0]; + + mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); + mmc->rca = 0; + + return 0; +} + +static int sunxi_mmc_mmc_send_op_cond(sdhci_t *sdhci) { + int timeout = 1000; + int err; + + mmc_t *mmc = sdhci->mmc; + mmc_cmd_t cmd; + + /* Some cards seem to need this */ + sunxi_mmc_go_idle(sdhci); + + /* Asking to the card its capabilities */ + cmd.cmdidx = MMC_CMD_SEND_OP_COND; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = 0; /*0x40ff8000;*/ /*foresee */ + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: send op cond failed\n"); + return err; + } + + mdelay(1); + + do { + cmd.cmdidx = MMC_CMD_SEND_OP_COND; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = (sunxi_mmc_host_is_spi(mmc) ? 0 : (mmc->voltages & (cmd.response[0] & OCR_VOLTAGE_MASK)) | (cmd.response[0] & OCR_ACCESS_MODE)); + + if (mmc->host_caps & MMC_MODE_HC) + cmd.cmdarg |= OCR_HCS; + + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: send op cond failed\n"); + return err; + } + + mdelay(1); + } while (!(cmd.response[0] & OCR_BUSY) && timeout--); + + if (timeout <= 0) { + printk_error("SMHC: wait for mmc init failed\n"); + return UNUSABLE_ERR; + } + + if (sunxi_mmc_host_is_spi(mmc)) { /* read OCR for spi */ + cmd.cmdidx = MMC_CMD_SPI_READ_OCR; + cmd.resp_type = MMC_RSP_R3; + cmd.cmdarg = 0; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + if (err) + return err; + } + + mmc->version = MMC_VERSION_UNKNOWN; + mmc->ocr = cmd.response[0]; + + mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); + mmc->rca = 1; + + return 0; +} + +static int sunxi_mmc_send_ext_csd(sdhci_t *sdhci, char *ext_csd) { + mmc_t *mmc = sdhci->mmc; + + mmc_cmd_t cmd; + mmc_data_t data; + int err; + + /* Get the Card Status Register */ + cmd.cmdidx = MMC_CMD_SEND_EXT_CSD; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 0; + cmd.flags = 0; + + data.b.dest = ext_csd; + data.blocks = 1; + data.blocksize = 512; + data.flags = MMC_DATA_READ; + + err = sunxi_sdhci_xfer(sdhci, &cmd, &data); + if (err) + printk_error("SMHC: send ext csd failed\n"); + + return err; +} + +static int sunxi_mmc_switch(sdhci_t *sdhci, uint8_t set, uint8_t index, uint8_t value) { + mmc_t *mmc = sdhci->mmc; + + mmc_cmd_t cmd; + int timeout = 1000; + int ret; + + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8); + cmd.flags = 0; + + ret = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + if (ret) { + printk_error("SMHC: switch failed\n"); + } + + /* for re-update sample phase */ + ret = sunxi_sdhci_update_phase(sdhci); + if (ret) { + printk_error("SMHC: update clock failed after send cmd6\n"); + return ret; + } + + /* Waiting for the ready status */ + sunxi_mmc_send_status(sdhci, timeout); + + return ret; +} + +static int sunxi_mmc_change_freq(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + + char ext_csd[512]; + char cardtype; + int err; + int retry = 5; + + mmc->card_caps = 0; + + if (sunxi_mmc_host_is_spi(mmc)) + return 0; + + /* Only version 4 supports high-speed */ + if (mmc->version < MMC_VERSION_4) + return 0; + + mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; + err = mmc_send_ext_csd(mmc, ext_csd); + + if (err) { + printk_error("SMHC: get ext csd failed\n"); + return err; + } + + cardtype = ext_csd[196] & 0xff; + + /*retry for Toshiba emmc,for the first time Toshiba emmc change to HS */ + /*it will return response crc err,so retry */ + do { + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); + if (!err) { + break; + } + printk_debug("SMHC: retry mmc switch(cmd6)\n"); + } while (retry--); + + if (err) { + printk_error("SMHC: change to hs failed\n"); + return err; + } + + /* Now check to see that it worked */ + err = sunxi_mmc_send_ext_csd(sdhci, ext_csd); + + if (err) { + printk_error("SMHC: send ext csd faild\n"); + return err; + } + + /* No high-speed support */ + if (!ext_csd[185]) + return 0; + + /* High Speed is set, there are two types: 52MHz and 26MHz */ + if (cardtype & EXT_CSD_CARD_TYPE_HS) { + if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) { + printk_trace("SMHC: get ddr OK!\n"); + mmc->card_caps |= MMC_MODE_DDR_52MHz; + mmc->speed_mode = MMC_HSDDR52_DDR50; + } else + mmc->speed_mode = MMC_HSSDR52_SDR25; + mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + + } else { + mmc->card_caps |= MMC_MODE_HS; + mmc->speed_mode = MMC_DS26_SDR12; + } + + return 0; +} + +static int sunxi_mmc_sd_switch(sdhci_t *sdhci, int mode, int group, uint8_t value, uint8_t *resp) { + mmc_cmd_t cmd; + mmc_data_t data; + + /* Switch the frequency */ + cmd.cmdidx = SD_CMD_SWITCH_FUNC; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = ((uint32_t) mode << 31) | 0xffffff; + cmd.cmdarg &= ~(0xf << (group * 4)); + cmd.cmdarg |= value << (group * 4); + cmd.flags = 0; + + data.b.dest = (char *) resp; + data.blocksize = 64; + data.blocks = 1; + data.flags = MMC_DATA_READ; + + return sunxi_sdhci_xfer(sdhci, &cmd, &data); +} + +static int sunxi_mmc_sd_change_freq(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + + mmc_cmd_t cmd; + mmc_data_t data; + uint32_t scr[2]; + uint32_t switch_status[16]; + int err; + int timeout; + + mmc->card_caps = 0; + + if (sunxi_mmc_host_is_spi(mmc)) + return 0; + + /* Read the SCR to find out if this card supports higher speeds */ + cmd.cmdidx = MMC_CMD_APP_CMD; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = mmc->rca << 16; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: Send app cmd failed\n"); + return err; + } + + cmd.cmdidx = SD_CMD_APP_SEND_SCR; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 0; + cmd.flags = 0; + + timeout = 3; + +retry_scr: + data.b.dest = (char *) &scr; + data.blocksize = 8; + data.blocks = 1; + data.flags = MMC_DATA_READ; + + err = sunxi_sdhci_xfer(sdhci, &cmd, &data); + + if (err) { + if (timeout--) + goto retry_scr; + printk_error("SMHC: Send scr failed\n"); + return err; + } + + mmc->scr[0] = be32_to_cpu(scr[0]); + mmc->scr[1] = be32_to_cpu(scr[1]); + + switch ((mmc->scr[0] >> 24) & 0xf) { + case 0: + mmc->version = SD_VERSION_1_0; + break; + case 1: + mmc->version = SD_VERSION_1_10; + break; + case 2: + mmc->version = SD_VERSION_2; + break; + default: + mmc->version = SD_VERSION_1_0; + break; + } + + if (mmc->scr[0] & SD_DATA_4BIT) + mmc->card_caps |= MMC_MODE_4BIT; + + /* Version 1.0 doesn't support switching */ + if (mmc->version == SD_VERSION_1_0) + return 0; + + timeout = 4; + while (timeout--) { + err = sunxi_mmc_sd_switch(sdhci, SD_SWITCH_CHECK, 0, 1, (uint8_t *) &switch_status); + + if (err) { + printk_error("SMHC: Check high speed status faild\n"); + return err; + } + + /* The high-speed function is busy. Try again */ + if (!(be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY)) + break; + } + + /* If high-speed isn't supported, we return */ + if (!(be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)) + return 0; + + err = sunxi_mmc_sd_switch(sdhci, SD_SWITCH_SWITCH, 0, 1, (uint8_t *) &switch_status); + + if (err) { + printk_error("SMHC: switch to high speed failed\n"); + return err; + } + + err = sunxi_sdhci_update_phase(sdhci); + if (err) { + printk_error("SMHC: update clock failed after send cmd6 to switch to sd high speed mode\n"); + return err; + } + + if ((be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000) { + mmc->card_caps |= MMC_MODE_HS; + mmc->speed_mode = MMC_HSSDR52_SDR25; + } + + return 0; +} + +/* frequency bases */ +/* divided by 10 to be nice to platforms without floating point */ +static const int fbase[] = { + 10000, + 100000, + 1000000, + 10000000, +}; + +/* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice + * to platforms without floating point. + */ +static const int multipliers[] = { + 0, /* reserved */ + 10, + 12, + 13, + 15, + 20, + 25, + 30, + 35, + 40, + 45, + 50, + 55, + 60, + 70, + 80, +}; + +static void sunxi_mmc_set_clock(sdhci_t *sdhci, uint32_t clock) { + mmc_t *mmc = sdhci->mmc; + + if (clock > mmc->f_max) { + clock = mmc->f_max; + } + + if (clock < mmc->f_min) { + clock = mmc->f_min; + } + + mmc->clock = clock; + sunxi_sdhci_set_ios(sdhci); +} + +static void sunxi_mmc_set_bus_width(sdhci_t *sdhci, uint32_t width) { + sdhci->width = width; + sunxi_sdhci_set_ios(sdhci); +} + +static int sunxi_mmc_mmc_switch_ds(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + int err; + + if (mmc->speed_mode == MMC_DS26_SDR12) { + printk_trace("SMHC: set in SDR12 mode\n"); + } + + if (!(mmc->card_caps && MMC_MODE_HS)) { + printk_error("SMHC: Card not support ds mode\n"); + return -1; + } + + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_BC); + + if (err) { + printk_error("SMHC: Change to ds failed\n"); + return err; + } + + mmc->speed_mode = MMC_DS26_SDR12; + + return 0; +} + +static int sunxi_mmc_mmc_switch_hs(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + int err; + + if (mmc->speed_mode == MMC_HSSDR52_SDR25) { + printk_trace("SMHC: set in SDR25 mode\n"); + } + + if (!(mmc->card_caps && MMC_MODE_HS_52MHz)) { + printk_error("SMHC: Card not support hs mode\n"); + return -1; + } + + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS); + + if (err) { + printk_error("SMHC: Change to hs failed\n"); + return err; + } + + mmc->speed_mode = MMC_HSSDR52_SDR25; + + return 0; +} + +static int sunxi_mmc_mmc_switch_hs200(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + int err; + + if (mmc->speed_mode == MMC_HS200_SDR104) { + printk_trace("SMHC: set in SDR104 mode\n"); + } + + if (!(mmc->card_caps && MMC_MODE_HS200)) { + printk_error("SMHC: Card not support hs200 mode\n"); + return -1; + } + + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200); + + if (err) { + printk_error("SMHC: Change to hs200 failed\n"); + return err; + } + + mmc->speed_mode = MMC_HS200_SDR104; + + return 0; +} + +static int sunxi_mmc_mmc_switch_hs400(sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + int err; + + if (mmc->speed_mode == MMC_HS400) { + printk_trace("SMHC: set in HS400 mode\n"); + } + + if (!(mmc->card_caps && MMC_MODE_HS400)) { + printk_error("SMHC: Card not support hs400 mode\n"); + return -1; + } + + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400); + + if (err) { + printk_error("SMHC: Change to hs400 failed\n"); + return err; + } + + mmc->speed_mode = MMC_HS400; + + return 0; +} + +static int sunxi_mmc_mmc_switch_mdoe(sdhci_t *sdhci, uint32_t spd_mode) { + mmc_t *mmc = sdhci->mmc; + int ret = 0; + + if (sunxi_mmc_host_is_spi(mmc)) { + return 0; + } + + switch (spd_mode) { + case MMC_DS26_SDR12: + ret = sunxi_mmc_mmc_switch_ds(sdhci); + break; + case MMC_HSSDR52_SDR25: + ret = sunxi_mmc_mmc_switch_to_hs(sdhci); + break; + case MMC_HS200_SDR104: + ret = sunxi_mmc_mmc_switch_to_hs200(sdhci); + break; + case MMC_HS400: + ret = sunxi_mmc_mmc_switch_to_hs400(sdhci); + break; + default: + ret = -1; + printk_debug("SMHC: error speed mode %d\n", spd_mode); + break; + } + return ret; +} + +static int sunxi_mmc_check_bus_width(sdhci_t *sdhci, uint32_t emmc_hs_ddr, uint32_t bus_width) { + mmc_t *mmc = sdhci->mmc; + int ret = 0; + + if (bus_width == SMHC_WIDTH_1BIT) { + /* don't consider SD3.0. tSD/fSD is SD2.0, 1-bit can be support */ { + if ((emmc_hs_ddr && (!IS_SD(mmc)) && (mmc->speed_mode == MMC_HSSDR52_SDR25)) || + ((!IS_SD(mmc)) && (mmc->speed_mode == MMC_HSDDR52_DDR50)) || + ((!IS_SD(mmc)) && (mmc->speed_mode == MMC_HS200_SDR104)) || + ((!IS_SD(mmc)) && (mmc->speed_mode == MMC_HS400))) + ret = -1; + } + } else if (bus_width == SMHC_WIDTH_1BIT) { + if (!(mmc->card_caps & MMC_MODE_4BIT)) { + ret = -1; + } + } else if (bus_width == SMHC_WIDTH_8BIT) { + if (!(mmc->card_caps & MMC_MODE_8BIT)) + ret = -1; + if (IS_SD(mmc)) + ret = -1; + } else { + printk_debug("SMHC: bus width error %d\n", bus_width); + ret = -1; + } + + return ret; +} + +static int sunxi_mmc_mmc_switch_bus_width(sdhci_t *sdhci, uint32_t spd_mode, uint32_t width) { + mmc_t *mmc = sdhci->mmc; + int err = 0; + uint32_t emmc_hs_ddr = 0; + uint32_t val = 0; + + if (spd_mode == MMC_HS400) { + return 0; + } + + if (spd_mode == MMC_DS26_SDR12) { + emmc_hs_ddr = 1; + } + + err = sunxi_mmc_check_bus_width(sdhci, emmc_hs_ddr, width); + + if (err) { + printk_error("SMHC: bus witdh param error.\n"); + return -1; + } + + if (width == SMHC_WIDTH_1BIT) + val = EXT_CSD_BUS_WIDTH_1; + else if (spd_mode == MMC_HSDDR52_DDR50) { + if (width == SMHC_WIDTH_4BIT) + val = EXT_CSD_BUS_DDR_4; + else if (width == SMHC_WIDTH_8BIT) + val = EXT_CSD_BUS_DDR_8; + } else if (width == SMHC_WIDTH_4BIT) + val = EXT_CSD_BUS_WIDTH_4; + else if (width == SMHC_WIDTH_8BIT) + val = EXT_CSD_BUS_WIDTH_8; + else + val = EXT_CSD_BUS_WIDTH_1; + + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, val); + + if (err) { + printk_error("SMHC: set bus witdh error.\n"); + return -1; + } + if (spd_mode == MMC_HSDDR52_DDR50) { + mmc->speed_mode = MMC_HSDDR52_DDR50; + } + + sunxi_mmc_set_bus_width(sdhci, width); + + return err; } \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index 4673c18a..0fc28db5 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -77,31 +77,73 @@ static int sunxi_sdhci_update_clk(sdhci_t *sdhci) { } /** - * @brief Update phase for the SDHC controller. + * @brief Configure timing settings for timing mode 4 in the SDHC controller. * - * This function updates the phase for the specified SDHC controller. + * This function configures timing settings for timing mode 4 in the SDHC controller. + * It calculates the delay based on the speed mode and frequency parameters and sets + * the appropriate values in the timing data structure. Additionally, it sets the + * output delay (`odly`) based on the speed mode and returns 0 on success or -1 on failure. * - * @param sdhci Pointer to the SDHC controller structure. - * @return Returns 0 on success. + * @param sdhci Pointer to the SDHC structure. + * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_update_phase(sdhci_t *sdhci) { - sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; +static int sunxi_sdhci_get_timing_config_timing_4(sdhci_t *sdhci) { + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + uint32_t spd_md_sdly = 0, dly = 0; + int ret = 0; - // Check if timing mode is mode 1 - if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { - printk_trace("SMHC: mmc update phase.\n"); - // Call function to update clock - return sunxi_sdhci_update_clk(sdhci); + /* Check if the controller ID is MMC_CONTROLLER_2 and if timing mode and frequency ID are valid */ + if ((sdhci->id != MMC_CONTROLLER_2) || (timing_data->spd_md_id > MMC_TIMING_MODE_4) || (timing_data->freq_id > MMC_MAX_SPD_MD_NUM)) { + printk_error("SMHC: timing 4 not supported for this configuration\n"); + return -1; } - return 0; -} + /* Calculate delay based on speed mode and frequency */ + dly = ((spd_md_sdly >> ((timing_data->freq_id % 4) * 8)) & 0xff); + if ((dly == 0xff) || (dly == 0)) { + if (timing_data->spd_md_id == MMC_DS26_SDR12) { + if (timing_data->freq_id <= MMC_CLK_25M) { + dly = 0; + } else { + printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data->freq_id, timing_data->spd_md_id); + ret = -1; + } + } else if (timing_data->spd_md_id == MMC_HSSDR52_SDR25) { + if (timing_data->freq_id <= MMC_CLK_25M) { + dly = 0; + } else if (timing_data->freq_id == MMC_CLK_50M) { + dly = 15; + } else { + printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data->freq_id, timing_data->spd_md_id); + ret = -1; + } + } else if (timing_data->spd_md_id == MMC_HSDDR52_DDR50) { + if (timing_data->freq_id <= MMC_CLK_25M) { + dly = 0; + } else { + printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data->freq_id, timing_data->spd_md_id); + ret = -1; + } + } else { + printk_error("SMHC: wrong speed mode %d\n", timing_data->spd_md_id); + ret = -1; + } + } + /* Set output delay based on speed mode */ + if (timing_data->spd_md_id == MMC_HSDDR52_DDR50) { + timing_data->odly = 1; + } else { + timing_data->odly = 0; + } -static int sunxi_sdhci_get_timing_config_timing_4(sdhci_t *sdhci) { - /* TODO: eMMC Timing set */ + /* Set the calculated delay */ + timing_data->sdly = dly; + + return ret; } + /** * @brief Get timing configuration for the SDHC controller. * @@ -120,6 +162,9 @@ static int sunxi_sdhci_get_timing_config(sdhci_t *sdhci) { if ((sdhci->id == 2) && mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { /* When using eMMC and SMHC2, config it as timing 4 */ ret = sunxi_sdhci_get_timing_config_timing_4(sdhci); + if (ret) { + printk_error("SMHC: Config timing TM4 fail\n"); + } } else if ((sdhci->id == 0) && (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1)) { // Check timing data and adjust configuration if necessary if ((timing_data->spd_md_id <= MMC_HSSDR52_SDR25) && (timing_data->freq_id <= MMC_CLK_50M)) { @@ -156,9 +201,9 @@ static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { // Determine the clock source based on the requested frequency if (clk_hz <= 4000000) { - src = 0; // SCLK = 24000000 OSC CLK + src = 0;// SCLK = 24000000 OSC CLK } else { - src = 2; // SCLK = AHB PLL + src = 2;// SCLK = AHB PLL } // Set the clock divider values based on the requested frequency @@ -178,7 +223,7 @@ static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { m = 2; break; case 200000000: - src = 1; // PERI0_800M + src = 1;// PERI0_800M n = 0; m = 1; break; @@ -506,7 +551,7 @@ static int sunxi_sdhci_config_clock(sdhci_t *sdhci, uint32_t clk) { return -1; } - return 0; // Success + return 0;// Success } /** @@ -529,9 +574,9 @@ static void sunxi_sdhci_ddr_mode_set(sdhci_t *sdhci, bool status) { // Set or clear DDR mode bit based on status if (status) { - reg_val |= SMHC_GCTRL_DDR_MODE; // Set DDR mode bit + reg_val |= SMHC_GCTRL_DDR_MODE;// Set DDR mode bit } else { - reg_val &= ~SMHC_GCTRL_DDR_MODE; // Clear DDR mode bit + reg_val &= ~SMHC_GCTRL_DDR_MODE;// Clear DDR mode bit } // Write updated value back to gctrl register @@ -567,8 +612,8 @@ static void sunxi_sdhci_hs400_mode_set(sdhci_t *sdhci, bool status) { reg_csdc_val = mmc_host->reg->csdc; // Clear existing bits related to HS400 mode - reg_dsbd_val &= ~(0x1 << 31); // Clear HS400EN bit - reg_csdc_val &= ~0xf; // Clear HSSDR bit and HS400DS bit + reg_dsbd_val &= ~(0x1 << 31);// Clear HS400EN bit + reg_csdc_val &= ~0xf; // Clear HSSDR bit and HS400DS bit // Configure HS400 mode based on status if (status) { @@ -659,39 +704,37 @@ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { // Determine the buffer based on the direction of data transfer if (data->flags * MMC_DATA_READ) { - buff = (uint32_t *) data->b.dest; // Destination buffer for read operation + buff = (uint32_t *) data->b.dest;// Destination buffer for read operation } else { - buff = (uint32_t *) data->b.src; // Source buffer for write operation + buff = (uint32_t *) data->b.src;// Source buffer for write operation } // Iterate over blocks of data to be transferred for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { // Wait until FIFO is empty for read operation, or full for write operation - while (((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : - (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) && (time_us() < timeout)) { + while (((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) && (time_us() < timeout)) { } // Check for timeout - if ((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : - (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) { + if ((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) { if (time_us() >= timeout) { - printk_error("SMHC: transfer %s by CPU failed, timeout\n", - (data->flags * MMC_DATA_READ) ? "read" : "write"); - return -1; // Return failure indication + printk_error("SMHC: transfer %s by CPU failed, timeout\n", + (data->flags * MMC_DATA_READ) ? "read" : "write"); + return -1;// Return failure indication } } // Perform read or write operation based on the direction of data transfer if (data->flags * MMC_DATA_READ) { - buff[i] = readl(mmc_host->database); // Read data from FIFO to buffer + buff[i] = readl(mmc_host->database);// Read data from FIFO to buffer } else { - writel(buff[i], mmc_host->database); // Write data from buffer to FIFO + writel(buff[i], mmc_host->database);// Write data from buffer to FIFO } - timeout = time_us() + SMHC_TIMEOUT; // Update timeout for next iteration + timeout = time_us() + SMHC_TIMEOUT;// Update timeout for next iteration } - return 0; // Return success indication + return 0;// Return success indication } /** @@ -1158,6 +1201,27 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { return 0; } +/** + * @brief Update phase for the SDHC controller. + * + * This function updates the phase for the specified SDHC controller. + * + * @param sdhci Pointer to the SDHC controller structure. + * @return Returns 0 on success. + */ +int sunxi_sdhci_update_phase(sdhci_t *sdhci) { + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + // Check if timing mode is mode 1 + if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { + printk_trace("SMHC: mmc update phase.\n"); + // Call function to update clock + return sunxi_sdhci_update_clk(sdhci); + } + + return 0; +} + /** * @brief Initialize the SDHC controller. * From 957a032274e549e6dae67444cec570b9b5a58899 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Mon, 3 Jun 2024 09:26:36 +0800 Subject: [PATCH 05/12] [driver] tmp sync for data --- include/drivers/mmc/sys-mmc.h | 2 -- src/drivers/mmc/sys-mmc.c | 24 +++++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h index f905e805..2f0094f1 100644 --- a/include/drivers/mmc/sys-mmc.h +++ b/include/drivers/mmc/sys-mmc.h @@ -49,8 +49,6 @@ enum { #define SD_DATA_4BIT 0x00040000 -#define IS_SD(x) (x->version & SD_VERSION_SD) - #define MMC_DATA_READ (1U << 0) #define MMC_DATA_WRITE (1U << 1) diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index e4bcd4b6..617e77a4 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -18,7 +18,11 @@ #include static inline int sunxi_mmc_host_is_spi(mmc_t *mmc) { - return (mmc->host_caps & MMC_MODE_SPI); + return mmc->host_caps & MMC_MODE_SPI; +} + +static inline int sunxi_mmc_device_is_sd(mmc_t *mmc) { + return mmc->version & SD_VERSION_SD; } static int sunxi_mmc_send_status(sdhci_t *sdhci, uint32_t timeout) { @@ -800,4 +804,22 @@ static int sunxi_mmc_mmc_switch_bus_width(sdhci_t *sdhci, uint32_t spd_mode, uin sunxi_mmc_set_bus_width(sdhci, width); return err; +} + +static int sunxi_mmc_mmc_switch_bus_mode(sdhci_t *sdhci, uint32_t spd_mode, uint32_t width) { + mmc_t *mmc = sdhci->mmc; + int err = 0; + int spd_mode_backup = 0; + + if (sunxi_mmc_device_is_sd(mmc)) { + return 0; + } + + if (spd_md == MMC_HSDDR52_DDR50) { + spd_mode_backup = MMC_HSSDR52_SDR25; + } else { + spd_mode_backup = spd_mode; + } + + err = } \ No newline at end of file From 57f3906bf730b58bf392411b0a47976bbf646bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=9A=E6=9C=A8=20=E9=89=89?= Date: Mon, 3 Jun 2024 09:29:14 +0800 Subject: [PATCH 06/12] [driver] fix read flag in sys-sdhci.c --- src/drivers/mmc/sys-sdhci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index 0fc28db5..a058a105 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -703,7 +703,7 @@ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { uint32_t *buff; // Determine the buffer based on the direction of data transfer - if (data->flags * MMC_DATA_READ) { + if (data->flags & MMC_DATA_READ) { buff = (uint32_t *) data->b.dest;// Destination buffer for read operation } else { buff = (uint32_t *) data->b.src;// Source buffer for write operation @@ -712,11 +712,11 @@ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { // Iterate over blocks of data to be transferred for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { // Wait until FIFO is empty for read operation, or full for write operation - while (((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) && (time_us() < timeout)) { + while (((data->flags & MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) && (time_us() < timeout)) { } // Check for timeout - if ((data->flags * MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) { + if ((data->flags & MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) { if (time_us() >= timeout) { printk_error("SMHC: transfer %s by CPU failed, timeout\n", (data->flags * MMC_DATA_READ) ? "read" : "write"); @@ -725,7 +725,7 @@ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { } // Perform read or write operation based on the direction of data transfer - if (data->flags * MMC_DATA_READ) { + if (data->flags & MMC_DATA_READ) { buff[i] = readl(mmc_host->database);// Read data from FIFO to buffer } else { writel(buff[i], mmc_host->database);// Write data from buffer to FIFO From b3e5bae20783d36a44dc7edea91dfbc4e464cfb9 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Tue, 4 Jun 2024 22:01:09 +0800 Subject: [PATCH 07/12] [driver] add basic mmc driver WIP 2/3 --- board/avaota-a1/board.c | 60 +- board/avaota-a1/extlinux_boot/main.c | 14 +- board/avaota-a1/load_e906/main.c | 2 +- board/avaota-a1/smhc2_test/main.c | 2 +- board/avaota-a1/smhc_test/main.c | 5 +- board/avaota-a1/syter_boot/main.c | 2 +- board/avaota-a1/syter_boot_uboot/main.c | 2 +- include/drivers/mmc/sys-mmc.h | 21 +- include/drivers/mmc/sys-sdcard.h | 2 +- include/drivers/mmc/sys-sdhci.h | 52 +- src/drivers/mmc/sys-mmc.c | 1184 ++++++++++++++++++++--- src/drivers/mmc/sys-sdcard.c | 10 +- src/drivers/mmc/sys-sdhci.c | 406 ++++---- src/drivers/sys-spi.c | 2 + 14 files changed, 1422 insertions(+), 342 deletions(-) diff --git a/board/avaota-a1/board.c b/board/avaota-a1/board.c index ed186501..8e39aa28 100644 --- a/board/avaota-a1/board.c +++ b/board/avaota-a1/board.c @@ -12,10 +12,11 @@ #include +#include + #include #include #include -#include #include #include #include @@ -50,10 +51,63 @@ sunxi_spi_t sunxi_spi0 = { .gpio_hold = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX4}, }; -sdhci_t sdhci0 = { - +sunxi_sdhci_t sdhci0 = { + .name = "sdhci0", + .id = MMC_CONTROLLER_0, + .reg_base = SUNXI_SMHC0_BASE, + .clk_ctrl_base = CCU_BASE + CCU_SMHC_BGR_REG, + .clk_base = CCU_BASE + CCU_SMHC0_CLK_REG, + .sdhci_mmc_type = MMC_TYPE_SD, + .max_clk = 75 * 1000 * 1000, + .pinctrl = { + .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTF, 1), GPIO_PERIPH_MUX2}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, + }, + .timing_data = { + .freq_id = MMC_CLK_25M, + .odly = 0, + .sdly = 0, + .spd_md_id = MMC_DS26_SDR12, + .auto_timing = TRUE, + }, +}; + +sunxi_sdhci_t sdhci2 = { + .name = "sdhci2", + .id = MMC_CONTROLLER_2, + .reg_base = SUNXI_SMHC2_BASE, + .clk_ctrl_base = CCU_BASE + CCU_SMHC_BGR_REG, + .clk_base = CCU_BASE + CCU_SMHC2_CLK_REG, + .sdhci_mmc_type = MMC_TYPE_EMMC, + .max_clk = 200 * 1000 * 1000, + .pinctrl = { + .gpio_clk = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX3}, + .gpio_cmd = {GPIO_PIN(GPIO_PORTC, 6), GPIO_PERIPH_MUX3}, + .gpio_d0 = {GPIO_PIN(GPIO_PORTC, 10), GPIO_PERIPH_MUX3}, + .gpio_d1 = {GPIO_PIN(GPIO_PORTC, 13), GPIO_PERIPH_MUX3}, + .gpio_d2 = {GPIO_PIN(GPIO_PORTC, 15), GPIO_PERIPH_MUX3}, + .gpio_d3 = {GPIO_PIN(GPIO_PORTC, 8), GPIO_PERIPH_MUX3}, + .gpio_d4 = {GPIO_PIN(GPIO_PORTC, 9), GPIO_PERIPH_MUX3}, + .gpio_d5 = {GPIO_PIN(GPIO_PORTC, 11), GPIO_PERIPH_MUX3}, + .gpio_d6 = {GPIO_PIN(GPIO_PORTC, 14), GPIO_PERIPH_MUX3}, + .gpio_d7 = {GPIO_PIN(GPIO_PORTC, 16), GPIO_PERIPH_MUX3}, + .gpio_ds = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX3}, + .gpio_rst = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX3}, + }, + .timing_data = { + .freq_id = MMC_CLK_25M, + .odly = 0, + .sdly = 0, + .spd_md_id = MMC_DS26_SDR12, + .auto_timing = TRUE, + }, }; + sunxi_i2c_t i2c_pmu = { .base = SUNXI_R_TWI0_BASE, .id = SUNXI_R_I2C0, diff --git a/board/avaota-a1/extlinux_boot/main.c b/board/avaota-a1/extlinux_boot/main.c index afaa51b1..ca0a8684 100644 --- a/board/avaota-a1/extlinux_boot/main.c +++ b/board/avaota-a1/extlinux_boot/main.c @@ -16,11 +16,11 @@ #include #include +#include #include #include #include #include -#include #include #include @@ -62,8 +62,8 @@ extern sunxi_serial_t uart_dbg; extern sunxi_i2c_t i2c_pmu; -extern sdhci_t sdhci0; -extern sdhci_t sdhci2; +extern sunxi_sdhci_t sdhci0; +extern sunxi_sdhci_t sdhci2; extern uint32_t dram_para[32]; @@ -760,14 +760,16 @@ int main(void) { strcpy(image.splash_filename, CONFIG_SPLASH_FILENAME); /* Initialize the SD host controller. */ - if (sunxi_sdhci_init(&sdhci0) != 0) { - printk_error("SMHC: %s controller init failed\n", sdhci0.name); + if (sunxi_sdhci_init(&sdhci2) != 0) { + printk_error("SMHC: %s controller init failed\n", sdhci2.name); LCD_ShowString(0, 92, "SMHC: SDC0 controller init failed", SPI_LCD_COLOR_GREEN, SPI_LCD_COLOR_BLACK, 12); goto _fail; } else { - printk_info("SMHC: %s controller initialized\n", sdhci0.name); + printk_info("SMHC: %s controller initialized\n", sdhci2.name); } + sunxi_mmc_init(&sdhci2); + /* Initialize the SD card and check if initialization is successful. */ if (sdmmc_init(&card0, &sdhci0) != 0) { printk_warning("SMHC: SDC0 init failed, init SDC2...\n"); diff --git a/board/avaota-a1/load_e906/main.c b/board/avaota-a1/load_e906/main.c index 5d437afb..da58e4c1 100644 --- a/board/avaota-a1/load_e906/main.c +++ b/board/avaota-a1/load_e906/main.c @@ -50,7 +50,7 @@ extern sunxi_serial_t uart_dbg; extern sunxi_i2c_t i2c_pmu; -extern sdhci_t sdhci0; +extern sunxi_sdhci_t sdhci0; extern void enable_sram_a3(); extern void rtc_set_vccio_det_spare(); diff --git a/board/avaota-a1/smhc2_test/main.c b/board/avaota-a1/smhc2_test/main.c index cdee2592..e2031f53 100644 --- a/board/avaota-a1/smhc2_test/main.c +++ b/board/avaota-a1/smhc2_test/main.c @@ -29,7 +29,7 @@ extern sunxi_serial_t uart_dbg; extern sunxi_i2c_t i2c_pmu; -extern sdhci_t sdhci2; +extern sunxi_sdhci_t sdhci2; msh_declare_command(speedtest); msh_define_help(speedtest, "Do speed test", "Usage: speedtest\n"); diff --git a/board/avaota-a1/smhc_test/main.c b/board/avaota-a1/smhc_test/main.c index 6db26b7c..7a08d290 100644 --- a/board/avaota-a1/smhc_test/main.c +++ b/board/avaota-a1/smhc_test/main.c @@ -25,6 +25,9 @@ extern sunxi_serial_t uart_dbg; +extern sunxi_sdhci_t sdhci0; +extern sunxi_sdhci_t sdhci2; + extern sunxi_i2c_t i2c_pmu; #define CONFIG_SDMMC_SPEED_TEST_SIZE 1024// (unit: 512B sectors) @@ -61,7 +64,7 @@ int cmd_write(int argc, const char **argv) { uint32_t test_time; start = time_ms(); - sdmmc_blk_write(&card0, (uint8_t *) (0x07380000), 0, 1024); + //sdmmc_blk_write(&card0, (uint8_t *) (0x07380000), 0, 1024); test_time = time_ms() - start; printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n", (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, diff --git a/board/avaota-a1/syter_boot/main.c b/board/avaota-a1/syter_boot/main.c index 57e20583..4bdd11a7 100644 --- a/board/avaota-a1/syter_boot/main.c +++ b/board/avaota-a1/syter_boot/main.c @@ -58,7 +58,7 @@ extern sunxi_serial_t uart_dbg; extern sunxi_i2c_t i2c_pmu; -extern sdhci_t sdhci0; +extern sunxi_sdhci_t sdhci0; extern void enable_sram_a3(); extern void rtc_set_vccio_det_spare(); diff --git a/board/avaota-a1/syter_boot_uboot/main.c b/board/avaota-a1/syter_boot_uboot/main.c index 1d02a459..28fe20ce 100644 --- a/board/avaota-a1/syter_boot_uboot/main.c +++ b/board/avaota-a1/syter_boot_uboot/main.c @@ -55,7 +55,7 @@ extern sunxi_serial_t uart_dbg; extern sunxi_i2c_t i2c_pmu; -extern sdhci_t sdhci0; +extern sunxi_sdhci_t sdhci0; extern void enable_sram_a3(); extern void rtc_set_vccio_det_spare(); diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h index 2f0094f1..92772ab8 100644 --- a/include/drivers/mmc/sys-mmc.h +++ b/include/drivers/mmc/sys-mmc.h @@ -59,8 +59,6 @@ enum { #define COMM_ERR -18 /* Communications Error */ #define TIMEOUT -19 -#define MMC_CMD_CMDVAL_MASK 0x80000000 - #define MMC_CMD_GO_IDLE_STATE 0 #define MMC_CMD_SEND_OP_COND 1 #define MMC_CMD_ALL_SEND_CID 2 @@ -144,7 +142,6 @@ enum { /* * EXT_CSD fields */ - #define EXT_CSD_PART_CONF 179 /* R/W */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ #define EXT_CSD_HS_TIMING 185 /* R/W */ @@ -155,7 +152,6 @@ enum { /* * EXT_CSD field definitions */ - #define EXT_CSD_CMD_SET_NORMAL (1 << 0) #define EXT_CSD_CMD_SET_SECURE (1 << 1) #define EXT_CSD_CMD_SET_CPSECURE (1 << 2) @@ -272,7 +268,7 @@ typedef struct mmc_data { typedef struct mmc { uint32_t voltages; uint32_t version; - uint32_t has_init; + uint32_t bus_width; uint32_t f_min; uint32_t f_max; uint32_t f_max_ddr; @@ -300,6 +296,21 @@ typedef struct mmc { uint32_t speed_mode; } mmc_t; + +/** + * @brief Initializes the SD/MMC host controller and attached card. + * + * This function initializes the specified SD/MMC host controller and the + * attached SD/MMC card. It initializes the host controller core, sets the + * bus width and clock speed, resets the card, and initializes the card + * based on its type (SD or eMMC). Finally, it probes the card to retrieve + * card-specific data. + * + * @param sdhci_hdl Pointer to the SD/MMC host controller structure. + * @return 0 on success, or an error code if an error occurred during initialization. + */ +int sunxi_mmc_init(void *sdhci_hdl); + #ifdef __cplusplus } #endif// __cplusplus diff --git a/include/drivers/mmc/sys-sdcard.h b/include/drivers/mmc/sys-sdcard.h index 8a81c8c9..9264eb1d 100644 --- a/include/drivers/mmc/sys-sdcard.h +++ b/include/drivers/mmc/sys-sdcard.h @@ -19,7 +19,7 @@ extern "C" { typedef struct { mmc_t card; - sdhci_t *hci; + sunxi_sdhci_t *hci; uint8_t buf[512]; bool online; } sdmmc_pdata_t; diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index 3d9c0d4c..504d4263 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -27,9 +27,9 @@ extern "C" { #define MMC_REG_FIFO_OS (0x200) #define SMHC_TIMEOUT 0xfffff -#define SMHC_DMA_TIMEOUT 0xffffff -#define SMHC_WAITBUSY_TIMEOUT 0x4ffffff -#define SMHC_DATA_TIMEOUT 0xffffff +#define SMHC_DMA_TIMEOUT 0xfffff +#define SMHC_WAITBUSY_TIMEOUT 0xfffff +#define SMHC_DATA_TIMEOUT 0xfffff #define SMHC_RESP_TIMEOUT 0xff enum { @@ -64,13 +64,14 @@ typedef struct sunxi_sdhci_host { uint32_t hclkrst; uint32_t hclkbase; uint32_t mclkbase; - uint32_t database; uint32_t commreg; - uint32_t fatal_err; - sunxi_sdhci_desc_t sdhci_desc[32]; - uint32_t timing_mode; + uint8_t fatal_err; + uint8_t timing_mode; uint32_t mod_clk; uint32_t clock; + + /* DMA DESC */ + sunxi_sdhci_desc_t sdhci_desc[32]; } sunxi_sdhci_host_t; typedef struct sunxi_sdhci_pinctrl { @@ -93,9 +94,10 @@ typedef struct sunxi_sdhci_timing { uint32_t sdly; uint32_t spd_md_id; uint32_t freq_id; + uint8_t auto_timing; } sunxi_sdhci_timing_t; -typedef struct sdhci { +typedef struct sunxi_sdhci { char *name; uint32_t reg_base; uint32_t id; @@ -103,12 +105,16 @@ typedef struct sdhci { uint32_t clk_ctrl_base; uint32_t clk_base; uint32_t max_clk; + sunxi_sdhci_type_t sdhci_mmc_type; + + /* Pinctrl info */ + sunxi_sdhci_pinctrl_t pinctrl; + + /* Private data */ mmc_t *mmc; - sunxi_sdhci_type_t type; sunxi_sdhci_host_t *mmc_host; - sunxi_sdhci_pinctrl_t *pinctrl; - sunxi_sdhci_timing_t *timing_data; -} sdhci_t; + sunxi_sdhci_timing_t timing_data; +} sunxi_sdhci_t; /** * @brief Initialize the SDHC controller. @@ -122,7 +128,7 @@ typedef struct sdhci { * @param sdhci Pointer to the SDHC structure. * @return Returns 0 on success, -1 on failure. */ -int sunxi_sdhci_init(sdhci_t *sdhci); +int sunxi_sdhci_init(sunxi_sdhci_t *sdhci); /** * @brief Initialize the core functionality of the SDHC controller. @@ -134,7 +140,7 @@ int sunxi_sdhci_init(sdhci_t *sdhci); * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success, -1 on failure. */ -int sunxi_sdhci_core_init(sdhci_t *sdhci); +int sunxi_sdhci_core_init(sunxi_sdhci_t *sdhci); /** * @brief Set the I/O settings for the SDHC controller. @@ -145,7 +151,7 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci); * @param sdhci Pointer to the SDHC controller structure. * @return void */ -void sunxi_sdhci_set_ios(sdhci_t *sdhci); +void sunxi_sdhci_set_ios(sunxi_sdhci_t *sdhci); /** * @brief Update phase for the SDHC controller. @@ -155,7 +161,7 @@ void sunxi_sdhci_set_ios(sdhci_t *sdhci); * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success. */ -int sunxi_sdhci_update_phase(sdhci_t *sdhci); +int sunxi_sdhci_update_phase(sunxi_sdhci_t *sdhci); /** * @brief Perform a data transfer operation on the SDHC controller. @@ -169,7 +175,19 @@ int sunxi_sdhci_update_phase(sdhci_t *sdhci); * @param data Pointer to the MMC data structure. * @return Returns 0 on success, -1 on failure. */ -int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data); +int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data); + +/** + * @brief Dump the contents of the SDHCI registers. + * + * This function dumps the contents of the SDHCI registers for a given SD card host controller. + * + * @param sdhci A pointer to the structure representing the SD card host controller. + * @return void + * + * @note This function is useful for debugging and analyzing the state of the SD card controller. + */ +void sunxi_sdhci_dump_reg(sunxi_sdhci_t *sdhci); #ifdef __cplusplus } diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index 617e77a4..6bdef862 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -17,15 +17,164 @@ #include #include +/** + * @brief Extracts a specified bit field from a response buffer. + * + * This macro extracts a specified bit field from a response buffer or an array of integers. + * It calculates the offset, shift amount, and bitmask based on the starting position and size of the field, + * then performs the extraction and applies the bitmask to isolate the desired bits. + * + * @param resp The response buffer or array of integers. + * @param start The starting bit position of the field within the response buffer. + * @param size The size (in bits) of the field to be extracted. + * @return The extracted bit field. + */ +#define UNSTUFF_BITS(resp, start, size) \ + ({ \ + const int __size = size; \ + const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \ + const int __off = 3 - ((start) / 32); \ + const int __shft = (start) &31; \ + uint32_t __res; \ + \ + __res = resp[__off] >> __shft; \ + if (__size + __shft > 32) \ + __res |= resp[__off - 1] << ((32 - __shft) % 32); \ + __res &__mask; \ + }) + + +/** + * @brief Checks if the MMC host operates in SPI mode. + * + * This function checks if the MMC host operates in SPI mode based on its capabilities. + * + * @param mmc Pointer to the MMC structure. + * @return 1 if the host operates in SPI mode, 0 otherwise. + */ static inline int sunxi_mmc_host_is_spi(mmc_t *mmc) { return mmc->host_caps & MMC_MODE_SPI; } +/** + * @brief Checks if the MMC device is an SD card. + * + * This function checks if the MMC device is an SD card based on its version information. + * + * @param mmc Pointer to the MMC structure. + * @return 1 if the device is an SD card, 0 otherwise. + */ static inline int sunxi_mmc_device_is_sd(mmc_t *mmc) { return mmc->version & SD_VERSION_SD; } -static int sunxi_mmc_send_status(sdhci_t *sdhci, uint32_t timeout) { +/** + * @brief Extracts the Manufacturer ID from the MMC card. + * + * This function extracts the Manufacturer ID from the MMC card's CID (Card Identification Data) register. + * The extraction is performed based on the MMC version and CID structure. + * + * @param card Pointer to the MMC card structure. + * @return The Manufacturer ID. + */ +static inline uint32_t extract_mid(mmc_t *card) { + if ((card->version & MMC_VERSION_MMC) && (card->version <= MMC_VERSION_1_4)) + return UNSTUFF_BITS(card->cid, 104, 24); + else + return UNSTUFF_BITS(card->cid, 120, 8); +} + +/** + * @brief Extracts the OEM/Application ID from the MMC card. + * + * This function extracts the OEM/Application ID from the MMC card's CID (Card Identification Data) register. + * + * @param card Pointer to the MMC card structure. + * @return The OEM/Application ID. + */ +static inline uint32_t extract_oid(mmc_t *card) { + return (card->cid[0] >> 8) & 0xffff; +} + +/** + * @brief Extracts the Product Revision from the MMC card. + * + * This function extracts the Product Revision from the MMC card's CID (Card Identification Data) register. + * + * @param card Pointer to the MMC card structure. + * @return The Product Revision. + */ +static inline uint32_t extract_prv(mmc_t *card) { + return (card->cid[2] >> 24); +} + +/** + * @brief Extracts the Product Serial Number (PSN) from the MMC card. + * + * This function extracts the Product Serial Number (PSN) from the MMC card based on its version and CSD/CID structure. + * + * @param card Pointer to the MMC card structure. + * @return The Product Serial Number. + */ +static inline uint32_t extract_psn(mmc_t *card) { + if (card->version & SD_VERSION_SD) { + return UNSTUFF_BITS(card->csd, 24, 32); + } else { + if (card->version > MMC_VERSION_1_4) + return UNSTUFF_BITS(card->cid, 16, 32); + else + return UNSTUFF_BITS(card->cid, 16, 24); + } +} + +/** + * @brief Extracts the manufacturing month from the MMC card. + * + * This function extracts the manufacturing month from the MMC card's CID (Card Identification Data) register. + * + * @param card Pointer to the MMC card structure. + * @return The manufacturing month. + */ +static inline uint32_t extract_month(mmc_t *card) { + if (card->version & SD_VERSION_SD) + return UNSTUFF_BITS(card->cid, 8, 4); + else + return UNSTUFF_BITS(card->cid, 12, 4); +} + +/** + * @brief Extracts the manufacturing year from the MMC card. + * + * This function extracts the manufacturing year from the MMC card's CID (Card Identification Data) register. + * + * @param card Pointer to the MMC card structure. + * @return The manufacturing year. + */ +static inline uint32_t extract_year(mmc_t *card) { + uint32_t year; + + if (card->version & SD_VERSION_SD) + year = UNSTUFF_BITS(card->cid, 12, 8) + 2000; + else if (card->version < MMC_VERSION_4_41) + return UNSTUFF_BITS(card->cid, 8, 4) + 1997; + else { + year = UNSTUFF_BITS(card->cid, 8, 4) + 1997; + if (year < 2010) + year += 16; + } + return year; +} +/** + * @brief Sends status command to the SD/MMC card and waits for the card to be ready. + * + * This function sends the status command to the SD/MMC card and waits for the card to be ready for data transfer. + * It retries sending the command until the card is ready or until the timeout expires. + * + * @param sdhci Pointer to the SDHCI controller structure. + * @param timeout Timeout value in milliseconds. + * @return 0 on success, error code otherwise. + */ +static int sunxi_mmc_send_status(sunxi_sdhci_t *sdhci, uint32_t timeout) { mmc_t *mmc = sdhci->mmc; int err = 0; @@ -57,10 +206,19 @@ static int sunxi_mmc_send_status(sdhci_t *sdhci, uint32_t timeout) { return 0; } -static int sunxi_mmc_set_block_len(sdhci_t *sdhci, uint32_t len) { +/** + * @brief Sets the block length for data transfer on the SD/MMC card. + * + * This function sets the block length for data transfer on the SD/MMC card, except in DDR mode. + * + * @param sdhci Pointer to the SDHCI controller structure. + * @param len Block length to be set. + * @return 0 on success, error code otherwise. + */ +static int sunxi_mmc_set_block_len(sunxi_sdhci_t *sdhci, uint32_t len) { mmc_t *mmc = sdhci->mmc; mmc_cmd_t cmd; - /* don't set blocklen at ddr mode */ + /* Don't set block length in DDR mode */ if ((mmc->speed_mode == MMC_HSDDR52_DDR50) || (mmc->speed_mode == MMC_HS400)) { return 0; } @@ -72,7 +230,19 @@ static int sunxi_mmc_set_block_len(sdhci_t *sdhci, uint32_t len) { return sunxi_sdhci_xfer(sdhci, &cmd, NULL); } -static uint64_t sunxi_mmc_read_blocks(sdhci_t *sdhci, void *dst, uint64_t start, uint64_t blkcnt) { +/** + * @brief Reads blocks from the SD/MMC card. + * + * This function reads blocks from the SD/MMC card starting from the specified block address. + * It supports reading multiple blocks and handles high capacity cards appropriately. + * + * @param sdhci Pointer to the SDHCI controller structure. + * @param dst Pointer to the destination buffer where the data will be stored. + * @param start Start block address from where to read the data. + * @param blkcnt Number of blocks to read. + * @return Number of blocks read on success, 0 otherwise. + */ +static uint64_t sunxi_mmc_read_blocks(sunxi_sdhci_t *sdhci, void *dst, uint64_t start, uint64_t blkcnt) { mmc_t *mmc = sdhci->mmc; mmc_cmd_t cmd; @@ -99,7 +269,7 @@ static uint64_t sunxi_mmc_read_blocks(sdhci_t *sdhci, void *dst, uint64_t start, data.flags = MMC_DATA_READ; if (sunxi_sdhci_xfer(sdhci, &cmd, &data)) { - printk_error("SMHC: read blcok failed\n"); + printk_error("SMHC: read block failed\n"); return 0; } @@ -109,7 +279,7 @@ static uint64_t sunxi_mmc_read_blocks(sdhci_t *sdhci, void *dst, uint64_t start, cmd.resp_type = MMC_RSP_R1b; cmd.flags = 0; if (sunxi_sdhci_xfer(sdhci, &cmd, NULL)) { - printk_error("SMHC: fail to send stop cmd\n"); + printk_error("SMHC: failed to send stop command\n"); return 0; } @@ -120,7 +290,15 @@ static uint64_t sunxi_mmc_read_blocks(sdhci_t *sdhci, void *dst, uint64_t start, return blkcnt; } -static int sunxi_mmc_go_idle(sdhci_t *sdhci) { +/** + * @brief Sends the SD/MMC card to idle state. + * + * This function sends the SD/MMC card to the idle state, preparing it for further commands. + * + * @param sdhci Pointer to the SDHCI controller structure. + * @return 0 on success, error code otherwise. + */ +static int sunxi_mmc_go_idle(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; mmc_cmd_t cmd; @@ -140,20 +318,32 @@ static int sunxi_mmc_go_idle(sdhci_t *sdhci) { mdelay(2); return 0; } +/** + * @brief Sends SD card initialization sequence and waits for it to become ready. + * + * This function sends the SD card initialization sequence, which includes sending + * application-specific commands and checking the card's response until it becomes ready. + * It also updates the MMC structure with relevant information such as the card version, + * OCR value, and high capacity flag. + * + * @param sdhci Pointer to the SDHCI controller structure. + * @return 0 on success, error code otherwise. + */ +static int sunxi_mmc_sd_send_op_cond(sunxi_sdhci_t *sdhci) { + int timeout = 1000;// Timeout value for waiting on card initialization + int err; // Error code variable -static int sunxi_mmc_sd_send_op_cond(sdhci_t *sdhci) { - int timeout = 1000; - int err; - - mmc_t *mmc = sdhci->mmc; - mmc_cmd_t cmd; + mmc_t *mmc = sdhci->mmc;// MMC structure pointer + mmc_cmd_t cmd; // MMC command structure do { + // Send application-specific command cmd.cmdidx = MMC_CMD_APP_CMD; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = 0; cmd.flags = 0; + // Transfer the command and check for errors err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); if (err) { @@ -161,21 +351,17 @@ static int sunxi_mmc_sd_send_op_cond(sdhci_t *sdhci) { return err; } + // Send SD card operation condition command cmd.cmdidx = SD_CMD_APP_SEND_OP_COND; cmd.resp_type = MMC_RSP_R3; - /* - * Most cards do not answer if some reserved bits - * in the ocr are set. However, Some controller - * can set bit 7 (reserved for low voltages), but - * how to manage low voltages SD card is not yet - * specified. - */ + // Set command arguments based on card type and version cmd.cmdarg = sunxi_mmc_host_is_spi(mmc) ? 0 : (mmc->voltages & 0xff8000); if (mmc->version == SD_VERSION_2) cmd.cmdarg |= OCR_HCS; + // Transfer the command and check for errors err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); if (err) { @@ -183,23 +369,27 @@ static int sunxi_mmc_sd_send_op_cond(sdhci_t *sdhci) { return err; } - mdelay(1); - } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--); + mdelay(1);// Delay for stability + + } while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);// Wait for card initialization and decrement timeout if (timeout <= 0) { printk_error("SMHC: wait card init failed\n"); return UNUSABLE_ERR; } + // Update MMC structure with card information if (mmc->version != SD_VERSION_2) mmc->version = SD_VERSION_1_0; - if (mmc_host_is_spi(mmc)) { /* read OCR for spi */ + if (sunxi_mmc_host_is_spi(mmc)) { + // For SPI, read OCR value cmd.cmdidx = MMC_CMD_SPI_READ_OCR; cmd.resp_type = MMC_RSP_R3; cmd.cmdarg = 0; cmd.flags = 0; + // Transfer the command and check for errors err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); if (err) { @@ -208,65 +398,83 @@ static int sunxi_mmc_sd_send_op_cond(sdhci_t *sdhci) { } } + // Update MMC structure with OCR value, high capacity flag, and relative card address mmc->ocr = cmd.response[0]; - mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 0; - return 0; + return 0;// Return success } -static int sunxi_mmc_mmc_send_op_cond(sdhci_t *sdhci) { - int timeout = 1000; - int err; - - mmc_t *mmc = sdhci->mmc; - mmc_cmd_t cmd; +/** + * @brief Send the SEND_OP_COND command to the MMC/SD card. + * + * This function sends the SEND_OP_COND command to the MMC/SD card to initialize and + * check its capabilities. It waits for the card to respond and initializes it, updating + * the MMC structure with card information upon successful initialization. + * + * @param sdhci Pointer to the Sunxi SDHCI controller structure. + * + * @return Returns 0 on success, indicating successful initialization of the card, + * or an error code indicating failure. + * Possible error codes: + * - Negative value: indicates a communication error with the MMC/SD card. + * - Positive value: indicates an internal error within the function. + * - UNUSABLE_ERR: indicates failure to initialize the card within the timeout. + */ +static int sunxi_mmc_mmc_send_op_cond(sunxi_sdhci_t *sdhci) { + int timeout = 1000; ///< Timeout value for waiting for card initialization. + int err; ///< Error code for indicating success or failure. + mmc_t *mmc = sdhci->mmc;///< Pointer to the MMC structure. + mmc_cmd_t cmd; ///< Command structure for the SEND_OP_COND command. - /* Some cards seem to need this */ + // Reset the MMC/SD card sunxi_mmc_go_idle(sdhci); - /* Asking to the card its capabilities */ + // Send the SEND_OP_COND command to inquire about card capabilities cmd.cmdidx = MMC_CMD_SEND_OP_COND; cmd.resp_type = MMC_RSP_R3; - cmd.cmdarg = 0; /*0x40ff8000;*/ /*foresee */ + cmd.cmdarg = 0; cmd.flags = 0; + // Send command to check card capabilities err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); - if (err) { printk_error("SMHC: send op cond failed\n"); return err; } - mdelay(1); + mdelay(1);// Delay for stability + // Loop until the card is initialized or timeout occurs do { cmd.cmdidx = MMC_CMD_SEND_OP_COND; cmd.resp_type = MMC_RSP_R3; - cmd.cmdarg = (sunxi_mmc_host_is_spi(mmc) ? 0 : (mmc->voltages & (cmd.response[0] & OCR_VOLTAGE_MASK)) | (cmd.response[0] & OCR_ACCESS_MODE)); + // Set command arguments based on card type and version + cmd.cmdarg = (sunxi_mmc_host_is_spi(mmc) ? 0 : (mmc->voltages & (cmd.response[0] & OCR_VOLTAGE_MASK)) | (cmd.response[0] & OCR_ACCESS_MODE)); if (mmc->host_caps & MMC_MODE_HC) cmd.cmdarg |= OCR_HCS; - cmd.flags = 0; + // Send command to check card capabilities err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); - if (err) { printk_error("SMHC: send op cond failed\n"); return err; } - mdelay(1); - } while (!(cmd.response[0] & OCR_BUSY) && timeout--); + mdelay(1);// Delay for stability + + } while (!(cmd.response[0] & OCR_BUSY) && timeout--);// Wait for card initialization and decrement timeout if (timeout <= 0) { printk_error("SMHC: wait for mmc init failed\n"); - return UNUSABLE_ERR; + return UNUSABLE_ERR;// Indicate failure to initialize the card within the timeout } - if (sunxi_mmc_host_is_spi(mmc)) { /* read OCR for spi */ + // Read OCR for SPI + if (sunxi_mmc_host_is_spi(mmc)) { cmd.cmdidx = MMC_CMD_SPI_READ_OCR; cmd.resp_type = MMC_RSP_R3; cmd.cmdarg = 0; @@ -277,58 +485,95 @@ static int sunxi_mmc_mmc_send_op_cond(sdhci_t *sdhci) { return err; } + // Update MMC structure with card information mmc->version = MMC_VERSION_UNKNOWN; mmc->ocr = cmd.response[0]; - mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 1; - return 0; + return 0;// Return success } -static int sunxi_mmc_send_ext_csd(sdhci_t *sdhci, char *ext_csd) { - mmc_t *mmc = sdhci->mmc; - - mmc_cmd_t cmd; - mmc_data_t data; - int err; +/** + * @brief Send the SEND_EXT_CSD command to retrieve the Extended CSD from the MMC/SD card. + * + * This function sends the SEND_EXT_CSD command to the MMC/SD card to retrieve its Extended CSD register, + * which contains various configuration parameters and settings. It stores the retrieved Extended CSD data + * in the provided buffer. + * + * @param sdhci Pointer to the Sunxi SDHCI controller structure. + * @param ext_csd Pointer to the buffer where the Extended CSD data will be stored. + * + * @return Returns 0 on success, indicating successful retrieval of the Extended CSD data, + * or an error code indicating failure. + * Possible error codes: + * - Negative value: indicates a communication error with the MMC/SD card. + * - Positive value: indicates an internal error within the function. + */ +static int sunxi_mmc_send_ext_csd(sunxi_sdhci_t *sdhci, char *ext_csd) { + mmc_t *mmc = sdhci->mmc;///< Pointer to the MMC structure. + mmc_cmd_t cmd; ///< Command structure for the SEND_EXT_CSD command. + mmc_data_t data; ///< Data structure for storing the Extended CSD data. + int err; ///< Error code for indicating success or failure. - /* Get the Card Status Register */ + // Send command to retrieve the Extended CSD cmd.cmdidx = MMC_CMD_SEND_EXT_CSD; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = 0; cmd.flags = 0; + // Prepare data structure to store the Extended CSD data.b.dest = ext_csd; data.blocks = 1; data.blocksize = 512; data.flags = MMC_DATA_READ; + // Send command to retrieve the Extended CSD and store it in the provided buffer err = sunxi_sdhci_xfer(sdhci, &cmd, &data); + if (err) printk_error("SMHC: send ext csd failed\n"); - return err; + return err;// Return the error code (0 if successful) } -static int sunxi_mmc_switch(sdhci_t *sdhci, uint8_t set, uint8_t index, uint8_t value) { - mmc_t *mmc = sdhci->mmc; - - mmc_cmd_t cmd; - int timeout = 1000; - int ret; +/** + * @brief Send the SWITCH command to the MMC/SD card to change a specified mode or setting. + * + * This function sends the SWITCH command to the MMC/SD card to change a specified mode or setting. + * It is typically used to modify various parameters or configurations of the card. + * + * @param sdhci Pointer to the Sunxi SDHCI controller structure. + * @param set Value indicating the type of setting to be changed. + * @param index Index of the setting within the specified set. + * @param value New value to set for the specified setting. + * + * @return Returns 0 on success, indicating successful completion of the SWITCH command, + * or an error code indicating failure. + * Possible error codes: + * - Negative value: indicates a communication error with the MMC/SD card. + * - Positive value: indicates an internal error within the function. + */ +static int sunxi_mmc_switch(sunxi_sdhci_t *sdhci, uint8_t set, uint8_t index, uint8_t value) { + mmc_t *mmc = sdhci->mmc;///< Pointer to the MMC structure. + mmc_cmd_t cmd; ///< Command structure for the SWITCH command. + int timeout = 1000; ///< Timeout value for waiting for the card to become ready. + int ret; ///< Error code for indicating success or failure. + // Prepare the SWITCH command cmd.cmdidx = MMC_CMD_SWITCH; cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8); + cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set; cmd.flags = 0; + // Send the SWITCH command to the card ret = sunxi_sdhci_xfer(sdhci, &cmd, NULL); if (ret) { printk_error("SMHC: switch failed\n"); } /* for re-update sample phase */ + // Update clock phase after sending command 6 ret = sunxi_sdhci_update_phase(sdhci); if (ret) { printk_error("SMHC: update clock failed after send cmd6\n"); @@ -336,40 +581,56 @@ static int sunxi_mmc_switch(sdhci_t *sdhci, uint8_t set, uint8_t index, uint8_t } /* Waiting for the ready status */ + // Wait for the card to become ready sunxi_mmc_send_status(sdhci, timeout); - return ret; + return ret;// Return the error code (0 if successful) } -static int sunxi_mmc_change_freq(sdhci_t *sdhci) { - mmc_t *mmc = sdhci->mmc; - - char ext_csd[512]; - char cardtype; - int err; - int retry = 5; +/** + * @brief Change the frequency of the MMC/SD card to support high-speed modes. + * + * This function changes the frequency of the MMC/SD card to support high-speed modes. + * It checks if the card supports high-speed modes and switches to the appropriate mode if possible. + * + * @param sdhci Pointer to the Sunxi SDHCI controller structure. + * + * @return Returns 0 on success, indicating successful completion of the frequency change, + * or an error code indicating failure. + * Possible error codes: + * - Negative value: indicates a communication error with the MMC/SD card. + * - Positive value: indicates an internal error within the function. + */ +static int sunxi_mmc_mmc_change_freq(sunxi_sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc;///< Pointer to the MMC structure. + char ext_csd[512]; ///< Buffer to hold the extended CSD data. + char cardtype; ///< Type of the MMC/SD card. + int err; ///< Error code for indicating success or failure. + int retry = 5; ///< Number of retries for certain operations. - mmc->card_caps = 0; + mmc->card_caps = 0;///< Initialize card capabilities. + // Skip frequency change if MMC/SD card is in SPI mode if (sunxi_mmc_host_is_spi(mmc)) return 0; - /* Only version 4 supports high-speed */ + // Check if the card version supports high-speed modes if (mmc->version < MMC_VERSION_4) return 0; + // Enable 4-bit and 8-bit modes for MMC/SD card mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; - err = mmc_send_ext_csd(mmc, ext_csd); + // Get the extended CSD data from the card + err = sunxi_mmc_send_ext_csd(sdhci, ext_csd); if (err) { printk_error("SMHC: get ext csd failed\n"); return err; } - cardtype = ext_csd[196] & 0xff; + cardtype = ext_csd[196] & 0xff;///< Extract card type from the extended CSD data - /*retry for Toshiba emmc,for the first time Toshiba emmc change to HS */ - /*it will return response crc err,so retry */ + // Retry switching to high-speed mode for certain types of cards do { err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); if (!err) { @@ -383,57 +644,90 @@ static int sunxi_mmc_change_freq(sdhci_t *sdhci) { return err; } - /* Now check to see that it worked */ + // Check if the frequency change was successful err = sunxi_mmc_send_ext_csd(sdhci, ext_csd); - if (err) { printk_error("SMHC: send ext csd faild\n"); return err; } - /* No high-speed support */ + // Check if high-speed mode is supported if (!ext_csd[185]) return 0; - /* High Speed is set, there are two types: 52MHz and 26MHz */ + // Determine the type of high-speed mode and update card capabilities if (cardtype & EXT_CSD_CARD_TYPE_HS) { if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) { printk_trace("SMHC: get ddr OK!\n"); mmc->card_caps |= MMC_MODE_DDR_52MHz; mmc->speed_mode = MMC_HSDDR52_DDR50; - } else + } else { mmc->speed_mode = MMC_HSSDR52_SDR25; + } mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; - } else { mmc->card_caps |= MMC_MODE_HS; mmc->speed_mode = MMC_DS26_SDR12; } - return 0; + return 0;// Return success } -static int sunxi_mmc_sd_switch(sdhci_t *sdhci, int mode, int group, uint8_t value, uint8_t *resp) { - mmc_cmd_t cmd; - mmc_data_t data; +/** + * @brief Switch the functionality of the SD card. + * + * This function switches the functionality of the SD card, such as changing the frequency or mode of operation. + * It sends a SWITCH_FUNC command to the SD card with the specified parameters to perform the desired switch. + * + * @param sdhci Pointer to the Sunxi SDHCI controller structure. + * @param mode Switch mode indicating the type of switch operation to perform. + * @param group Switch group indicating the group of functions to switch. + * @param value Value indicating the specific function or setting to switch to within the specified group. + * @param resp Pointer to a buffer to store the response from the SD card. + * + * @return Returns 0 on success, indicating successful completion of the switch operation, + * or an error code indicating failure. + * Possible error codes: + * - Negative value: indicates a communication error with the SD card. + * - Positive value: indicates an internal error within the function. + */ +static int sunxi_mmc_sd_switch(sunxi_sdhci_t *sdhci, int mode, int group, uint8_t value, uint8_t *resp) { + mmc_cmd_t cmd; ///< MMC command structure for sending commands to the SD card. + mmc_data_t data;///< MMC data structure for specifying data transfer parameters. /* Switch the frequency */ - cmd.cmdidx = SD_CMD_SWITCH_FUNC; - cmd.resp_type = MMC_RSP_R1; - cmd.cmdarg = ((uint32_t) mode << 31) | 0xffffff; - cmd.cmdarg &= ~(0xf << (group * 4)); - cmd.cmdarg |= value << (group * 4); - cmd.flags = 0; - - data.b.dest = (char *) resp; - data.blocksize = 64; - data.blocks = 1; - data.flags = MMC_DATA_READ; - + cmd.cmdidx = SD_CMD_SWITCH_FUNC; ///< Command index for SWITCH_FUNC command. + cmd.resp_type = MMC_RSP_R1; ///< Response type for the command. + cmd.cmdarg = ((uint32_t) mode << 31) | 0xffffff;///< Command argument specifying the mode and reserved bits. + cmd.cmdarg &= ~(0xf << (group * 4)); ///< Clear the bits corresponding to the specified group. + cmd.cmdarg |= value << (group * 4); ///< Set the bits corresponding to the specified value within the group. + cmd.flags = 0; ///< Flags for command execution. + + data.b.dest = (char *) resp;///< Destination buffer for storing the response from the SD card. + data.blocksize = 64; ///< Block size for data transfer. + data.blocks = 1; ///< Number of blocks to transfer. + data.flags = MMC_DATA_READ; ///< Flags indicating the direction of data transfer. + + // Execute the command and data transfer return sunxi_sdhci_xfer(sdhci, &cmd, &data); } -static int sunxi_mmc_sd_change_freq(sdhci_t *sdhci) { +/** + * @brief Change the frequency of the SD card. + * + * This function changes the operating frequency of the SD card based on its capabilities. + * It reads the SCR (SD Configuration Register) to determine if the card supports higher speeds. + * If the card supports higher speeds, it adjusts the frequency accordingly. + * + * @param sdhci Pointer to the Sunxi SDHCI controller structure. + * + * @return Returns 0 on success, indicating successful change of frequency, + * or an error code indicating failure. + * Possible error codes: + * - Negative value: indicates a communication error with the SD card. + * - Positive value: indicates an internal error within the function. + */ +static int sunxi_mmc_sd_change_freq(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; mmc_cmd_t cmd; @@ -549,7 +843,7 @@ static int sunxi_mmc_sd_change_freq(sdhci_t *sdhci) { /* frequency bases */ /* divided by 10 to be nice to platforms without floating point */ -static const int fbase[] = { +static const int tran_speed_unit[] = { 10000, 100000, 1000000, @@ -559,7 +853,7 @@ static const int fbase[] = { /* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice * to platforms without floating point. */ -static const int multipliers[] = { +static const int tran_speed_time[] = { 0, /* reserved */ 10, 12, @@ -578,9 +872,21 @@ static const int multipliers[] = { 80, }; -static void sunxi_mmc_set_clock(sdhci_t *sdhci, uint32_t clock) { +/** + * @brief Set the clock frequency for the Sunxi SDHCI controller. + * + * This function sets the clock frequency for the Secure Digital Host Controller Interface (SDHCI) in a Sunxi system-on-a-chip (SoC) environment. + * + * @param sdhci A pointer to the Sunxi SDHCI controller structure. + * @param clock The desired clock frequency to be set. + */ +static void sunxi_mmc_set_clock(sunxi_sdhci_t *sdhci, uint32_t clock) { mmc_t *mmc = sdhci->mmc; + // Print debug information about clock frequencies + printk_trace("SMHC: fmax:%u, fmin:%u, clk:%u\n", mmc->f_max, mmc->f_min, clock); + + // Ensure clock frequency is within supported range if (clock > mmc->f_max) { clock = mmc->f_max; } @@ -589,116 +895,189 @@ static void sunxi_mmc_set_clock(sdhci_t *sdhci, uint32_t clock) { clock = mmc->f_min; } + // Update MMC clock frequency mmc->clock = clock; + + // Apply new clock settings to SDHCI controller sunxi_sdhci_set_ios(sdhci); } -static void sunxi_mmc_set_bus_width(sdhci_t *sdhci, uint32_t width) { - sdhci->width = width; +/** + * @brief Set the bus width for the Sunxi SDHCI controller. + * + * This function sets the bus width for the Secure Digital Host Controller Interface (SDHCI) in a Sunxi system-on-a-chip (SoC) environment. + * + * @param sdhci A pointer to the Sunxi SDHCI controller structure. + * @param width The bus width to be set (in bits). + */ +static void sunxi_mmc_set_bus_width(sunxi_sdhci_t *sdhci, uint32_t width) { + mmc_t *mmc = sdhci->mmc; + + // Set the bus width + mmc->bus_width = width; + + // Apply new settings to SDHCI controller sunxi_sdhci_set_ios(sdhci); } -static int sunxi_mmc_mmc_switch_ds(sdhci_t *sdhci) { +/** + * @brief Switch the Sunxi SDHCI controller to Double Speed (DS) mode. + * + * This function switches the Secure Digital Host Controller Interface (SDHCI) in a Sunxi system-on-a-chip (SoC) environment to Double Speed (DS) mode. + * + * @param sdhci A pointer to the Sunxi SDHCI controller structure. + * @return Returns 0 on success, or a negative error code on failure. + */ +static int sunxi_mmc_mmc_switch_ds(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; int err; + // Check if already in SDR12 mode if (mmc->speed_mode == MMC_DS26_SDR12) { printk_trace("SMHC: set in SDR12 mode\n"); } + // Check if card supports DS mode if (!(mmc->card_caps && MMC_MODE_HS)) { - printk_error("SMHC: Card not support ds mode\n"); + printk_error("SMHC: Card does not support DS mode\n"); return -1; } + // Switch to DS mode err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_BC); if (err) { - printk_error("SMHC: Change to ds failed\n"); + printk_error("SMHC: Failed to change to DS mode\n"); return err; } + // Update speed mode to SDR12 mmc->speed_mode = MMC_DS26_SDR12; return 0; } -static int sunxi_mmc_mmc_switch_hs(sdhci_t *sdhci) { +/** + * @brief Switch the Sunxi SDHCI controller to High Speed (HS) mode. + * + * This function switches the Secure Digital Host Controller Interface (SDHCI) in a Sunxi system-on-a-chip (SoC) environment to High Speed (HS) mode. + * + * @param sdhci A pointer to the Sunxi SDHCI controller structure. + * @return Returns 0 on success, or a negative error code on failure. + */ +static int sunxi_mmc_mmc_switch_hs(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; int err; + // Check if already in SDR25 mode if (mmc->speed_mode == MMC_HSSDR52_SDR25) { printk_trace("SMHC: set in SDR25 mode\n"); } + // Check if card supports HS mode if (!(mmc->card_caps && MMC_MODE_HS_52MHz)) { - printk_error("SMHC: Card not support hs mode\n"); + printk_error("SMHC: Card does not support HS mode\n"); return -1; } + // Switch to HS mode err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS); if (err) { - printk_error("SMHC: Change to hs failed\n"); + printk_error("SMHC: Failed to change to HS mode\n"); return err; } + // Update speed mode to SDR25 mmc->speed_mode = MMC_HSSDR52_SDR25; return 0; } -static int sunxi_mmc_mmc_switch_hs200(sdhci_t *sdhci) { +/** + * @brief Switch the Sunxi SDHCI controller to High Speed 200 (HS200) mode. + * + * This function switches the Secure Digital Host Controller Interface (SDHCI) in a Sunxi system-on-a-chip (SoC) environment to High Speed 200 (HS200) mode. + * + * @param sdhci A pointer to the Sunxi SDHCI controller structure. + * @return Returns 0 on success, or a negative error code on failure. + */ +static int sunxi_mmc_mmc_switch_hs200(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; int err; + // Check if already in SDR104 mode if (mmc->speed_mode == MMC_HS200_SDR104) { printk_trace("SMHC: set in SDR104 mode\n"); } + // Check if card supports HS200 mode if (!(mmc->card_caps && MMC_MODE_HS200)) { - printk_error("SMHC: Card not support hs200 mode\n"); + printk_error("SMHC: Card does not support HS200 mode\n"); return -1; } + // Switch to HS200 mode err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS200); if (err) { - printk_error("SMHC: Change to hs200 failed\n"); + printk_error("SMHC: Failed to change to HS200 mode\n"); return err; } + // Update speed mode to SDR104 mmc->speed_mode = MMC_HS200_SDR104; return 0; } -static int sunxi_mmc_mmc_switch_hs400(sdhci_t *sdhci) { +/** + * @brief Switch the Sunxi SDHCI controller to High Speed 400 (HS400) mode. + * + * This function switches the Secure Digital Host Controller Interface (SDHCI) in a Sunxi system-on-a-chip (SoC) environment to High Speed 400 (HS400) mode. + * + * @param sdhci A pointer to the Sunxi SDHCI controller structure. + * @return Returns 0 on success, or a negative error code on failure. + */ +static int sunxi_mmc_mmc_switch_hs400(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; int err; + // Check if already in HS400 mode if (mmc->speed_mode == MMC_HS400) { printk_trace("SMHC: set in HS400 mode\n"); } + // Check if card supports HS400 mode if (!(mmc->card_caps && MMC_MODE_HS400)) { - printk_error("SMHC: Card not support hs400 mode\n"); + printk_error("SMHC: Card does not support HS400 mode\n"); return -1; } + // Switch to HS400 mode err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS400); if (err) { - printk_error("SMHC: Change to hs400 failed\n"); + printk_error("SMHC: Failed to change to HS400 mode\n"); return err; } + // Update speed mode to HS400 mmc->speed_mode = MMC_HS400; return 0; } -static int sunxi_mmc_mmc_switch_mdoe(sdhci_t *sdhci, uint32_t spd_mode) { +/** + * @brief Switches the speed mode of the MMC controller. + * + * This function switches the speed mode of the MMC controller based on the provided speed mode. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + * @param spd_mode Speed mode to be switched to. + * @return Returns 0 upon success, -1 if an error occurs. + */ +static int sunxi_mmc_mmc_switch_speed_mode(sunxi_sdhci_t *sdhci, uint32_t spd_mode) { mmc_t *mmc = sdhci->mmc; int ret = 0; @@ -727,7 +1106,17 @@ static int sunxi_mmc_mmc_switch_mdoe(sdhci_t *sdhci, uint32_t spd_mode) { return ret; } -static int sunxi_mmc_check_bus_width(sdhci_t *sdhci, uint32_t emmc_hs_ddr, uint32_t bus_width) { +/** + * @brief Checks if the specified bus width is supported by the MMC controller. + * + * This function checks if the specified bus width is supported by the MMC controller, based on the provided parameters. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + * @param emmc_hs_ddr Flag indicating if eMMC high-speed DDR mode is enabled. + * @param bus_width The bus width to be checked. + * @return Returns 0 if the bus width is supported, -1 if not. + */ +static int sunxi_mmc_check_bus_width(sunxi_sdhci_t *sdhci, uint32_t emmc_hs_ddr, uint32_t bus_width) { mmc_t *mmc = sdhci->mmc; int ret = 0; @@ -756,7 +1145,17 @@ static int sunxi_mmc_check_bus_width(sdhci_t *sdhci, uint32_t emmc_hs_ddr, uint3 return ret; } -static int sunxi_mmc_mmc_switch_bus_width(sdhci_t *sdhci, uint32_t spd_mode, uint32_t width) { +/** + * @brief Switches the bus width of the MMC controller. + * + * This function switches the bus width of the MMC controller based on the provided parameters. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + * @param spd_mode Speed mode of the MMC controller. + * @param width The bus width to be set. + * @return Returns 0 upon success, -1 if an error occurs. + */ +static int sunxi_mmc_mmc_switch_bus_width(sunxi_sdhci_t *sdhci, uint32_t spd_mode, uint32_t width) { mmc_t *mmc = sdhci->mmc; int err = 0; uint32_t emmc_hs_ddr = 0; @@ -806,7 +1205,18 @@ static int sunxi_mmc_mmc_switch_bus_width(sdhci_t *sdhci, uint32_t spd_mode, uin return err; } -static int sunxi_mmc_mmc_switch_bus_mode(sdhci_t *sdhci, uint32_t spd_mode, uint32_t width) { +/** + * @brief Switches the speed mode and bus width of the MMC controller. + * + * This function switches the speed mode and bus width of the MMC controller based on the provided parameters. + * If the device is an SD card, no action is taken and the function returns successfully. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + * @param spd_mode Speed mode to be switched to. + * @param width The bus width to be set. + * @return Returns 0 upon success, an error code if an error occurs. + */ +static int sunxi_mmc_mmc_switch_bus_mode(sunxi_sdhci_t *sdhci, uint32_t spd_mode, uint32_t width) { mmc_t *mmc = sdhci->mmc; int err = 0; int spd_mode_backup = 0; @@ -815,11 +1225,545 @@ static int sunxi_mmc_mmc_switch_bus_mode(sdhci_t *sdhci, uint32_t spd_mode, uint return 0; } - if (spd_md == MMC_HSDDR52_DDR50) { + if (spd_mode == MMC_HSDDR52_DDR50) { spd_mode_backup = MMC_HSSDR52_SDR25; } else { spd_mode_backup = spd_mode; } - err = + err = sunxi_mmc_mmc_switch_speed_mode(sdhci, spd_mode); + + if (err) { + printk_error("SMHC: Switch speed mode failed\n"); + return err; + } + + err = sunxi_mmc_mmc_switch_bus_width(sdhci, spd_mode, width); + + if (err) { + printk_error("SMHC: Switch bus width\n"); + return err; + } + + if (spd_mode == MMC_HSDDR52_DDR50) { + mmc->speed_mode = MMC_HSDDR52_DDR50; + } + + return err; +} + +/** + * @brief Sends the SD CMD8 (SEND_IF_COND) command to the MMC controller. + * + * This function sends the SD CMD8 command to the MMC controller to check if the card supports the given voltage range. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + * @return Returns 0 upon success, an error code if an error occurs. + */ +static int sunxi_mmc_send_if_cond(sunxi_sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + mmc_cmd_t cmd; + int err = 0; + + cmd.cmdidx = SD_CMD_SEND_IF_COND; + /* We set the bit if the host supports voltages between 2.7 and 3.6 V */ + cmd.cmdarg = ((mmc->voltages & 0xff8000) != 0) << 8 | 0xaa; + cmd.resp_type = MMC_RSP_R7; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: send if cond failed\n"); + return err; + } + + if ((cmd.response[0] & 0xff) != 0xaa) + return UNUSABLE_ERR; + else + mmc->version = SD_VERSION_2; + + return 0; +} + +/** + * @brief Displays information about the SD/MMC card attached to the given host controller. + * + * This function prints various details about the SD/MMC card attached to the specified host controller, + * such as the card type, capacity, CID, CSD, maximum transfer speed, manufacturer ID, OEM/application ID, + * product name, product revision, serial number, and manufacturing date. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + */ +static void sunxi_mmc_show_card_info(sunxi_sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + + printk_debug("SD/MMC card at the '%s' host controller:\r\n", sdhci->name); + printk_debug(" Attached is a %s card\r\n", mmc->version & SD_VERSION_SD ? "SD" : "MMC"); + if (mmc->capacity / (f64) 1000000000.0 < 4) + printk_info(" Capacity: %.1fMB\n", (f32) ((f64) mmc->capacity / (f64) 1000000.0)); + else + printk_info(" Capacity: %.1fGB\n", (f32) ((f64) mmc->capacity / (f64) 1000000000.0)); + if (mmc->high_capacity) + printk_debug(" High capacity card\r\n"); + printk_debug(" CID: %08X-%08X-%08X-%08X\r\n", mmc->cid[0], mmc->cid[1], mmc->cid[2], mmc->cid[3]); + printk_debug(" CSD: %08X-%08X-%08X-%08X\r\n", mmc->csd[0], mmc->csd[1], mmc->csd[2], mmc->csd[3]); + printk_debug(" Max transfer speed: %u HZ\r\n", mmc->tran_speed); + printk_debug(" Manufacturer ID: %02X\r\n", extract_mid(mmc)); + printk_debug(" OEM/Application ID: %04X\r\n", extract_oid(mmc)); + printk_debug(" Product name: '%c%c%c%c%c'\r\n", mmc->cid[0] & 0xff, (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff, (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff); + printk_debug(" Product revision: %u.%u\r\n", extract_prv(mmc) >> 4, extract_prv(mmc) & 0xf); + printk_debug(" Serial no: %0u\r\n", extract_psn(mmc)); + printk_debug(" Manufacturing date: %u.%u\r\n", extract_year(mmc), extract_month(mmc)); +} + +/** + * @brief Probes the SD/MMC card attached to the given host controller. + * + * This function probes the SD/MMC card attached to the specified host controller, + * retrieves various card-specific data such as CID and CSD, and sets the card + * to the appropriate mode. It also handles sending commands and checking for errors. + * + * @param sdhci Pointer to the SD/MMC host controller structure. + * @return 0 on success, or an error code if an error occurred during probing. + */ +static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { + mmc_t *mmc = sdhci->mmc; + int err = 0; + int timeout = 1000; + uint32_t capacity, cmult, csize; + const char *strver = "unknown"; + + mmc_cmd_t cmd; + char ext_csd[512]; + + /* Set card to identity Mode */ + cmd.cmdidx = sunxi_mmc_host_is_spi(mmc) ? MMC_CMD_SEND_CID : MMC_CMD_ALL_SEND_CID; + cmd.resp_type = MMC_RSP_R2; + cmd.cmdarg = 0; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: Put the Card in Identify Mode failed\n"); + return -1; + } + + memcpy(mmc->cid, cmd.response, 16); + + /* + * For MMC cards, set the Relative Address. + * For SD cards, get the Relatvie Address. + * This also puts the cards into Standby State + */ + if (!sunxi_mmc_host_is_spi(mmc)) { + cmd.cmdidx = SD_CMD_SEND_RELATIVE_ADDR; + cmd.cmdarg = mmc->rca << 16; + cmd.resp_type = MMC_RSP_R6; + cmd.flags = MMC_DATA_READ; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: send rca failed\n"); + return err; + } + + if (sunxi_mmc_device_is_sd(mmc)) { + mmc->rca = (cmd.response[0] >> 16) & 0xffff; + } + } + + /* Get the Card-Specific Data */ + cmd.cmdidx = MMC_CMD_SEND_CSD; + cmd.resp_type = MMC_RSP_R2; + cmd.cmdarg = mmc->rca << 16; + cmd.flags = MMC_DATA_READ; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + /* Waiting for the ready status */ + sunxi_mmc_send_status(sdhci, timeout); + + if (err) { + printk_error("SMHC: MMC get csd failed\n"); + return err; + } + + mmc->csd[0] = cmd.response[0]; + mmc->csd[1] = cmd.response[1]; + mmc->csd[2] = cmd.response[2]; + mmc->csd[3] = cmd.response[3]; + + if (mmc->version == MMC_VERSION_UNKNOWN) { + uint32_t version = (cmd.response[0] >> 26) & 0xf; + switch (version) { + case 0: + mmc->version = MMC_VERSION_1_2; + break; + case 1: + mmc->version = MMC_VERSION_1_4; + break; + case 2: + mmc->version = MMC_VERSION_2_2; + break; + case 3: + mmc->version = MMC_VERSION_3; + break; + case 4: + mmc->version = MMC_VERSION_4; + break; + default: + mmc->version = MMC_VERSION_1_2; + break; + } + } + + /* divide frequency by 10, since the mults are 10x bigger */ + uint32_t freq = tran_speed_unit[(cmd.response[0] & 0x7)]; + uint32_t mult = tran_speed_time[((cmd.response[0] >> 3) & 0xf)]; + + printk_trace("SMHC: Card frep:%uHz, mult:%u\n", freq, mult); + + mmc->tran_speed = freq * mult; + mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf); + + if (sunxi_mmc_device_is_sd(mmc)) + mmc->write_bl_len = mmc->read_bl_len; + else + mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf); + + if (mmc->high_capacity) { + csize = (mmc->csd[1] & 0x3f) << 16 | + (mmc->csd[2] & 0xffff0000) >> 16; + cmult = 8; + } else { + csize = (mmc->csd[1] & 0x3ff) << 2 | + (mmc->csd[2] & 0xc0000000) >> 30; + cmult = (mmc->csd[2] & 0x00038000) >> 15; + } + + mmc->capacity = (csize + 1) << (cmult + 2); + mmc->capacity *= mmc->read_bl_len; + + if (mmc->read_bl_len > 512) + mmc->read_bl_len = 512; + + if (mmc->write_bl_len > 512) + mmc->write_bl_len = 512; + + /* Select the card, and put it into Transfer Mode */ + if (!sunxi_mmc_host_is_spi(mmc)) { /* cmd not supported in spi */ + cmd.cmdidx = MMC_CMD_SELECT_CARD; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = mmc->rca << 16; + cmd.flags = 0; + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + + if (err) { + printk_error("SMHC: Select the card failed\n"); + return err; + } + } + + if (!sunxi_mmc_device_is_sd(mmc)) { + /* TODO MMC Timing update */ + } + + sunxi_mmc_set_clock(sdhci, mmc->tran_speed); + + /* + * For SD, its erase group is always one sector + */ + mmc->erase_grp_size = 1; + mmc->part_config = MMCPART_NOAVAILABLE; + + if (!sunxi_mmc_device_is_sd(mmc) && (mmc->version >= MMC_VERSION_4)) { + /* check ext_csd version and capacity */ + err = sunxi_mmc_send_ext_csd(sdhci, ext_csd); + if (!err) { + /* update mmc version */ + switch (ext_csd[192]) { + case 0: + mmc->version = MMC_VERSION_4; + strver = "4.0"; + break; + case 1: + mmc->version = MMC_VERSION_4_1; + strver = "4.1"; + break; + case 2: + mmc->version = MMC_VERSION_4_2; + strver = "4.2"; + break; + case 3: + mmc->version = MMC_VERSION_4_3; + strver = "4.3"; + break; + case 5: + mmc->version = MMC_VERSION_4_41; + strver = "4.41"; + break; + case 6: + mmc->version = MMC_VERSION_4_5; + strver = "4.5"; + break; + case 7: + mmc->version = MMC_VERSION_5_0; + strver = "5.0"; + break; + case 8: + mmc->version = MMC_VERSION_5_1; + strver = "5.1"; + break; + } + } + + if (!err & (ext_csd[192] >= 2)) { + /* + * According to the JEDEC Standard, the value of + * ext_csd's capacity is valid if the value is more + * than 2GB + */ + capacity = ext_csd[212] << 0 | ext_csd[213] << 8 | + ext_csd[214] << 16 | ext_csd[215] << 24; + capacity *= 512; + if ((capacity >> 20) > 2 * 1024) + mmc->capacity = capacity; + } + + /* + * Check whether GROUP_DEF is set, if yes, read out + * group size from ext_csd directly, or calculate + * the group size from the csd value. + */ + if (ext_csd[175]) + mmc->erase_grp_size = ext_csd[224] * 512 * 1024; + else { + int erase_gsz, erase_gmul; + erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10; + erase_gmul = (mmc->csd[2] & 0x000003e0) >> 5; + mmc->erase_grp_size = (erase_gsz + 1) * (erase_gmul + 1); + } + + /* store the partition info of emmc */ + if (ext_csd[160] & PART_SUPPORT) { + mmc->part_config = ext_csd[179]; + } + } + + if (sunxi_mmc_device_is_sd(mmc)) { + err = sunxi_mmc_sd_change_freq(sdhci); + } else { + err = sunxi_mmc_mmc_change_freq(sdhci); + } + + if (err) { + printk_error("SMHC: Change speed mode failed\n"); + return err; + } + + /* for re-update sample phase */ + err = sunxi_sdhci_update_phase(sdhci); + if (err) { + printk_error("SMHC: update clock failed\n"); + return err; + } + + printk_trace("SMHC: mmc->card_caps 0x%x, ddr caps:0x%x\n", mmc->card_caps, mmc->card_caps & MMC_MODE_DDR_52MHz); + + /* Restrict card's capabilities by what the host can do */ + mmc->card_caps &= mmc->host_caps; + printk_trace("SMHC: mmc->card_caps 0x%x, ddr caps:0x%x\n", mmc->card_caps, mmc->card_caps & MMC_MODE_DDR_52MHz); + + if (!(mmc->card_caps & MMC_MODE_DDR_52MHz) && !sunxi_mmc_device_is_sd(mmc)) { + if (mmc->speed_mode == MMC_HSDDR52_DDR50) + mmc->speed_mode = MMC_HSSDR52_SDR25; + else + mmc->speed_mode = MMC_DS26_SDR12; + } + + if (sunxi_mmc_device_is_sd(mmc)) { + /* SD CARD */ + if (mmc->card_caps & MMC_MODE_4BIT) { + cmd.cmdidx = MMC_CMD_APP_CMD; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = mmc->rca << 16; + cmd.flags = 0; + + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + if (err) { + printk_trace("SMHC: send app cmd failed\n"); + return err; + } + + cmd.cmdidx = SD_CMD_APP_SET_BUS_WIDTH; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = 2; + cmd.flags = 0; + err = sunxi_sdhci_xfer(sdhci, &cmd, NULL); + if (err) { + printk_trace("SMHC: sd set bus width failed\n"); + return err; + } + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_4BIT); + } + + if (mmc->card_caps & MMC_MODE_HS) + mmc->tran_speed = 50000000; + else + mmc->tran_speed = 25000000; + } else { + /* EMMC */ + if (mmc->card_caps & MMC_MODE_8BIT) { + mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HS400; + mmc->speed_mode = MMC_HS400; + if ((mmc->card_caps & MMC_MODE_HS400)) { + /* firstly, switch to HS-DDR 8 bit */ + err = sunxi_mmc_mmc_switch_bus_width(sdhci, MMC_HSDDR52_DDR50, 8); + if (err) { + printk_error("SMHC: HS400 switch to DDR mode fail\n"); + return err; + } + + /* then, switch to HS400 */ + err = sunxi_mmc_mmc_switch_bus_mode(sdhci, MMC_HS400, 8); + if (err) { + printk_error("SMHC: switch to HS400 mode fail\n"); + return err; + } + mmc->tran_speed = sdhci->max_clk; + + /* Set the card to use 8 bit */ + } else if ((mmc->card_caps & MMC_MODE_DDR_52MHz)) { + /* Set the card to use 8 bit ddr */ + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_DDR_8); + if (err) { + printk_error("SMHC: switch bus width failed\n"); + return err; + } + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_8BIT); + } + } else if (mmc->card_caps & MMC_MODE_4BIT) { + if ((mmc->card_caps & MMC_MODE_DDR_52MHz)) { + /* Set the card to use 4 bit ddr */ + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_DDR_4); + if (err) { + printk_error("SMHC: switch bus width failed\n"); + return err; + } + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_4BIT); + } else { + /* Set the card to use 4 bit */ + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_4); + if (err) { + printk_error("SMHC: switch bus width failed\n"); + return err; + } + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_4BIT); + } + } else { + /* Set the card to use 8 bit */ + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8); + + if (err) { + printk_error("SMHC: witch bus width8 failed\n"); + return err; + } + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_8BIT); + } + } + + if (mmc->card_caps & MMC_MODE_HS400) { + mmc->tran_speed = sdhci->max_clk; + } else if (mmc->card_caps & MMC_MODE_DDR_52MHz) { + mmc->tran_speed = 52000000; + } else if (mmc->card_caps & MMC_MODE_HS) { + if (mmc->card_caps & MMC_MODE_HS_52MHz) { + mmc->tran_speed = 52000000; + } else { + mmc->tran_speed = 26000000; + } + } else { + mmc->tran_speed = 26000000; + } + + printk_trace("SMHC: set clock to %u\n", mmc->tran_speed); + sunxi_mmc_set_clock(sdhci, mmc->tran_speed); + + /* fill in device description */ + mmc->blksz = mmc->read_bl_len; + mmc->lba = mmc->capacity >> 9; + + sunxi_mmc_show_card_info(sdhci); + + return 0; +} + +/** + * @brief Initializes the SD/MMC host controller and attached card. + * + * This function initializes the specified SD/MMC host controller and the + * attached SD/MMC card. It initializes the host controller core, sets the + * bus width and clock speed, resets the card, and initializes the card + * based on its type (SD or eMMC). Finally, it probes the card to retrieve + * card-specific data. + * + * @param sdhci_hdl Pointer to the SD/MMC host controller structure. + * @return 0 on success, or an error code if an error occurred during initialization. + */ +int sunxi_mmc_init(void *sdhci_hdl) { + sunxi_sdhci_t *sdhci = (sunxi_sdhci_t *) sdhci_hdl; + + mmc_t *mmc = sdhci->mmc; + int err = 0; + + printk_trace("SMHC: init mmc device\n"); + + err = sunxi_sdhci_core_init(sdhci); + if (err) { + printk_error("SMHC: host init failed\n"); + return err; + } + + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_1BIT); + sunxi_mmc_set_clock(sdhci, 400000); + + err = sunxi_mmc_go_idle(sdhci); + + if (err) { + printk_error("SMHC: Reset card fail\n"); + return err; + } + + mmc->part_num = 0; + + if (sdhci->sdhci_mmc_type == MMC_TYPE_SD) { + printk_debug("SMHC: Try to init SD Card\n"); + err = sunxi_mmc_send_if_cond(sdhci); + if (err) { + printk_error("SMHC%d: SD Card did not respond to voltage select\n", sdhci->id); + return -1; + } + err = sunxi_mmc_sd_send_op_cond(sdhci); + if (err) { + printk_error("SMHC%d: SD Card did not respond to voltage select\n", sdhci->id); + return -1; + } + } else if (sdhci->sdhci_mmc_type == MMC_TYPE_EMMC) { + printk_debug("SMHC: Try to init eMMC Card\n"); + err = sunxi_mmc_mmc_send_op_cond(sdhci); + if (err) { + printk_error("SMHC%d: MMC did not respond to voltage select\n", sdhci->id); + return -1; + } + } + + err = sunxi_mmc_probe(sdhci); + if (err) { + printk_error("SMHC%d: SD/MMC Probe failed, err %d\n", sdhci->id, err); + } + + return err; } \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdcard.c b/src/drivers/mmc/sys-sdcard.c index 85bc12e5..caced5f2 100644 --- a/src/drivers/mmc/sys-sdcard.c +++ b/src/drivers/mmc/sys-sdcard.c @@ -16,4 +16,12 @@ #include -sdmmc_pdata_t card0; \ No newline at end of file +sdmmc_pdata_t card0; + +int sdmmc_init(sdmmc_pdata_t *data, sunxi_sdhci_t *hci) { + return 0; +} + +uint64_t sdmmc_blk_read(sdmmc_pdata_t *data, uint8_t *buf, uint64_t blkno, uint64_t blkcnt) { + return 0; +} \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index a058a105..087f2ea1 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -17,6 +17,10 @@ #include #include +/* Global data*/ +sunxi_sdhci_host_t g_mmc_host; +mmc_t g_mmc; + /** * @brief Enable clock for the SDHC controller. * @@ -25,7 +29,7 @@ * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success. */ -static int sunxi_sdhci_clk_enable(sdhci_t *sdhci) { +static int sunxi_sdhci_clk_enable(sunxi_sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; uint32_t reg_val; @@ -41,6 +45,10 @@ static int sunxi_sdhci_clk_enable(sdhci_t *sdhci) { /* Configure module clock */ writel(0x80000000, mmc_host->mclkbase); mmc_host->mod_clk = 24000000; + + printk_trace("SMHC: sdhci%d clk enable clk reg = 0x%08x -> 0x%08x, mclk: 0x%08x\n", sdhci->id, + mmc_host->hclkbase, readl(mmc_host->hclkbase), readl(mmc_host->mclkbase)); + return 0; } @@ -52,21 +60,19 @@ static int sunxi_sdhci_clk_enable(sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success, -1 on failure. */ -static int sunxi_sdhci_update_clk(sdhci_t *sdhci) { +static int sunxi_sdhci_update_clk(sunxi_sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - - uint32_t cmd = 0x0; uint32_t timeout = time_us() + SMHC_TIMEOUT; mmc_host->reg->clkcr |= SMHC_CLKCR_MASK_D0; mmc_host->reg->cmd = SMHC_CMD_START | SMHC_CMD_UPCLK_ONLY | SMHC_CMD_WAIT_PRE_OVER; /* Wait for process done */ - while ((mmc_host->reg->cmd & MMC_CMD_CMDVAL_MASK) && (time_us() < timeout)) { + while ((mmc_host->reg->cmd & SMHC_CMD_START) && (time_us() < timeout)) { } /* Check status */ - if (mmc_host->reg->cmd & MMC_CMD_CMDVAL_MASK) { + if (mmc_host->reg->cmd & SMHC_CMD_START) { printk_error("SMHC: mmc %d update clk failed\n", sdhci->id); return -1; } @@ -87,58 +93,64 @@ static int sunxi_sdhci_update_clk(sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC structure. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_get_timing_config_timing_4(sdhci_t *sdhci) { - sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; +static int sunxi_sdhci_get_timing_config_timing_4(sunxi_sdhci_t *sdhci) { + sunxi_sdhci_timing_t timing_data = sdhci->timing_data; uint32_t spd_md_sdly = 0, dly = 0; int ret = 0; + printk_trace("SMHC: sdhci timing config timing 4\n"); + /* Check if the controller ID is MMC_CONTROLLER_2 and if timing mode and frequency ID are valid */ - if ((sdhci->id != MMC_CONTROLLER_2) || (timing_data->spd_md_id > MMC_TIMING_MODE_4) || (timing_data->freq_id > MMC_MAX_SPD_MD_NUM)) { + if ((sdhci->id != MMC_CONTROLLER_2) || (timing_data.spd_md_id > MMC_TIMING_MODE_4) || (timing_data.freq_id > MMC_MAX_SPD_MD_NUM)) { printk_error("SMHC: timing 4 not supported for this configuration\n"); return -1; } /* Calculate delay based on speed mode and frequency */ - dly = ((spd_md_sdly >> ((timing_data->freq_id % 4) * 8)) & 0xff); + dly = ((spd_md_sdly >> ((timing_data.freq_id % 4) * 8)) & 0xff); if ((dly == 0xff) || (dly == 0)) { - if (timing_data->spd_md_id == MMC_DS26_SDR12) { - if (timing_data->freq_id <= MMC_CLK_25M) { + if (timing_data.spd_md_id == MMC_DS26_SDR12) { + if (timing_data.freq_id <= MMC_CLK_25M) { dly = 0; } else { - printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data->freq_id, timing_data->spd_md_id); + printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data.freq_id, timing_data.spd_md_id); ret = -1; } - } else if (timing_data->spd_md_id == MMC_HSSDR52_SDR25) { - if (timing_data->freq_id <= MMC_CLK_25M) { + } else if (timing_data.spd_md_id == MMC_HSSDR52_SDR25) { + if (timing_data.freq_id <= MMC_CLK_25M) { dly = 0; - } else if (timing_data->freq_id == MMC_CLK_50M) { + } else if (timing_data.freq_id == MMC_CLK_50M) { dly = 15; } else { - printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data->freq_id, timing_data->spd_md_id); + printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data.freq_id, timing_data.spd_md_id); ret = -1; } - } else if (timing_data->spd_md_id == MMC_HSDDR52_DDR50) { - if (timing_data->freq_id <= MMC_CLK_25M) { + } else if (timing_data.spd_md_id == MMC_HSDDR52_DDR50) { + if (timing_data.freq_id <= MMC_CLK_25M) { dly = 0; } else { - printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data->freq_id, timing_data->spd_md_id); + printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data.freq_id, timing_data.spd_md_id); ret = -1; } } else { - printk_error("SMHC: wrong speed mode %d\n", timing_data->spd_md_id); + printk_error("SMHC: wrong speed mode %d\n", timing_data.spd_md_id); ret = -1; } } /* Set output delay based on speed mode */ - if (timing_data->spd_md_id == MMC_HSDDR52_DDR50) { - timing_data->odly = 1; + if (timing_data.spd_md_id == MMC_HSDDR52_DDR50) { + timing_data.odly = 1; } else { - timing_data->odly = 0; + timing_data.odly = 0; } /* Set the calculated delay */ - timing_data->sdly = dly; + timing_data.sdly = dly; + + printk_trace("SMHC: TM4 Timing odly = %u, sdly = %u, spd_md_id = %u, freq_id = %u\n", + timing_data.odly, timing_data.sdly, timing_data.spd_md_id, + timing_data.freq_id); return ret; } @@ -152,11 +164,11 @@ static int sunxi_sdhci_get_timing_config_timing_4(sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success, -1 on failure. */ -static int sunxi_sdhci_get_timing_config(sdhci_t *sdhci) { +static int sunxi_sdhci_get_timing_config(sunxi_sdhci_t *sdhci) { int ret = 0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + sunxi_sdhci_timing_t timing_data = sdhci->timing_data; // Check for specific conditions based on the controller ID and timing mode if ((sdhci->id == 2) && mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { @@ -167,13 +179,13 @@ static int sunxi_sdhci_get_timing_config(sdhci_t *sdhci) { } } else if ((sdhci->id == 0) && (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1)) { // Check timing data and adjust configuration if necessary - if ((timing_data->spd_md_id <= MMC_HSSDR52_SDR25) && (timing_data->freq_id <= MMC_CLK_50M)) { + if ((timing_data.spd_md_id <= MMC_HSSDR52_SDR25) && (timing_data.freq_id <= MMC_CLK_50M)) { /* if timing less than SDR25, use default odly */ - timing_data->odly = 0; - timing_data->sdly = 0; + timing_data.odly = 0; + timing_data.sdly = 0; ret = 0; } else { - printk_warning("SMHC: SMHC0 does not support input spd mode %d\n", timing_data->spd_md_id); + printk_warning("SMHC: SMHC0 does not support input spd mode %d\n", timing_data.spd_md_id); ret = -1; } } else { @@ -193,7 +205,7 @@ static int sunxi_sdhci_get_timing_config(sdhci_t *sdhci) { * @param clk_hz Desired clock frequency in Hertz. * @return Returns 0 on success, -1 on failure. */ -static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { +static int sunxi_sdhci_set_mclk(sunxi_sdhci_t *sdhci, uint32_t clk_hz) { uint32_t n, m, src; uint32_t reg_val = 0x0; @@ -249,7 +261,7 @@ static int sunxi_sdhci_set_mclk(sdhci_t *sdhci, uint32_t clk_hz) { * @param sdhci Pointer to the SDHC controller structure. * @return Current clock frequency in Hertz. */ -static uint32_t sunxi_sdhci_get_mclk(sdhci_t *sdhci) { +static uint32_t sunxi_sdhci_get_mclk(sunxi_sdhci_t *sdhci) { uint32_t n, m, src, clk_hz; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; @@ -292,99 +304,105 @@ static uint32_t sunxi_sdhci_get_mclk(sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC controller structure. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_config_delay(sdhci_t *sdhci) { +static int sunxi_sdhci_config_delay(sunxi_sdhci_t *sdhci) { int ret = 0; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + sunxi_sdhci_timing_t timing_data = sdhci->timing_data; - if (mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_1) { - timing_data->odly = 0; - timing_data->sdly = 0; - printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_1, odly %d, sldy %d\n", timing_data->odly, timing_data->sdly); + if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { + timing_data.odly = 0; + timing_data.sdly = 0; + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_1, odly %d, sldy %d\n", timing_data.odly, timing_data.sdly); reg_val = mmc_host->reg->drv_dl; reg_val &= (~(0x3 << 16)); - reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); + reg_val |= (((timing_data.odly & 0x1) << 16) | ((timing_data.odly & 0x1) << 17)); writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); mmc_host->reg->drv_dl = reg_val; writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); reg_val = mmc_host->reg->ntsr; reg_val &= (~(0x3 << 4)); - reg_val |= ((timing_data->sdly & 0x3) << 4); + reg_val |= ((timing_data.sdly & 0x3) << 4); mmc_host->reg->ntsr = reg_val; - } else if (mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_3) { - timing_data->odly = 0; - timing_data->sdly = 0; - printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_3, odly %d, sldy %d\n", timing_data->odly, timing_data->sdly); + } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3) { + timing_data.odly = 0; + timing_data.sdly = 0; + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_3, odly %d, sldy %d\n", timing_data.odly, timing_data.sdly); reg_val = mmc_host->reg->drv_dl; reg_val &= (~(0x3 << 16)); - reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); + reg_val |= (((timing_data.odly & 0x1) << 16) | ((timing_data.odly & 0x1) << 17)); writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); mmc_host->reg->drv_dl = reg_val; writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); reg_val = mmc_host->reg->samp_dl; reg_val &= (~SDXC_NTDC_CFG_DLY); - reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + reg_val |= ((timing_data.sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); mmc_host->reg->samp_dl = reg_val; - } else if (mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_4) { - uint32_t spd_md_orig = timing_data->spd_md_id; + } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { + uint32_t spd_md_orig = timing_data.spd_md_id; + + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_4, setup\n"); - if (timing_data->spd_md_id == MMC_HS400) - timing_data->spd_md_id = MMC_HS200_SDR104; + if (timing_data.spd_md_id == MMC_HS400) + timing_data.spd_md_id = MMC_HS200_SDR104; - timing_data->odly = 0xff; - timing_data->sdly = 0xff; + timing_data.odly = 0xff; + timing_data.sdly = 0xff; if ((ret = sunxi_sdhci_get_timing_config(sdhci)) != 0) { printk_error("SMHC: getting timing param error %d\n", ret); return -1; } - if ((timing_data->odly == 0xff) || (timing_data->sdly = 0xff)) { + timing_data = sdhci->timing_data; + + if ((timing_data.odly == 0xff) || (timing_data.sdly == 0xff)) { printk_error("SMHC: getting timing config error\n"); return -1; } reg_val = mmc_host->reg->drv_dl; reg_val &= (~(0x3 << 16)); - reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); + reg_val |= (((timing_data.odly & 0x1) << 16) | ((timing_data.odly & 0x1) << 17)); writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); mmc_host->reg->drv_dl = reg_val; writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); reg_val = mmc_host->reg->samp_dl; reg_val &= (~SDXC_NTDC_CFG_DLY); - reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + reg_val |= ((timing_data.sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); mmc_host->reg->samp_dl = reg_val; /* Reset to orig md id */ - timing_data->spd_md_id = spd_md_orig; - if (timing_data->spd_md_id = MMC_HS400) { - timing_data->odly = 0xff; - timing_data->sdly = 0xff; + timing_data.spd_md_id = spd_md_orig; + if (timing_data.spd_md_id = MMC_HS400) { + timing_data.odly = 0xff; + timing_data.sdly = 0xff; if ((ret = sunxi_sdhci_get_timing_config(sdhci)) != 0) { printk_error("SMHC: getting timing param error %d\n", ret); return -1; } - if ((timing_data->odly == 0xff) || (timing_data->sdly = 0xff)) { + timing_data = sdhci->timing_data; + + if ((timing_data.odly == 0xff) || (timing_data.sdly == 0xff)) { printk_error("SMHC: getting timing config error\n"); return -1; } reg_val = mmc_host->reg->ds_dl; reg_val &= (~SDXC_NTDC_CFG_DLY); - reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + reg_val |= ((timing_data.sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); mmc_host->reg->ds_dl = reg_val; } printk_trace("SMHC: config delay freq = %d, odly = %d," "sdly = %d, spd_md_id = %d\n", - timing_data->freq_id, timing_data->odly, - timing_data->sdly, timing_data->spd_md_id); + timing_data.freq_id, timing_data.odly, + timing_data.sdly, timing_data.spd_md_id); } } @@ -397,17 +415,18 @@ static int sunxi_sdhci_config_delay(sdhci_t *sdhci) { * @param clk Clock frequency. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { +static int sunxi_sdhci_clock_mode(sunxi_sdhci_t *sdhci, uint32_t clk) { int ret = 0; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; + sunxi_sdhci_timing_t timing_data = sdhci->timing_data; mmc_t *mmc = sdhci->mmc; /* disable mclk */ writel(0x0, mmc_host->mclkbase); if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { mmc_host->reg->ntsr |= (1 << 31); + printk_trace("SMHC: rntsr 0x%x\n", mmc_host->reg->ntsr); } else { mmc_host->reg->ntsr = 0x0; } @@ -421,7 +440,7 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { } } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { /* If using DDR mod to 4 */ - if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (sdhci->width == SMHC_WIDTH_8BIT)) { + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (mmc->bus_width == SMHC_WIDTH_8BIT)) { mmc_host->mod_clk = clk * 4; } else { mmc_host->mod_clk = clk * 2; @@ -440,7 +459,7 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { } } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { /* If using DDR mod to 4 */ - if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (sdhci->width == SMHC_WIDTH_8BIT)) { + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (mmc->bus_width == SMHC_WIDTH_8BIT)) { mmc->clock = sunxi_sdhci_get_mclk(sdhci) / 4; } else { mmc->clock = sunxi_sdhci_get_mclk(sdhci) / 2; @@ -448,10 +467,11 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { } /* Set host clock */ mmc_host->clock = mmc->clock; - printk_trace("SMHC: get round clk %lu, mod_clk %lu", mmc->clock, mmc_host->mod_clk); + printk_trace("SMHC: get round clk %luHz, mod_clk %luHz\n", mmc->clock, mmc_host->mod_clk); /* enable mclk */ writel(readl(mmc_host->mclkbase) | (1U << 31), mmc_host->mclkbase); + printk_trace("SMHC: mclkbase 0x%x\n", readl(mmc_host->mclkbase)); /* Configure SMHC_CLKDIV to open clock for devices */ reg_val = mmc_host->reg->clkcr; @@ -462,7 +482,7 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { } } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { /* If using DDR mod to 4 */ - if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (sdhci->width == SMHC_WIDTH_8BIT)) { + if ((mmc->speed_mode == MMC_HSDDR52_DDR50) && (mmc->bus_width == SMHC_WIDTH_8BIT)) { reg_val |= 0x1; } } @@ -473,28 +493,28 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { } /* config delay for mmc device */ - timing_data->freq_id = MMC_CLK_25M; + timing_data.freq_id = MMC_CLK_25M; switch (clk) { case 0 ... 400000: - timing_data->freq_id = MMC_CLK_400K; + timing_data.freq_id = MMC_CLK_400K; break; case 400001 ... 26000000: - timing_data->freq_id = MMC_CLK_25M; + timing_data.freq_id = MMC_CLK_25M; break; case 26000001 ... 52000000: - timing_data->freq_id = MMC_CLK_50M; + timing_data.freq_id = MMC_CLK_50M; break; case 52000001 ... 100000000: - timing_data->freq_id = MMC_CLK_100M; + timing_data.freq_id = MMC_CLK_100M; break; case 100000001 ... 150000000: - timing_data->freq_id = MMC_CLK_150M; + timing_data.freq_id = MMC_CLK_150M; break; case 150000001 ... 200000000: - timing_data->freq_id = MMC_CLK_200M; + timing_data.freq_id = MMC_CLK_200M; break; default: - timing_data->freq_id = MMC_CLK_25M; + timing_data.freq_id = MMC_CLK_25M; break; } sunxi_sdhci_config_delay(sdhci); @@ -512,7 +532,7 @@ static int sunxi_sdhci_clock_mode(sdhci_t *sdhci, uint32_t clk) { * @param clk Clock frequency. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_config_clock(sdhci_t *sdhci, uint32_t clk) { +static int sunxi_sdhci_config_clock(sunxi_sdhci_t *sdhci, uint32_t clk) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = sdhci->mmc; @@ -562,7 +582,7 @@ static int sunxi_sdhci_config_clock(sdhci_t *sdhci, uint32_t clk) { * @param sdhci Pointer to the SDHC controller structure. * @param status Boolean indicating whether to enable (true) or disable (false) DDR mode. */ -static void sunxi_sdhci_ddr_mode_set(sdhci_t *sdhci, bool status) { +static void sunxi_sdhci_ddr_mode_set(sunxi_sdhci_t *sdhci, bool status) { uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; @@ -597,7 +617,7 @@ static void sunxi_sdhci_ddr_mode_set(sdhci_t *sdhci, bool status) { * @param sdhci Pointer to the SDHC controller structure. * @param status Boolean indicating whether to enable (true) or disable (false) HS400 mode. */ -static void sunxi_sdhci_hs400_mode_set(sdhci_t *sdhci, bool status) { +static void sunxi_sdhci_hs400_mode_set(sunxi_sdhci_t *sdhci, bool status) { uint32_t reg_dsbd_val = 0x0, reg_csdc_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; @@ -640,51 +660,51 @@ static void sunxi_sdhci_hs400_mode_set(sdhci_t *sdhci, bool status) { * * @param sdhci Pointer to the SDHC controller structure. */ -static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { - sunxi_sdhci_pinctrl_t *sdhci_pins = sdhci->pinctrl; +static void sunxi_sdhci_pin_config(sunxi_sdhci_t *sdhci) { + sunxi_sdhci_pinctrl_t sdhci_pins = sdhci->pinctrl; // Initialize and configure GPIO pins for clock, command, and data lines - sunxi_gpio_init(sdhci_pins->gpio_clk.pin, sdhci_pins->gpio_clk.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_clk.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_clk.pin, sdhci_pins.gpio_clk.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_clk.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_cmd.pin, sdhci_pins->gpio_cmd.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_cmd.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_cmd.pin, sdhci_pins.gpio_cmd.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_cmd.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_d0.pin, sdhci_pins->gpio_d0.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d0.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d0.pin, sdhci_pins.gpio_d0.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d0.pin, GPIO_PULL_UP); // Initialize and configure GPIO pins for 4-bit MMC data bus if applicable if (sdhci->width > SMHC_WIDTH_1BIT) { - sunxi_gpio_init(sdhci_pins->gpio_d1.pin, sdhci_pins->gpio_d1.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d1.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d1.pin, sdhci_pins.gpio_d1.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d1.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_d2.pin, sdhci_pins->gpio_d2.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d2.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d2.pin, sdhci_pins.gpio_d2.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d2.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_d3.pin, sdhci_pins->gpio_d3.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d3.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d3.pin, sdhci_pins.gpio_d3.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d3.pin, GPIO_PULL_UP); } // Initialize and configure GPIO pins for 8-bit MMC data bus if applicable if (sdhci->width > SMHC_WIDTH_4BIT) { - sunxi_gpio_init(sdhci_pins->gpio_d4.pin, sdhci_pins->gpio_d4.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d4.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d4.pin, sdhci_pins.gpio_d4.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d4.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_d5.pin, sdhci_pins->gpio_d5.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d5.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d5.pin, sdhci_pins.gpio_d5.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d5.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_d6.pin, sdhci_pins->gpio_d6.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d6.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d6.pin, sdhci_pins.gpio_d6.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d6.pin, GPIO_PULL_UP); - sunxi_gpio_init(sdhci_pins->gpio_d7.pin, sdhci_pins->gpio_d7.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_d7.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_d7.pin, sdhci_pins.gpio_d7.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_d7.pin, GPIO_PULL_UP); // Additional GPIO pins for 8-bit MMC configuration - sunxi_gpio_init(sdhci_pins->gpio_ds.pin, sdhci_pins->gpio_ds.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_ds.pin, GPIO_PULL_DOWN); + sunxi_gpio_init(sdhci_pins.gpio_ds.pin, sdhci_pins.gpio_ds.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_ds.pin, GPIO_PULL_DOWN); - sunxi_gpio_init(sdhci_pins->gpio_rst.pin, sdhci_pins->gpio_rst.mux); - sunxi_gpio_set_pull(sdhci_pins->gpio_rst.pin, GPIO_PULL_UP); + sunxi_gpio_init(sdhci_pins.gpio_rst.pin, sdhci_pins.gpio_rst.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_rst.pin, GPIO_PULL_UP); } } @@ -697,7 +717,7 @@ static void sunxi_sdhci_pin_config(sdhci_t *sdhci) { * @param data Pointer to the MMC data structure containing transfer information. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { +static int sunxi_sunxi_sdhci_trans_data_cpu(sunxi_sdhci_t *sdhci, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; uint32_t timeout = time_us() + SMHC_TIMEOUT; uint32_t *buff; @@ -705,33 +725,20 @@ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { // Determine the buffer based on the direction of data transfer if (data->flags & MMC_DATA_READ) { buff = (uint32_t *) data->b.dest;// Destination buffer for read operation - } else { - buff = (uint32_t *) data->b.src;// Source buffer for write operation - } - - // Iterate over blocks of data to be transferred - for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { - // Wait until FIFO is empty for read operation, or full for write operation - while (((data->flags & MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) && (time_us() < timeout)) { - } - - // Check for timeout - if ((data->flags & MMC_DATA_READ) ? (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) : (mmc_host->reg->status & SMHC_STATUS_FIFO_FULL)) { - if (time_us() >= timeout) { - printk_error("SMHC: transfer %s by CPU failed, timeout\n", - (data->flags * MMC_DATA_READ) ? "read" : "write"); - return -1;// Return failure indication + for (size_t i = 0; i < ((data->blocksize * data->blocks) >> 2); i++) { + while (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY && (time_us() < timeout)) { } + if (mmc_host->reg->status & SMHC_STATUS_FIFO_EMPTY) { + if (time_us() >= timeout) { + printk_error("SMHC: read by CPU failed, timeout, index %u\n", i); + } + return -1; + } + buff[i] = mmc_host->reg->fifo; + timeout = time_us() + SMHC_TIMEOUT;// Update timeout for next iteration } - - // Perform read or write operation based on the direction of data transfer - if (data->flags & MMC_DATA_READ) { - buff[i] = readl(mmc_host->database);// Read data from FIFO to buffer - } else { - writel(buff[i], mmc_host->database);// Write data from buffer to FIFO - } - - timeout = time_us() + SMHC_TIMEOUT;// Update timeout for next iteration + } else { + buff = (uint32_t *) data->b.src;// Source buffer for write operation } return 0;// Return success indication @@ -747,7 +754,7 @@ static int sunxi_sdhci_trans_data_cpu(sdhci_t *sdhci, mmc_data_t *data) { * @param data Pointer to the MMC data structure containing transfer information. * @return void */ -static int sunxi_sdhci_trans_data_dma(sdhci_t *sdhci, mmc_data_t *data) { +static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; sunxi_sdhci_desc_t *pdes = mmc_host->sdhci_desc; uint8_t *buff; @@ -866,10 +873,12 @@ static int sunxi_sdhci_trans_data_dma(sdhci_t *sdhci, mmc_data_t *data) { * @param sdhci Pointer to the SDHC controller structure. * @return void */ -void sunxi_sdhci_set_ios(sdhci_t *sdhci) { +void sunxi_sdhci_set_ios(sunxi_sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = sdhci->mmc; + printk_trace("SMHC: ios setting bus:%u, speed %u\n", mmc->bus_width, mmc->clock); + // Configure clock and handle errors if (mmc->clock && sunxi_sdhci_config_clock(sdhci, mmc->clock)) { printk_error("SMHC: update clock failed\n"); @@ -878,17 +887,7 @@ void sunxi_sdhci_set_ios(sdhci_t *sdhci) { } /* Change bus width */ - switch (sdhci->width) { - case SMHC_WIDTH_8BIT: - mmc_host->reg->width = 2; - break; - case SMHC_WIDTH_4BIT: - mmc_host->reg->width = 1; - break; - default: - mmc_host->reg->width = 0; - break; - } + mmc_host->reg->width = mmc->bus_width; /* Set DDR mode */ if (mmc->speed_mode == MMC_HSDDR52_DDR50) { @@ -914,7 +913,7 @@ void sunxi_sdhci_set_ios(sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success, -1 on failure. */ -int sunxi_sdhci_core_init(sdhci_t *sdhci) { +int sunxi_sdhci_core_init(sunxi_sdhci_t *sdhci) { uint32_t reg_val = 0x0; uint32_t timeout = time_us() + SMHC_TIMEOUT; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; @@ -969,15 +968,14 @@ int sunxi_sdhci_core_init(sdhci_t *sdhci) { * @param data Pointer to the MMC data structure. * @return Returns 0 on success, -1 on failure. */ -int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { +int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - uint32_t cmdval = MMC_CMD_CMDVAL_MASK; + uint32_t cmdval = SMHC_CMD_START; uint32_t timeout = time_us() + SMHC_TIMEOUT; uint32_t status; + uint32_t reg_val; int ret = 0, error_code = 0; - uint8_t use_dma_status; - - printk_trace("SMHC: CMD%u 0x%x dlen:%u\n", cmd->cmdidx, cmd->cmdarg, data ? data->blkcnt * data->blksz : 0); + uint8_t use_dma_status = false; /* Check if have fatal error */ if (mmc_host->fatal_err) { @@ -987,7 +985,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { /* check card busy*/ if (cmd->resp_type & MMC_RSP_BUSY) { - printk_debug("SMHC: Card busy"); + printk_trace("SMHC: cmd %u check Card busy\n", cmd->cmdidx); } /* Check if stop or manual */ @@ -1012,18 +1010,14 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { * CMD[31] : Load cmd */ - if (cmd->cmdidx) { + if (!cmd->cmdidx) cmdval |= SMHC_CMD_SEND_INIT_SEQUENCE; - } - - - if (cmd->resp_type & MMC_RSP_PRESENT) { + if (cmd->resp_type & MMC_RSP_PRESENT) cmdval |= SMHC_CMD_RESP_EXPIRE; - if (cmd->resp_type & MMC_RSP_136) - cmdval |= SMHC_CMD_LONG_RESPONSE; - if (cmd->resp_type & MMC_RSP_CRC) - cmdval |= SMHC_CMD_CHECK_RESPONSE_CRC; - } + if (cmd->resp_type & MMC_RSP_136) + cmdval |= SMHC_CMD_LONG_RESPONSE; + if (cmd->resp_type & MMC_RSP_CRC) + cmdval |= SMHC_CMD_CHECK_RESPONSE_CRC; if (data) { /* Check data desc align */ @@ -1049,6 +1043,8 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { } } + printk_trace("SMHC: CMD: %u(0x%08x), arg: 0x%x, dlen:%u\n", cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg, data ? data->blocks * data->blocksize : 0); + mmc_host->reg->arg = cmd->cmdarg; if (!data) { @@ -1060,18 +1056,17 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { * STATREG[2] : FIFO empty * STATREG[3] : FIFO full */ - if (data) { printk_trace("SMHC: transfer data %lu bytes\n", data->blocksize * data->blocks); if (data->blocksize * data->blocks > 512) { use_dma_status = true; - mmc_host->reg->gctrl &= (~MMC_CMD_CMDVAL_MASK); - ret = sunxi_sdhci_trans_data_dma(sdhci, data); - mmc_host->reg->cmd = (cmdval & cmd->cmdidx); + mmc_host->reg->gctrl &= ~SMHC_GCTRL_ACCESS_BY_AHB; + ret = sunxi_sunxi_sdhci_trans_data_dma(sdhci, data); + mmc_host->reg->cmd = (cmdval | cmd->cmdidx); } else { - mmc_host->reg->gctrl |= MMC_CMD_CMDVAL_MASK; - mmc_host->reg->cmd = (cmdval & cmd->cmdidx); - ret = sunxi_sdhci_trans_data_cpu(sdhci, data); + mmc_host->reg->gctrl |= SMHC_GCTRL_ACCESS_BY_AHB; + mmc_host->reg->cmd = (cmdval | cmd->cmdidx); + ret = sunxi_sunxi_sdhci_trans_data_cpu(sdhci, data); } if (ret) { @@ -1092,7 +1087,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { if (!error_code) { error_code = 0xffffffff; } - printk_error("SMHC: cmd 0x%08x timeout, error %08x", cmd->cmdidx, error_code); + printk_error("SMHC: cmd 0x%08x timeout, error %08x\n", cmd->cmdidx, error_code); goto out; } } while (!(status & SMHC_RINT_COMMAND_DONE)); @@ -1107,7 +1102,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { if (!error_code) { error_code = 0xffffffff; } - printk_error("SMHC: data timeout, error %08x", error_code); + printk_error("SMHC: data timeout, error %08x\n", error_code); goto out; } @@ -1129,7 +1124,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { if (!error_code) { error_code = 0xffffffff; } - printk_error("SMHC: wait dma timeout, error %08x", error_code); + printk_error("SMHC: wait dma timeout, error %08x\n", error_code); goto out; } done = status & BIT(1); @@ -1146,7 +1141,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { if (!error_code) { error_code = 0xffffffff; } - printk_error("SMHC: busy timeout, status %08x", status); + printk_error("SMHC: busy timeout, status %08x\n", status); goto out; } } while (status & SMHC_STATUS_CARD_DATA_BUSY); @@ -1157,13 +1152,16 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { cmd->response[1] = mmc_host->reg->resp2; cmd->response[2] = mmc_host->reg->resp1; cmd->response[3] = mmc_host->reg->resp0; + printk_trace("SMHC: resp 0x%08x 0x%08x 0x%08x 0x%08x\n", + cmd->response[3], cmd->response[2], cmd->response[1], cmd->response[0]); } else { cmd->response[0] = mmc_host->reg->resp0; + printk_trace("SMHC: resp 0x%08x\n", cmd->response[0]); } out: if (data && use_dma_status) { - /* IDMASTAREG + /* IDMASTAREG Reset controller status * IDST[0] : idma tx int * IDST[1] : idma rx int * IDST[2] : idma fatal bus error @@ -1189,7 +1187,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { } } sunxi_sdhci_update_clk(sdhci); - printk_error("SMHC: CMD 0x%08x, error 0x%08x", cmd->cmdidx, error_code); + printk_error("SMHC: CMD 0x%08x, error 0x%08x\n", cmd->cmdidx, error_code); } mmc_host->reg->rint = 0xffffffff; @@ -1209,7 +1207,7 @@ int sunxi_sdhci_xfer(sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success. */ -int sunxi_sdhci_update_phase(sdhci_t *sdhci) { +int sunxi_sdhci_update_phase(sunxi_sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; // Check if timing mode is mode 1 @@ -1234,18 +1232,21 @@ int sunxi_sdhci_update_phase(sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC structure. * @return Returns 0 on success, -1 on failure. */ -int sunxi_sdhci_init(sdhci_t *sdhci) { - sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - mmc_t *mmc = sdhci->mmc; - +int sunxi_sdhci_init(sunxi_sdhci_t *sdhci) { /* Check if controller ID is correct */ if (sdhci->id > MMC_CONTROLLER_2) { printk_error("SMHC: Unsupported MAX Controller reached\n"); return -1; } - memset(mmc_host, 0, sizeof(sunxi_sdhci_host_t)); - memset(mmc, 0, sizeof(mmc_t)); + /* init resource */ + memset(&g_mmc_host, 0, sizeof(sunxi_sdhci_host_t)); + sdhci->mmc_host = &g_mmc_host; + sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; + + memset(&g_mmc, 0, sizeof(mmc_t)); + sdhci->mmc = &g_mmc; + mmc_t *mmc = sdhci->mmc; /* Set timing mode based on controller ID */ if (sdhci->id == MMC_CONTROLLER_0) { @@ -1275,7 +1276,6 @@ int sunxi_sdhci_init(sdhci_t *sdhci) { /* Set register addresses */ mmc_host->reg = (sdhci_reg_t *) sdhci->reg_base; - mmc_host->database = (uint32_t) sdhci->reg_base + MMC_REG_FIFO_OS; mmc_host->hclkbase = sdhci->clk_ctrl_base; mmc_host->hclkrst = sdhci->clk_ctrl_base; mmc_host->mclkbase = sdhci->clk_base; @@ -1286,3 +1286,41 @@ int sunxi_sdhci_init(sdhci_t *sdhci) { return 0; } + +/** + * @brief Dump the contents of the SDHCI registers. + * + * This function dumps the contents of the SDHCI registers for a given SD card host controller. + * + * @param sdhci A pointer to the structure representing the SD card host controller. + * @return void + * + * @note This function is useful for debugging and analyzing the state of the SD card controller. + */ +void sunxi_sdhci_dump_reg(sunxi_sdhci_t *sdhci) { + sdhci_reg_t *reg = sdhci->mmc_host->reg; + printk_trace("=========SDHCI%d REG========\n", sdhci->id); + printk_trace("gctrl 0x%x\n", reg->gctrl); + printk_trace("clkcr 0x%x\n", reg->clkcr); + printk_trace("timeout 0x%x\n", reg->timeout); + printk_trace("width 0x%x\n", reg->width); + printk_trace("blksz 0x%x\n", reg->blksz); + printk_trace("bytecnt 0x%x\n", reg->bytecnt); + printk_trace("cmd 0x%x\n", reg->cmd); + printk_trace("arg 0x%x\n", reg->arg); + printk_trace("resp0 0x%x\n", reg->resp0); + printk_trace("resp1 0x%x\n", reg->resp1); + printk_trace("resp2 0x%x\n", reg->resp2); + printk_trace("resp3 0x%x\n", reg->resp3); + printk_trace("imask 0x%x\n", reg->imask); + printk_trace("mint 0x%x\n", reg->mint); + printk_trace("rint 0x%x\n", reg->rint); + printk_trace("status 0x%x\n", reg->status); + printk_trace("ftrglevel 0x%x\n", reg->ftrglevel); + printk_trace("funcsel 0x%x\n", reg->funcsel); + printk_trace("dmac 0x%x\n", reg->dmac); + printk_trace("dlba 0x%x\n", reg->dlba); + printk_trace("idst 0x%x\n", reg->idst); + printk_trace("idie 0x%x\n", reg->idie); + printk_trace("\n\n"); +} diff --git a/src/drivers/sys-spi.c b/src/drivers/sys-spi.c index 0d1a48dc..81723de7 100644 --- a/src/drivers/sys-spi.c +++ b/src/drivers/sys-spi.c @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 */ +#define LOG_LEVEL_DEFAULT LOG_LEVEL_INFO + #include #include #include From eda46876d7279adfe259314203addb013b625b65 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Wed, 5 Jun 2024 20:59:54 +0800 Subject: [PATCH 08/12] [driver] add basic mmc driver WIP 3/4 --- board/avaota-a1/board.c | 7 --- board/avaota-a1/extlinux_boot/main.c | 8 +-- include/drivers/mmc/sys-mmc.h | 78 +++++++++++++++++++++++++--- include/drivers/mmc/sys-sdhci.h | 2 +- include/log.h | 12 +++++ src/drivers/mmc/sys-mmc.c | 66 ++++++++++++++--------- src/drivers/mmc/sys-sdhci.c | 13 ++++- 7 files changed, 141 insertions(+), 45 deletions(-) diff --git a/board/avaota-a1/board.c b/board/avaota-a1/board.c index 8e39aa28..fcfbe561 100644 --- a/board/avaota-a1/board.c +++ b/board/avaota-a1/board.c @@ -98,13 +98,6 @@ sunxi_sdhci_t sdhci2 = { .gpio_ds = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX3}, .gpio_rst = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX3}, }, - .timing_data = { - .freq_id = MMC_CLK_25M, - .odly = 0, - .sdly = 0, - .spd_md_id = MMC_DS26_SDR12, - .auto_timing = TRUE, - }, }; diff --git a/board/avaota-a1/extlinux_boot/main.c b/board/avaota-a1/extlinux_boot/main.c index ca0a8684..07714bde 100644 --- a/board/avaota-a1/extlinux_boot/main.c +++ b/board/avaota-a1/extlinux_boot/main.c @@ -760,15 +760,15 @@ int main(void) { strcpy(image.splash_filename, CONFIG_SPLASH_FILENAME); /* Initialize the SD host controller. */ - if (sunxi_sdhci_init(&sdhci2) != 0) { - printk_error("SMHC: %s controller init failed\n", sdhci2.name); + if (sunxi_sdhci_init(&sdhci0) != 0) { + printk_error("SMHC: %s controller init failed\n", sdhci0.name); LCD_ShowString(0, 92, "SMHC: SDC0 controller init failed", SPI_LCD_COLOR_GREEN, SPI_LCD_COLOR_BLACK, 12); goto _fail; } else { - printk_info("SMHC: %s controller initialized\n", sdhci2.name); + printk_info("SMHC: %s controller initialized\n", sdhci0.name); } - sunxi_mmc_init(&sdhci2); + sunxi_mmc_init(&sdhci0); /* Initialize the SD card and check if initialization is successful. */ if (sdmmc_init(&card0, &sdhci0) != 0) { diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h index 92772ab8..977d2196 100644 --- a/include/drivers/mmc/sys-mmc.h +++ b/include/drivers/mmc/sys-mmc.h @@ -142,12 +142,78 @@ enum { /* * EXT_CSD fields */ -#define EXT_CSD_PART_CONF 179 /* R/W */ -#define EXT_CSD_BUS_WIDTH 183 /* R/W */ -#define EXT_CSD_HS_TIMING 185 /* R/W */ -#define EXT_CSD_CARD_TYPE 196 /* RO */ -#define EXT_CSD_REV 192 /* RO */ -#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */ +#define EXT_CSD_FLUSH_CACHE 32 /* W */ +#define EXT_CSD_CACHE_CTRL 33 /* R/W */ +#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */ +#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */ +#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */ +#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */ +#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */ +#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */ +#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ +#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ +#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */ +#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */ +#define EXT_CSD_HPI_MGMT 161 /* R/W */ +#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ +#define EXT_CSD_BKOPS_EN 163 /* R/W */ +#define EXT_CSD_BKOPS_START 164 /* W */ +#define EXT_CSD_SANITIZE_START 165 /* W */ +#define EXT_CSD_WR_REL_PARAM 166 /* RO */ +#define EXT_CSD_RPMB_MULT 168 /* RO */ +#define EXT_CSD_FW_CONFIG 169 /* R/W */ +#define EXT_CSD_BOOT_WP 173 /* R/W */ +#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ +#define EXT_CSD_PART_CONFIG 179 /* R/W */ +#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ +#define EXT_CSD_STROBE_SUPPORT 184 /* RO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_POWER_CLASS 187 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */ +#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */ +#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */ +#define EXT_CSD_PWR_CL_52_195 200 /* RO */ +#define EXT_CSD_PWR_CL_26_195 201 /* RO */ +#define EXT_CSD_PWR_CL_52_360 202 /* RO */ +#define EXT_CSD_PWR_CL_26_360 203 /* RO */ +#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ +#define EXT_CSD_S_A_TIMEOUT 217 /* RO */ +#define EXT_CSD_REL_WR_SEC_C 222 /* RO */ +#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */ +#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */ +#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */ +#define EXT_CSD_BOOT_MULT 226 /* RO */ +#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */ +#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */ +#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */ +#define EXT_CSD_TRIM_MULT 232 /* RO */ +#define EXT_CSD_PWR_CL_200_195 236 /* RO */ +#define EXT_CSD_PWR_CL_200_360 237 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */ +#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */ +#define EXT_CSD_BKOPS_STATUS 246 /* RO */ +#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */ +#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ +#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ +#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ +#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ +#define EXT_CSD_PRE_EOL_INFO 267 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */ +#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */ +#define EXT_CSD_CMDQ_DEPTH 307 /* RO */ +#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */ +#define EXT_CSD_SUPPORTED_MODE 493 /* RO */ +#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ +#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ +#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ +#define EXT_CSD_MAX_PACKED_READS 501 /* RO */ +#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */ +#define EXT_CSD_HPI_FEATURES 503 /* * EXT_CSD field definitions diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index 504d4263..d89ed25c 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -27,7 +27,7 @@ extern "C" { #define MMC_REG_FIFO_OS (0x200) #define SMHC_TIMEOUT 0xfffff -#define SMHC_DMA_TIMEOUT 0xfffff +#define SMHC_DMA_TIMEOUT 0xffffff #define SMHC_WAITBUSY_TIMEOUT 0xfffff #define SMHC_DATA_TIMEOUT 0xfffff #define SMHC_RESP_TIMEOUT 0xff diff --git a/include/log.h b/include/log.h index 8aad153f..af997baa 100644 --- a/include/log.h +++ b/include/log.h @@ -113,6 +113,18 @@ void uart_printf(const char *fmt, ...); */ int printf(const char *fmt, ...); +/** + * @brief Dumps memory content in hexadecimal format. + * + * This function dumps the content of memory starting from the specified + * address in hexadecimal format. It prints the hexadecimal values of memory + * contents and ASCII characters corresponding to printable characters. + * + * @param start_addr The starting address of the memory region to dump. + * @param count The number of bytes to dump. + */ +void dump_hex(uint32_t start_addr, uint32_t count); + #ifdef __cplusplus } #endif// __cplusplus diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index 6bdef862..aa870583 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -628,7 +628,7 @@ static int sunxi_mmc_mmc_change_freq(sunxi_sdhci_t *sdhci) { return err; } - cardtype = ext_csd[196] & 0xff;///< Extract card type from the extended CSD data + cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xff;///< Extract card type from the extended CSD data // Retry switching to high-speed mode for certain types of cards do { @@ -652,7 +652,7 @@ static int sunxi_mmc_mmc_change_freq(sunxi_sdhci_t *sdhci) { } // Check if high-speed mode is supported - if (!ext_csd[185]) + if (!ext_csd[EXT_CSD_HS_TIMING]) return 0; // Determine the type of high-speed mode and update card capabilities @@ -1297,13 +1297,6 @@ static int sunxi_mmc_send_if_cond(sunxi_sdhci_t *sdhci) { */ static void sunxi_mmc_show_card_info(sunxi_sdhci_t *sdhci) { mmc_t *mmc = sdhci->mmc; - - printk_debug("SD/MMC card at the '%s' host controller:\r\n", sdhci->name); - printk_debug(" Attached is a %s card\r\n", mmc->version & SD_VERSION_SD ? "SD" : "MMC"); - if (mmc->capacity / (f64) 1000000000.0 < 4) - printk_info(" Capacity: %.1fMB\n", (f32) ((f64) mmc->capacity / (f64) 1000000.0)); - else - printk_info(" Capacity: %.1fGB\n", (f32) ((f64) mmc->capacity / (f64) 1000000000.0)); if (mmc->high_capacity) printk_debug(" High capacity card\r\n"); printk_debug(" CID: %08X-%08X-%08X-%08X\r\n", mmc->cid[0], mmc->cid[1], mmc->cid[2], mmc->cid[3]); @@ -1401,21 +1394,27 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { switch (version) { case 0: mmc->version = MMC_VERSION_1_2; + strver = "1.2"; break; case 1: mmc->version = MMC_VERSION_1_4; + strver = "1.4"; break; case 2: mmc->version = MMC_VERSION_2_2; + strver = "2.2"; break; case 3: mmc->version = MMC_VERSION_3; + strver = "3.0"; break; case 4: mmc->version = MMC_VERSION_4; + strver = "4.0"; break; default: mmc->version = MMC_VERSION_1_2; + strver = "1.2"; break; } } @@ -1471,7 +1470,7 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { /* TODO MMC Timing update */ } - sunxi_mmc_set_clock(sdhci, mmc->tran_speed); + sunxi_mmc_set_clock(sdhci, 25000000); /* * For SD, its erase group is always one sector @@ -1484,7 +1483,7 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { err = sunxi_mmc_send_ext_csd(sdhci, ext_csd); if (!err) { /* update mmc version */ - switch (ext_csd[192]) { + switch (ext_csd[EXT_CSD_REV]) { case 0: mmc->version = MMC_VERSION_4; strver = "4.0"; @@ -1520,17 +1519,12 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { } } - if (!err & (ext_csd[192] >= 2)) { - /* - * According to the JEDEC Standard, the value of - * ext_csd's capacity is valid if the value is more - * than 2GB - */ - capacity = ext_csd[212] << 0 | ext_csd[213] << 8 | - ext_csd[214] << 16 | ext_csd[215] << 24; - capacity *= 512; - if ((capacity >> 20) > 2 * 1024) - mmc->capacity = capacity; + if (!err & (ext_csd[EXT_CSD_REV] >= 2)) { + mmc->capacity = ext_csd[EXT_CSD_SEC_CNT] << 0 | + ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | + ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | + ext_csd[EXT_CSD_SEC_CNT + 3] << 24; + mmc->capacity *= 1 << UNSTUFF_BITS(mmc->csd, 80, 4); } /* @@ -1539,7 +1533,7 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { * the group size from the csd value. */ if (ext_csd[175]) - mmc->erase_grp_size = ext_csd[224] * 512 * 1024; + mmc->erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 512 * 1024; else { int erase_gsz, erase_gmul; erase_gsz = (mmc->csd[2] & 0x00007c00) >> 10; @@ -1548,8 +1542,8 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { } /* store the partition info of emmc */ - if (ext_csd[160] & PART_SUPPORT) { - mmc->part_config = ext_csd[179]; + if (ext_csd[EXT_CSD_PARTITION_SUPPORT] & PART_SUPPORT) { + mmc->part_config = ext_csd[EXT_CSD_PART_CONFIG]; } } @@ -1696,6 +1690,14 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { mmc->blksz = mmc->read_bl_len; mmc->lba = mmc->capacity >> 9; + printk_debug("SD/MMC card at the '%s' host controller:\r\n", sdhci->name); + printk_debug(" Attached is a %s%s card\r\n", mmc->version & SD_VERSION_SD ? "SD" : "MMC", + mmc->version & SD_VERSION_SD ? "" : strver); + if (mmc->capacity / (f64) 1000000000.0 < 4) + printk_info(" Capacity: %.1fMB\n", (f32) ((f64) mmc->capacity / (f64) 1000000.0)); + else + printk_info(" Capacity: %.1fGB\n", (f32) ((f64) mmc->capacity / (f64) 1000000000.0)); + sunxi_mmc_show_card_info(sdhci); return 0; @@ -1765,5 +1767,19 @@ int sunxi_mmc_init(void *sdhci_hdl) { printk_error("SMHC%d: SD/MMC Probe failed, err %d\n", sdhci->id, err); } +#define CONFIG_SDMMC_SPEED_TEST_SIZE 4096 + + memset((void *) 0x40000000, 0xff, 0x20000); + + uint32_t start = time_ms(); + sunxi_mmc_read_blocks(sdhci, (uint8_t *) (0x40000000), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); + uint32_t test_time = time_ms() - start; + + printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + dump_hex(0x40000000, 0x200); + return err; } \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index 087f2ea1..34a9fa1f 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -796,6 +796,8 @@ static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *da } else { pdes[des_idx].next_desc_addr = ((size_t) &pdes[des_idx + 1]) >> 2; } + +#ifdef SMHC_DMA_TRACE printk_trace("SMHC: frag %d, remain %d, des[%d] = 0x%08x:" " [0] = 0x%08x, [1] = 0x%08x, [2] = 0x%08x, [3] = 0x%08x\n", i, remain, des_idx, (uint32_t) (&pdes[des_idx]), @@ -803,6 +805,7 @@ static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *da (uint32_t) ((uint32_t *) &pdes[des_idx])[1], (uint32_t) ((uint32_t *) &pdes[des_idx])[2], (uint32_t) ((uint32_t *) &pdes[des_idx])[3]); +#endif// SMHC_DMA_TRACE } dsb(); @@ -825,6 +828,7 @@ static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *da /* Enable DMA */ + mmc_host->reg->idst = 0x337; mmc_host->reg->gctrl |= (SMHC_GCTRL_DMA_ENABLE | SMHC_GCTRL_DMA_RESET); timeout = time_us() + SMHC_TIMEOUT; @@ -859,7 +863,7 @@ static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *da mmc_host->reg->dlba = (uint32_t) pdes >> 2; /* burst-16, rx/tx trigger level=15/240 */ - mmc_host->reg->ftrglevel = ((0x3 << 28) | (15 << 16) | 240); + mmc_host->reg->ftrglevel = ((3 << 28) | (15 << 16) | 240); return 0; } @@ -1096,13 +1100,17 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { uint32_t done = false; timeout = time_us() + (use_dma_status ? SMHC_DMA_TIMEOUT : SMHC_TIMEOUT); do { + sunxi_sdhci_dump_reg(sdhci); status = mmc_host->reg->rint; if ((time_us() > timeout) || (status & SMHC_RINT_INTERRUPT_ERROR_BIT)) { error_code = status & SMHC_RINT_INTERRUPT_ERROR_BIT; if (!error_code) { error_code = 0xffffffff; } - printk_error("SMHC: data timeout, error %08x\n", error_code); + if (time_us() > timeout) + printk_error("SMHC: data timeout, error %08x\n", error_code); + else + printk_error("SMHC: status get interrupt, error 0x%08x\n", error_code); goto out; } @@ -1178,6 +1186,7 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { } if (error_code) { + dump_hex(sdhci->reg_base, 0x200); mmc_host->reg->gctrl = SMHC_GCTRL_HARDWARE_RESET; timeout = time_us() + SMHC_TIMEOUT; while (mmc_host->reg->gctrl & SMHC_GCTRL_HARDWARE_RESET) { From 8d1a22d672657a465b74771ba12695f25a71dbf1 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Thu, 6 Jun 2024 10:23:39 +0800 Subject: [PATCH 09/12] [board] support parram in --- board/100ask-ros/board.c | 37 +- board/100ask-ros/init_dram/main.c | 6 +- board/100ask-ros/payloads/init_dram_bin.c | 2412 +++++++++++---------- board/100ask-ros/smhc_test/main.c | 4 +- board/100ask-ros/syter_boot/main.c | 5 +- include/drivers/sys-rtc.h | 14 + payloads | 2 +- src/drivers/sun50iw10/sys-dram.c | 16 +- src/drivers/sun55iw3/sys-dram.c | 12 - src/drivers/sys-rtc.c | 59 + 10 files changed, 1395 insertions(+), 1172 deletions(-) diff --git a/board/100ask-ros/board.c b/board/100ask-ros/board.c index ee5a7bce..f39895d4 100644 --- a/board/100ask-ros/board.c +++ b/board/100ask-ros/board.c @@ -78,6 +78,41 @@ void clean_syterkit_data(void) { printk_info("free interrupt ok...\n"); } +const uint32_t dram_para[32] = { + 0x318, + 0x8, + 0x7070707, + 0xd0d0d0d, + 0xe0e, + 0xd0a050c, + 0x30fa, + 0x8001000, + 0x0, + 0x34, + 0x1b, + 0x33, + 0x3, + 0x0, + 0x0, + 0x4, + 0x72, + 0x0, + 0x7, + 0x0, + 0x0, + 0x26, + 0x6060606, + 0x4040404, + 0x0, + 0x74000000, + 0x48000000, + 0x273333, + 0x201c181f, + 0x13151513, + 0x7521, + 0x2023211f, +}; + #define RTC_DATA_COLD_START (7) #define CPUS_CODE_LENGTH (0x1000) #define CPUS_VECTOR_LENGTH (0x4000) @@ -89,7 +124,7 @@ int ar100s_gpu_fix(void) { uint32_t value; uint32_t id = (readl(SUNXI_SYSCRL_BASE + 0x24)) & 0x07; printk_debug("SUNXI_SYSCRL_BASE + 0x24 = 0x%08x, id = %d, RTC_DATA_COLD_START = %d\n", - readl(SUNXI_SYSCRL_BASE + 0x24), id, rtc_read_data(RTC_DATA_COLD_START)); + readl(SUNXI_SYSCRL_BASE + 0x24), id, rtc_read_data(RTC_DATA_COLD_START)); if (((id == 0) || (id == 3) || (id == 4) || (id == 5))) { if (rtc_read_data(RTC_DATA_COLD_START) == 0) { rtc_write_data(RTC_DATA_COLD_START, 0x1); diff --git a/board/100ask-ros/init_dram/main.c b/board/100ask-ros/init_dram/main.c index 27a7689b..33370fd4 100644 --- a/board/100ask-ros/init_dram/main.c +++ b/board/100ask-ros/init_dram/main.c @@ -2,8 +2,8 @@ #include #include -#include #include +#include #include @@ -14,7 +14,7 @@ #include extern sunxi_serial_t uart_dbg; - +extern uint32_t dram_para[32]; extern sunxi_i2c_t i2c_pmu; static void set_pmu_fin_voltage(char *power_name, uint32_t voltage) { @@ -52,7 +52,7 @@ int main(void) { pmu_axp2202_dump(&i2c_pmu); - printk_info("DRAM: DRAM Size = %dMB\n", sunxi_dram_init(NULL)); + printk_info("DRAM: DRAM Size = %dMB\n", sunxi_dram_init(&dram_para)); sunxi_clk_dump(); diff --git a/board/100ask-ros/payloads/init_dram_bin.c b/board/100ask-ros/payloads/init_dram_bin.c index f1141aed..ff82b535 100644 --- a/board/100ask-ros/payloads/init_dram_bin.c +++ b/board/100ask-ros/payloads/init_dram_bin.c @@ -1,9 +1,9 @@ -const unsigned char __attribute__((section(".init_dram_bin"))) init_dram_bin[19789] = { +const unsigned char __attribute__((section(".init_dram_bin"))) init_dram_bin[21732] = { 0xFF, 0xFF, 0xFF, 0xEA, 0x00, 0x40, 0x2D, 0xE9, 0x05, 0x00, 0x00, 0xEB, 0x10, 0x0F, 0x11, 0xEE, 0x01, 0x0A, 0x80, 0xE3, 0x10, 0x0F, 0x01, 0xEE, 0x15, 0x01, 0x00, 0xFB, 0x00, 0x40, 0xBD, 0xE8, 0x0E, 0xF0, 0xA0, 0xE1, 0x18, 0x00, 0x9F, 0xE5, 0x18, 0x10, 0x9F, 0xE5, 0x00, 0x20, 0xA0, 0xE3, 0x00, 0x20, 0x80, 0xE5, 0x04, 0x00, 0x80, 0xE2, 0x01, 0x00, 0x50, 0xE1, 0xFB, 0xFF, 0xFF, 0x1A, - 0x0E, 0xF0, 0xA0, 0xE1, 0x50, 0x36, 0x04, 0x00, 0x54, 0x36, 0x04, 0x00, 0x01, 0x00, 0x50, 0xE1, + 0x0E, 0xF0, 0xA0, 0xE1, 0xE4, 0x3D, 0x04, 0x00, 0xEC, 0x3D, 0x04, 0x00, 0x01, 0x00, 0x50, 0xE1, 0x0E, 0xF0, 0xA0, 0x01, 0x11, 0x40, 0x2D, 0xE9, 0x04, 0x20, 0x52, 0xE2, 0x29, 0x00, 0x00, 0xBA, 0x03, 0xC0, 0x10, 0xE2, 0x30, 0x00, 0x00, 0x1A, 0x03, 0xC0, 0x11, 0xE2, 0x3A, 0x00, 0x00, 0x1A, 0x1C, 0x20, 0x52, 0xE2, 0xE0, 0x01, 0x2D, 0xE9, 0x0A, 0x00, 0x00, 0xBA, 0x1F, 0xC0, 0x10, 0xE2, @@ -70,1173 +70,1295 @@ const unsigned char __attribute__((section(".init_dram_bin"))) init_dram_bin[197 0xF7, 0xFF, 0xFF, 0xBA, 0x02, 0x00, 0x53, 0xE3, 0x01, 0x10, 0xCC, 0xB4, 0x01, 0x10, 0xCC, 0xD4, 0x01, 0x10, 0xCC, 0xE4, 0x03, 0x20, 0x82, 0xE0, 0xCB, 0xFF, 0xFF, 0xEA, 0x4F, 0xF0, 0xE0, 0x63, 0xC3, 0xF8, 0x08, 0x01, 0xBF, 0xF3, 0x4F, 0x8F, 0xBF, 0xF3, 0x6F, 0x8F, 0xD3, 0xF8, 0x08, 0x21, - 0x90, 0x42, 0xF5, 0xD1, 0x70, 0x47, 0x10, 0xB5, 0xA0, 0xB0, 0x00, 0xF0, 0x2F, 0xF8, 0x80, 0x22, - 0x0A, 0x49, 0x68, 0x46, 0x00, 0xF0, 0x4A, 0xF8, 0x69, 0x46, 0x00, 0x20, 0x03, 0xF0, 0xB8, 0xFA, - 0x01, 0x46, 0x04, 0x46, 0x06, 0x48, 0x00, 0xF0, 0x38, 0xF8, 0x0A, 0x20, 0x00, 0xF0, 0x5F, 0xF8, - 0x20, 0x46, 0xFF, 0xF7, 0xDB, 0xFF, 0x20, 0xB0, 0x10, 0xBD, 0x00, 0xBF, 0x14, 0x29, 0x04, 0x00, - 0x50, 0x2D, 0x04, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x02, 0x48, 0x00, 0xF0, 0x26, 0xF8, 0x00, 0x20, - 0x08, 0xBD, 0x00, 0xBF, 0x71, 0x2D, 0x04, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x02, 0x48, 0x00, 0xF0, - 0x1C, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x8B, 0x2D, 0x04, 0x00, 0x4F, 0xF0, 0xE0, 0x63, - 0xD3, 0xF8, 0x08, 0x31, 0x70, 0x47, 0x4F, 0xF0, 0xA0, 0x63, 0x5A, 0x69, 0x52, 0x06, 0xFC, 0xD5, - 0x18, 0x60, 0x70, 0x47, 0x0A, 0x29, 0x08, 0xB5, 0x02, 0xD1, 0x0D, 0x20, 0xFF, 0xF7, 0xF3, 0xFF, - 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x46, 0xFF, 0xF7, 0xEE, 0xBF, 0x0F, 0xB4, 0x04, 0xB0, 0x70, 0x47, - 0x01, 0x4B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEC, 0x03, 0x00, 0x01, 0x4B, 0x18, 0x47, - 0x70, 0x47, 0x00, 0xBF, 0x4C, 0xE9, 0x03, 0x00, 0x00, 0x20, 0x70, 0x47, 0x52, 0xEC, 0x0E, 0x3F, - 0x18, 0x21, 0x48, 0x43, 0x18, 0x18, 0x42, 0xF1, 0x00, 0x03, 0x52, 0xEC, 0x0E, 0x1F, 0x88, 0x42, - 0x73, 0xEB, 0x02, 0x02, 0xF9, 0xD2, 0x70, 0x47, 0xFF, 0xF7, 0xF0, 0xBF, 0x08, 0xB5, 0x51, 0xEC, - 0x0E, 0x0F, 0x45, 0xF6, 0xC0, 0x52, 0x00, 0x23, 0x03, 0xF0, 0x6E, 0xEC, 0x08, 0xBD, 0x38, 0xB5, - 0x04, 0x46, 0x4F, 0xF4, 0x7A, 0x70, 0x60, 0x43, 0xFF, 0xF7, 0xE0, 0xFF, 0xFF, 0xF7, 0xEE, 0xFF, - 0x05, 0x46, 0xFF, 0xF7, 0xEB, 0xFF, 0x43, 0x1B, 0xA3, 0x42, 0xFA, 0xD3, 0x38, 0xBD, 0x80, 0xEA, - 0x01, 0x20, 0x08, 0x23, 0x48, 0xF2, 0x05, 0x01, 0x42, 0x00, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x04, - 0x92, 0xB2, 0x4C, 0xBF, 0x82, 0xEA, 0x01, 0x00, 0x10, 0x46, 0x00, 0x2B, 0xF4, 0xD1, 0x70, 0x47, - 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x2C, 0x44, 0xFF, 0xF7, 0xE9, 0xFF, 0x44, 0xEA, 0x00, 0x40, - 0x38, 0xBD, 0x00, 0x00, 0x00, 0x23, 0x73, 0xB5, 0x01, 0x93, 0x06, 0x46, 0x13, 0x4B, 0x1B, 0x68, - 0x9B, 0xB2, 0x01, 0x93, 0x01, 0x9B, 0xB3, 0xF5, 0x00, 0x7F, 0x0A, 0xD0, 0x03, 0xDC, 0xB3, 0xB1, - 0x00, 0x24, 0x05, 0x25, 0x07, 0xE0, 0xB3, 0xF5, 0xC4, 0x6F, 0x02, 0xD0, 0xB3, 0xF5, 0x80, 0x5F, - 0xF6, 0xD1, 0x01, 0x24, 0x02, 0x25, 0x01, 0x99, 0x09, 0x48, 0xFF, 0xF7, 0x8E, 0xFF, 0x4C, 0xB1, - 0x29, 0x46, 0x30, 0x46, 0x02, 0xB0, 0xBD, 0xE8, 0x70, 0x40, 0xFF, 0xF7, 0xD1, 0xBF, 0x01, 0x24, - 0x25, 0x46, 0xF0, 0xE7, 0x00, 0x20, 0x02, 0xB0, 0x70, 0xBD, 0x00, 0xBF, 0x00, 0x62, 0x00, 0x03, - 0xAD, 0x2D, 0x04, 0x00, 0xFF, 0xF7, 0x8A, 0xBF, 0x10, 0xB5, 0x01, 0xFB, 0x00, 0xF4, 0x4F, 0xF4, - 0x7A, 0x71, 0x20, 0x46, 0x03, 0xF0, 0x52, 0xEB, 0x03, 0x4A, 0xA4, 0xFB, 0x02, 0x23, 0x98, 0x09, - 0x00, 0x29, 0x18, 0xBF, 0x01, 0x30, 0x10, 0xBD, 0xD3, 0x4D, 0x62, 0x10, 0x01, 0x20, 0x70, 0x47, - 0x40, 0x08, 0xF8, 0xB5, 0x18, 0x4A, 0x4F, 0xF0, 0x80, 0x43, 0x00, 0x05, 0x00, 0x24, 0x17, 0x4D, - 0x8C, 0x42, 0x0C, 0xD1, 0x15, 0x4F, 0x4F, 0xF0, 0x80, 0x43, 0xDF, 0xF8, 0x4C, 0xC0, 0x00, 0x25, - 0xAC, 0x42, 0x0B, 0xD1, 0x12, 0x48, 0xFF, 0xF7, 0x50, 0xFF, 0x00, 0x20, 0x10, 0xE0, 0xA6, 0x18, - 0x1E, 0x60, 0x66, 0x19, 0xC6, 0x50, 0x01, 0x34, 0x04, 0x33, 0xE9, 0xE7, 0xC1, 0x58, 0xEA, 0x19, - 0xC6, 0x18, 0x8A, 0x42, 0x05, 0xD0, 0x33, 0x46, 0x0A, 0x48, 0xFF, 0xF7, 0x3E, 0xFF, 0x01, 0x20, - 0xF8, 0xBD, 0x1E, 0x46, 0x05, 0xEB, 0x0C, 0x02, 0x56, 0xF8, 0x04, 0x1B, 0x8A, 0x42, 0xF3, 0xD1, - 0x01, 0x35, 0x33, 0x46, 0xDC, 0xE7, 0x00, 0xBF, 0x67, 0x45, 0x23, 0x01, 0x98, 0xBA, 0xDC, 0xFE, - 0xF4, 0x2D, 0x04, 0x00, 0xC2, 0x2D, 0x04, 0x00, 0x83, 0x69, 0x10, 0xB5, 0x04, 0x46, 0xC3, 0xF3, - 0x01, 0x31, 0xC3, 0xF3, 0x07, 0x12, 0x0A, 0x44, 0xE1, 0x69, 0x03, 0xF0, 0x0F, 0x00, 0xC3, 0xF3, - 0x81, 0x33, 0x02, 0x44, 0x13, 0x44, 0xC1, 0xF3, 0x03, 0x32, 0x1A, 0x44, 0x11, 0xF0, 0x0F, 0x0F, - 0x4F, 0xF0, 0x01, 0x03, 0x0C, 0xBF, 0x12, 0x3A, 0x13, 0x3A, 0x03, 0xFA, 0x02, 0xF0, 0xB4, 0xF8, - 0x7A, 0x30, 0x5B, 0x07, 0x05, 0xD0, 0x89, 0x0F, 0x02, 0x29, 0x1C, 0xBF, 0x00, 0xEB, 0x40, 0x00, - 0x80, 0x08, 0x10, 0xBD, 0x08, 0x4B, 0x1A, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x1A, 0x60, 0x1A, 0x68, - 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x05, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, - 0x00, 0x22, 0x03, 0x4B, 0x1A, 0x60, 0x70, 0x47, 0x0C, 0x17, 0x00, 0x03, 0x04, 0x18, 0x00, 0x03, - 0x20, 0x20, 0x00, 0x03, 0xF0, 0xB5, 0x8D, 0xB0, 0x07, 0x46, 0x14, 0x46, 0x0E, 0x46, 0x30, 0x22, - 0x00, 0x21, 0x68, 0x46, 0x1D, 0x46, 0xFF, 0xF7, 0xE3, 0xFE, 0x18, 0x21, 0x0C, 0xAB, 0x61, 0x43, - 0x5A, 0x18, 0x13, 0x4B, 0x42, 0xF8, 0x30, 0x3C, 0x42, 0xF8, 0x2C, 0x7C, 0xBF, 0xF3, 0x4F, 0x8F, - 0x42, 0xF8, 0x28, 0x6C, 0xBF, 0xF3, 0x4F, 0x8F, 0x42, 0xF8, 0x24, 0x5C, 0xBF, 0xF3, 0x4F, 0x8F, - 0x00, 0x23, 0x42, 0xF8, 0x20, 0x3C, 0xBF, 0xF3, 0x4F, 0x8F, 0xA3, 0xF5, 0x00, 0x63, 0x42, 0xF8, - 0x1C, 0x3C, 0xBF, 0xF3, 0x4F, 0x8F, 0x04, 0xF5, 0x40, 0x22, 0x69, 0x44, 0x84, 0x32, 0x92, 0x01, - 0x91, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x01, 0x23, 0x13, 0x60, 0x0D, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, - 0xC1, 0x06, 0xC1, 0x06, 0x00, 0x23, 0x09, 0x1A, 0x30, 0xB5, 0x93, 0x42, 0x01, 0xD1, 0x00, 0x20, - 0x30, 0xBD, 0x05, 0x68, 0x0C, 0x58, 0x04, 0x30, 0xA5, 0x42, 0x01, 0xD1, 0x01, 0x33, 0xF4, 0xE7, - 0x01, 0x20, 0xF5, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, 0x9C, 0x46, 0x5C, 0x4F, 0x0C, 0x46, 0x06, 0x46, - 0x89, 0xB0, 0x02, 0xAD, 0x0F, 0xCF, 0x0F, 0xC5, 0x97, 0xE8, 0x03, 0x00, 0x85, 0xE8, 0x03, 0x00, - 0x60, 0x46, 0xFF, 0xF7, 0x69, 0xFF, 0x45, 0x08, 0x03, 0x2C, 0x4F, 0xEA, 0x05, 0x55, 0x05, 0xF1, - 0x80, 0x45, 0x05, 0xF1, 0x0C, 0x05, 0x02, 0xD9, 0x07, 0x2C, 0x3E, 0xD8, 0x04, 0x3C, 0x00, 0x27, - 0xDF, 0xF8, 0x3C, 0xB1, 0x4F, 0xEA, 0xA6, 0x09, 0x4F, 0xF0, 0x00, 0x0A, 0x06, 0xF1, 0x80, 0x48, - 0x02, 0xAB, 0x53, 0xF8, 0x2A, 0x20, 0x4F, 0xF0, 0x80, 0x43, 0xD1, 0x43, 0x98, 0x45, 0x33, 0xD8, - 0x33, 0x46, 0x00, 0x22, 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, 0x83, 0xFF, 0xDB, 0xF8, - 0x00, 0x30, 0x13, 0xF0, 0x01, 0x03, 0x01, 0x93, 0xF9, 0xD1, 0x4A, 0x46, 0x29, 0x46, 0x4F, 0xF0, - 0x80, 0x40, 0xFF, 0xF7, 0xAF, 0xFF, 0x00, 0x28, 0x72, 0xD1, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, - 0x06, 0x0F, 0xDD, 0xD1, 0xE4, 0x00, 0xDF, 0xF8, 0xE8, 0xB0, 0x4F, 0xF0, 0x01, 0x0A, 0x04, 0xF1, - 0x08, 0x03, 0x3B, 0x44, 0x27, 0x46, 0x00, 0x93, 0x00, 0x9B, 0xBB, 0x42, 0x11, 0xD8, 0x4F, 0xF0, - 0x00, 0x0A, 0x27, 0x46, 0x4F, 0xF0, 0x01, 0x0B, 0x49, 0xE0, 0x08, 0x2C, 0x02, 0xD0, 0x00, 0x27, - 0x00, 0x24, 0xBD, 0xE7, 0x18, 0x27, 0xFB, 0xE7, 0x1A, 0x60, 0x08, 0x33, 0x43, 0xF8, 0x04, 0x1C, - 0xC4, 0xE7, 0x0A, 0xFA, 0x07, 0xF2, 0x4F, 0xF0, 0x80, 0x43, 0xD1, 0x43, 0x98, 0x45, 0x13, 0xD8, - 0x33, 0x46, 0x00, 0x22, 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, 0x43, 0xFF, 0xDB, 0xF8, - 0x00, 0x30, 0xDA, 0x07, 0xFB, 0xD4, 0x4A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, - 0x71, 0xFF, 0xA8, 0xBB, 0x01, 0x37, 0xCF, 0xE7, 0x1A, 0x60, 0x08, 0x33, 0x43, 0xF8, 0x04, 0x1C, - 0xE4, 0xE7, 0x0B, 0xFA, 0x07, 0xF2, 0xBA, 0xF1, 0x00, 0x0F, 0x21, 0xD1, 0xD1, 0x43, 0x52, 0x46, - 0x4F, 0xF0, 0x80, 0x43, 0x98, 0x45, 0x1E, 0xD8, 0x33, 0x46, 0x00, 0x22, 0x29, 0x46, 0x4F, 0xF0, - 0x80, 0x40, 0xFF, 0xF7, 0x1F, 0xFF, 0x12, 0x4B, 0x1B, 0x68, 0xDB, 0x07, 0xFB, 0xD4, 0x4A, 0x46, - 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, 0x4D, 0xFF, 0x88, 0xB9, 0x01, 0x37, 0x00, 0x9B, - 0xBB, 0x42, 0xDE, 0xD8, 0xBA, 0xF1, 0x00, 0x0F, 0x0C, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0xA8, 0xE7, - 0x4F, 0xF0, 0xFF, 0x31, 0xDC, 0xE7, 0x19, 0x60, 0x08, 0x33, 0x43, 0xF8, 0x04, 0x2C, 0xD9, 0xE7, - 0x01, 0x23, 0x01, 0x93, 0x01, 0x98, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x94, 0x29, 0x04, 0x00, - 0x30, 0x20, 0x00, 0x03, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x00, 0x20, - 0x10, 0x60, 0x70, 0x47, 0x04, 0x00, 0x81, 0x04, 0x43, 0x68, 0x10, 0xB5, 0x04, 0x46, 0x03, 0x3B, - 0x05, 0x2B, 0x1F, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x0C, 0x1E, 0x1E, 0x20, 0x23, 0x90, 0xF8, - 0x64, 0x30, 0x0A, 0x24, 0x5C, 0x43, 0x40, 0xF2, 0xDC, 0x53, 0x08, 0xBF, 0x1C, 0x46, 0x0A, 0xE0, - 0x40, 0xF6, 0xC4, 0x10, 0xFF, 0xF7, 0xA0, 0xFD, 0x94, 0xF8, 0x65, 0x30, 0x0A, 0x24, 0x5C, 0x43, - 0x01, 0xD1, 0x4F, 0xF4, 0x96, 0x64, 0x20, 0x46, 0xFF, 0xF7, 0x8C, 0xFD, 0x70, 0xB1, 0x0A, 0x48, - 0xFF, 0xF7, 0xB3, 0xFD, 0x00, 0x24, 0x0D, 0xE0, 0x90, 0xF8, 0x66, 0x30, 0xEE, 0xE7, 0x90, 0xF8, - 0x67, 0x30, 0x0A, 0x24, 0x5C, 0x43, 0x40, 0xF2, 0x4C, 0x43, 0xDE, 0xE7, 0x21, 0x46, 0x03, 0x48, - 0xFF, 0xF7, 0xA3, 0xFD, 0x20, 0x46, 0x10, 0xBD, 0x0A, 0x2E, 0x04, 0x00, 0x20, 0x2E, 0x04, 0x00, - 0x83, 0x6F, 0xC3, 0xF3, 0x02, 0x53, 0x05, 0x2B, 0x16, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x06, 0x03, - 0x0C, 0x0F, 0x15, 0x12, 0x0A, 0x4B, 0x0B, 0x4A, 0x1A, 0x60, 0x0B, 0x4A, 0x13, 0x68, 0x43, 0xF0, - 0x80, 0x73, 0x13, 0x60, 0x70, 0x47, 0x06, 0x4B, 0x08, 0x4A, 0xF5, 0xE7, 0x04, 0x4B, 0x08, 0x4A, - 0xF2, 0xE7, 0x03, 0x4B, 0x07, 0x4A, 0xEF, 0xE7, 0x01, 0x4B, 0x07, 0x4A, 0xEC, 0xE7, 0x00, 0xBF, - 0x10, 0x11, 0x00, 0x03, 0xCC, 0xCC, 0x86, 0xE4, 0x10, 0x10, 0x00, 0x03, 0x99, 0x99, 0x06, 0xE9, - 0x66, 0x66, 0x86, 0xED, 0x00, 0x00, 0x86, 0xF5, 0x33, 0x33, 0x06, 0xF2, 0x38, 0xB5, 0x0F, 0x4C, - 0xA0, 0xFB, 0x04, 0x45, 0x0C, 0x68, 0x10, 0x46, 0x24, 0xF4, 0x7F, 0x44, 0x24, 0xF0, 0x03, 0x04, - 0x2D, 0x09, 0x6B, 0x1E, 0x44, 0xEA, 0x03, 0x24, 0x44, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0xFF, 0xF7, - 0xBF, 0xFF, 0x44, 0xF0, 0x60, 0x43, 0x44, 0xF0, 0x20, 0x44, 0x0B, 0x60, 0x0C, 0x60, 0x0B, 0x68, - 0xDB, 0x00, 0xFC, 0xD5, 0x18, 0x20, 0x68, 0x43, 0x38, 0xBD, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, - 0x95, 0x4A, 0xF8, 0xB5, 0x04, 0x46, 0x95, 0x4E, 0x13, 0x68, 0x95, 0x4D, 0x43, 0xF4, 0x80, 0x73, - 0x13, 0x60, 0x00, 0x23, 0x2B, 0x60, 0x32, 0x68, 0x92, 0x4B, 0x42, 0xF0, 0x01, 0x02, 0x32, 0x60, - 0x1F, 0x46, 0x32, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x32, 0x60, 0x01, 0x22, 0x2A, 0x60, 0x1A, 0x68, - 0xD2, 0x07, 0xFC, 0xD5, 0x00, 0x23, 0x2B, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x20, 0x03, 0x33, 0x60, - 0x01, 0x23, 0x2B, 0x60, 0x3B, 0x68, 0xDB, 0x07, 0xFC, 0xD5, 0x87, 0x4A, 0x13, 0x68, 0xD8, 0x07, - 0xFC, 0xD5, 0x86, 0x4A, 0x00, 0x23, 0x2B, 0x60, 0x13, 0x68, 0x23, 0xF0, 0x20, 0x03, 0x13, 0x60, - 0x01, 0x23, 0x2B, 0x60, 0x3B, 0x68, 0xD9, 0x07, 0xFC, 0xD5, 0x81, 0x4A, 0x13, 0x68, 0x03, 0xF0, - 0x03, 0x03, 0x01, 0x2B, 0xFA, 0xD1, 0xA3, 0x6F, 0xDA, 0x06, 0x02, 0xD4, 0xC8, 0x20, 0xFF, 0xF7, - 0x1D, 0xFD, 0x00, 0x23, 0x2B, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x01, 0x23, - 0x2B, 0x60, 0x3B, 0x68, 0xDB, 0x07, 0xFC, 0xD5, 0x63, 0x68, 0x08, 0x2B, 0x59, 0xD1, 0x23, 0x6A, - 0x74, 0x4A, 0x75, 0x49, 0x13, 0x60, 0x75, 0x4B, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, - 0x61, 0x6A, 0x41, 0xF4, 0x80, 0x71, 0x11, 0x60, 0x6F, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, - 0xFC, 0xDB, 0xA1, 0x6A, 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x6B, 0x49, 0x19, 0x60, 0x19, 0x68, - 0x00, 0x29, 0xFC, 0xDB, 0xE1, 0x6A, 0x41, 0xF4, 0x40, 0x71, 0x11, 0x60, 0x66, 0x49, 0x19, 0x60, - 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x21, 0x6B, 0x41, 0xF4, 0x80, 0x61, 0x11, 0x60, 0x62, 0x49, - 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xE1, 0x6B, 0x41, 0xF4, 0x30, 0x61, 0x11, 0x60, - 0x5D, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x21, 0x6C, 0x41, 0xF4, 0x40, 0x61, - 0x11, 0x60, 0x59, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x61, 0x6C, 0x41, 0xF4, - 0x50, 0x61, 0x11, 0x60, 0x54, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6C, - 0x41, 0xF4, 0x60, 0x61, 0x11, 0x60, 0x50, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, - 0x61, 0x6D, 0x41, 0xF4, 0xB0, 0x51, 0x11, 0x60, 0x4B, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, - 0xFC, 0xDB, 0x63, 0x68, 0x07, 0x2B, 0x25, 0xD1, 0x63, 0x6A, 0x46, 0x4A, 0x48, 0x49, 0x43, 0xF4, - 0x80, 0x73, 0x13, 0x60, 0x45, 0x4B, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6A, - 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x42, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, - 0xE1, 0x6A, 0x41, 0xF4, 0x40, 0x71, 0x11, 0x60, 0x3D, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, - 0xFC, 0xDB, 0xE1, 0x6B, 0x41, 0xF4, 0x30, 0x61, 0x11, 0x60, 0x37, 0x4A, 0x1A, 0x60, 0x1A, 0x68, - 0x00, 0x2A, 0xFC, 0xDB, 0x63, 0x68, 0x04, 0x2B, 0x44, 0xD1, 0x23, 0x6A, 0x31, 0x48, 0x32, 0x4A, - 0x03, 0x60, 0x32, 0x4B, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x62, 0x6A, 0x02, 0x60, - 0x30, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0xA2, 0x6A, 0x02, 0x60, 0x2E, 0x4A, - 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0xE2, 0x6A, 0x02, 0x60, 0x2B, 0x4A, 0x1A, 0x60, - 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x22, 0x6B, 0x02, 0x60, 0x29, 0x4A, 0x1A, 0x60, 0x1A, 0x68, - 0x00, 0x2A, 0xFC, 0xDB, 0x62, 0x6B, 0x02, 0x60, 0x26, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, - 0xFC, 0xDB, 0xA2, 0x6B, 0x42, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x23, 0x4A, 0x1A, 0x60, 0x19, 0x68, - 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6B, 0x41, 0xF0, 0x80, 0x01, 0x01, 0x60, 0x1A, 0x60, 0x19, 0x68, - 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6B, 0x21, 0xF0, 0x80, 0x01, 0x01, 0x60, 0x1A, 0x60, 0x1A, 0x68, - 0x00, 0x2A, 0xFC, 0xDB, 0x63, 0x68, 0x03, 0x2B, 0x41, 0xD1, 0x23, 0x6A, 0x0D, 0x4A, 0x0E, 0x49, - 0x13, 0x60, 0x0E, 0x4B, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x61, 0x6A, 0x11, 0x60, - 0x0C, 0x49, 0x19, 0x60, 0x22, 0xE0, 0x00, 0xBF, 0x20, 0x00, 0x81, 0x04, 0xB0, 0x01, 0x82, 0x04, - 0x20, 0x03, 0x82, 0x04, 0x24, 0x03, 0x82, 0x04, 0xBC, 0x01, 0x82, 0x04, 0x30, 0x00, 0x82, 0x04, - 0x04, 0x00, 0x82, 0x04, 0x14, 0x00, 0x82, 0x04, 0x30, 0x00, 0x00, 0x80, 0x10, 0x00, 0x82, 0x04, - 0xF0, 0x00, 0x00, 0x80, 0x30, 0x10, 0x00, 0x80, 0x30, 0x20, 0x00, 0x80, 0x30, 0x30, 0x00, 0x80, - 0x30, 0x40, 0x00, 0x80, 0x30, 0x50, 0x00, 0x80, 0x30, 0x60, 0x00, 0x80, 0x19, 0x68, 0x00, 0x29, - 0xFC, 0xDB, 0xA1, 0x6A, 0x11, 0x60, 0x08, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, - 0xE1, 0x6A, 0x11, 0x60, 0x05, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x04, 0x4B, - 0x00, 0x22, 0x1A, 0x60, 0xF8, 0xBD, 0x00, 0xBF, 0x30, 0x20, 0x00, 0x80, 0x30, 0x30, 0x00, 0x80, - 0x54, 0x00, 0x83, 0x04, 0x43, 0x68, 0x03, 0x3B, 0x05, 0x2B, 0x1A, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, - 0x03, 0x0D, 0x19, 0x19, 0x10, 0x13, 0x90, 0xF8, 0x68, 0x30, 0x00, 0x2B, 0x08, 0xBF, 0x80, 0x23, - 0x09, 0x4A, 0x13, 0x60, 0xC2, 0xF8, 0x80, 0x30, 0x70, 0x47, 0x90, 0xF8, 0x69, 0x30, 0xF4, 0xE7, - 0x90, 0xF8, 0x6A, 0x30, 0xF1, 0xE7, 0x90, 0xF8, 0x6B, 0x30, 0x00, 0x2B, 0x08, 0xBF, 0x33, 0x23, - 0xEE, 0xE7, 0x00, 0x23, 0xEC, 0xE7, 0x00, 0xBF, 0xDC, 0x03, 0x83, 0x04, 0xC3, 0x68, 0x51, 0x4A, - 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x04, 0x32, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x07, 0xD1, - 0xC3, 0x6D, 0x13, 0xF0, 0x1F, 0x3F, 0x14, 0xBF, 0x03, 0xF0, 0x1F, 0x03, 0x04, 0x23, 0x13, 0x60, - 0xC3, 0x68, 0x49, 0x4A, 0xC3, 0xF3, 0x04, 0x23, 0x13, 0x60, 0x04, 0x32, 0x13, 0x60, 0x43, 0x68, - 0x08, 0x2B, 0x07, 0xD1, 0xC3, 0x6D, 0x13, 0xF0, 0x1F, 0x3F, 0x14, 0xBF, 0xC3, 0xF3, 0x04, 0x23, - 0x04, 0x23, 0x13, 0x60, 0xC3, 0x89, 0x41, 0x4A, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x04, 0x32, + 0x90, 0x42, 0xF5, 0xD1, 0x70, 0x47, 0x10, 0xB5, 0x00, 0xF0, 0x40, 0xF8, 0x4F, 0xF0, 0xE0, 0x63, + 0x6F, 0xF4, 0xA0, 0x72, 0xD3, 0xF8, 0x0C, 0x31, 0x19, 0x68, 0x88, 0x18, 0x40, 0xF2, 0x62, 0x52, + 0x90, 0x42, 0x13, 0xD9, 0x0C, 0x48, 0x00, 0xF0, 0x5F, 0xF8, 0x0C, 0x49, 0x00, 0x20, 0x03, 0xF0, + 0x13, 0xFE, 0x04, 0x46, 0x01, 0x46, 0x0A, 0x48, 0x00, 0xF0, 0x56, 0xF8, 0x0A, 0x20, 0x00, 0xF0, + 0xA0, 0xF8, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0xD0, 0xBF, 0x80, 0x22, 0x19, 0x46, + 0x02, 0x48, 0x00, 0xF0, 0x75, 0xF8, 0xE8, 0xE7, 0x18, 0x34, 0x04, 0x00, 0x64, 0x3D, 0x04, 0x00, + 0x53, 0x34, 0x04, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x02, 0x48, 0x00, 0xF0, 0x3D, 0xF8, 0x00, 0x20, + 0x08, 0xBD, 0x00, 0xBF, 0x74, 0x34, 0x04, 0x00, 0x08, 0xB5, 0x01, 0x46, 0x02, 0x48, 0x00, 0xF0, + 0x33, 0xF8, 0x00, 0x20, 0x08, 0xBD, 0x00, 0xBF, 0x8E, 0x34, 0x04, 0x00, 0x4F, 0xF0, 0xE0, 0x63, + 0xD3, 0xF8, 0x08, 0x21, 0x01, 0x4B, 0x1A, 0x60, 0x70, 0x47, 0x00, 0xBF, 0xE4, 0x3D, 0x04, 0x00, + 0x4F, 0xF0, 0xA0, 0x63, 0x5A, 0x69, 0x52, 0x06, 0xFC, 0xD5, 0x18, 0x60, 0x70, 0x47, 0x0A, 0x29, + 0x08, 0xB5, 0x02, 0xD1, 0x0D, 0x20, 0xFF, 0xF7, 0xF3, 0xFF, 0xBD, 0xE8, 0x08, 0x40, 0x08, 0x46, + 0xFF, 0xF7, 0xEE, 0xBF, 0x0F, 0xB4, 0x07, 0xB5, 0x00, 0x21, 0x06, 0x48, 0x04, 0xAB, 0x53, 0xF8, + 0x04, 0x2B, 0xCD, 0xE9, 0x00, 0x33, 0x00, 0xF0, 0x99, 0xF8, 0x03, 0xB0, 0x5D, 0xF8, 0x04, 0xEB, + 0x04, 0xB0, 0x70, 0x47, 0x1F, 0xEE, 0x03, 0x00, 0x0F, 0xB4, 0x37, 0xB5, 0x06, 0xAC, 0x54, 0xF8, + 0x04, 0x5B, 0x00, 0xF0, 0x3D, 0xF8, 0x0C, 0x4B, 0x1A, 0x68, 0x80, 0x1A, 0x4F, 0xF4, 0x7A, 0x72, + 0xB0, 0xFB, 0xF2, 0xF1, 0x02, 0xFB, 0x11, 0x02, 0x08, 0x48, 0xFF, 0xF7, 0xDB, 0xFF, 0x23, 0x46, + 0x2A, 0x46, 0x00, 0x21, 0x06, 0x48, 0xCD, 0xE9, 0x00, 0x44, 0x00, 0xF0, 0x77, 0xF8, 0x03, 0xB0, + 0xBD, 0xE8, 0x30, 0x40, 0x04, 0xB0, 0x70, 0x47, 0xE4, 0x3D, 0x04, 0x00, 0xB0, 0x34, 0x04, 0x00, + 0x1F, 0xEE, 0x03, 0x00, 0x01, 0x4B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEC, 0x03, 0x00, + 0x01, 0x4B, 0x18, 0x47, 0x70, 0x47, 0x00, 0xBF, 0x4C, 0xE9, 0x03, 0x00, 0x00, 0x20, 0x70, 0x47, + 0x52, 0xEC, 0x0E, 0x3F, 0x18, 0x21, 0x48, 0x43, 0x18, 0x18, 0x42, 0xF1, 0x00, 0x03, 0x52, 0xEC, + 0x0E, 0x1F, 0x88, 0x42, 0x73, 0xEB, 0x02, 0x02, 0xF9, 0xD2, 0x70, 0x47, 0xFF, 0xF7, 0xF0, 0xBF, + 0x08, 0xB5, 0x51, 0xEC, 0x0E, 0x0F, 0x00, 0x23, 0x45, 0xF6, 0xC0, 0x52, 0x03, 0xF0, 0x88, 0xEF, + 0x08, 0xBD, 0x38, 0xB5, 0x04, 0x46, 0x4F, 0xF4, 0x7A, 0x70, 0x60, 0x43, 0xFF, 0xF7, 0xE0, 0xFF, + 0xFF, 0xF7, 0xEE, 0xFF, 0x05, 0x46, 0xFF, 0xF7, 0xEB, 0xFF, 0x43, 0x1B, 0xA3, 0x42, 0xFA, 0xD3, + 0x38, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x0A, 0x21, 0x16, 0x4C, 0x02, 0x6A, + 0x53, 0x1E, 0x00, 0x2A, 0x03, 0x62, 0x03, 0x68, 0x01, 0xDC, 0x03, 0xB9, 0x30, 0xBD, 0x90, 0xF8, + 0x57, 0x20, 0x08, 0x2A, 0x10, 0xD0, 0x10, 0x2A, 0x12, 0xD0, 0x02, 0x2A, 0x14, 0xD1, 0x03, 0xF0, + 0x01, 0x02, 0x5B, 0x08, 0x03, 0x60, 0x83, 0x68, 0xA2, 0x5C, 0x5D, 0x1E, 0x85, 0x60, 0x1A, 0x70, + 0xC3, 0x69, 0x01, 0x33, 0xC3, 0x61, 0xE2, 0xE7, 0x03, 0xF0, 0x07, 0x02, 0xDB, 0x08, 0xF1, 0xE7, + 0x03, 0xF0, 0x0F, 0x02, 0x1B, 0x09, 0xED, 0xE7, 0xB3, 0xFB, 0xF1, 0xF5, 0x01, 0xFB, 0x15, 0x33, + 0x05, 0x60, 0xDA, 0xB2, 0xE7, 0xE7, 0x00, 0xBF, 0xDC, 0x2F, 0x04, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, + 0x06, 0x46, 0xDF, 0xF8, 0x2C, 0x92, 0x2D, 0xED, 0x02, 0x8B, 0x9B, 0xB0, 0x0F, 0x46, 0x02, 0xF1, + 0xFF, 0x38, 0x09, 0xF1, 0x77, 0x0A, 0x9F, 0xED, 0x84, 0x8B, 0x1C, 0x46, 0x00, 0x23, 0x0C, 0x93, + 0x8D, 0xF8, 0x61, 0x30, 0x18, 0xF8, 0x01, 0x1F, 0x29, 0xB9, 0x0C, 0x98, 0x1B, 0xB0, 0xBD, 0xEC, + 0x02, 0x8B, 0xBD, 0xE8, 0xF0, 0x8F, 0xA1, 0xF1, 0x20, 0x03, 0x5A, 0x2B, 0x22, 0xD8, 0x09, 0xEB, + 0x01, 0x03, 0x13, 0xF8, 0x04, 0x3C, 0x03, 0xF0, 0x0F, 0x03, 0x9D, 0xF8, 0x61, 0x20, 0x09, 0xEB, + 0xC3, 0x03, 0x13, 0x44, 0x1B, 0x7F, 0x1B, 0x09, 0x8D, 0xF8, 0x61, 0x30, 0x01, 0x3B, 0x06, 0x2B, + 0x12, 0xD8, 0x01, 0xA2, 0x52, 0xF8, 0x23, 0xF0, 0x15, 0xF0, 0x03, 0x00, 0x87, 0xF0, 0x03, 0x00, + 0x29, 0xF0, 0x03, 0x00, 0xA5, 0xEF, 0x03, 0x00, 0x43, 0xF0, 0x03, 0x00, 0x65, 0xF0, 0x03, 0x00, + 0xC5, 0xF0, 0x03, 0x00, 0x00, 0x23, 0xE0, 0xE7, 0x38, 0x46, 0xB0, 0x47, 0x0C, 0x9B, 0x01, 0x33, + 0x0C, 0x93, 0xC7, 0xE7, 0x00, 0x23, 0xCD, 0xE9, 0x0A, 0x33, 0x0E, 0x93, 0x09, 0x93, 0x0D, 0x93, + 0x20, 0x23, 0x8D, 0xF8, 0x60, 0x30, 0xBD, 0xE7, 0x2A, 0x29, 0x03, 0xD1, 0x54, 0xF8, 0x04, 0x3B, + 0x0B, 0x93, 0xB7, 0xE7, 0x0B, 0x9B, 0x30, 0x39, 0x0A, 0x22, 0x02, 0xFB, 0x03, 0x11, 0x0B, 0x91, + 0xB0, 0xE7, 0x0D, 0x9B, 0x2A, 0x29, 0x43, 0xF0, 0x04, 0x03, 0x0D, 0x93, 0x03, 0xD1, 0x54, 0xF8, + 0x04, 0x3B, 0x0A, 0x93, 0xA6, 0xE7, 0x0A, 0x9B, 0x30, 0x39, 0x0A, 0x22, 0x02, 0xFB, 0x03, 0x11, + 0x0A, 0x91, 0x9F, 0xE7, 0x6C, 0x29, 0x08, 0xD0, 0x7A, 0x29, 0x9B, 0xD1, 0x0D, 0x9B, 0x23, 0xF0, + 0x03, 0x03, 0x43, 0xF0, 0x02, 0x03, 0x0D, 0x93, 0x94, 0xE7, 0x0D, 0x9B, 0x23, 0xF0, 0x03, 0x03, + 0x43, 0xF0, 0x01, 0x03, 0xF7, 0xE7, 0x2B, 0x29, 0x18, 0xD0, 0x07, 0xD8, 0x20, 0x29, 0x11, 0xD0, + 0x23, 0x29, 0x87, 0xD1, 0x0D, 0x9B, 0x43, 0xF0, 0x20, 0x03, 0xEC, 0xE7, 0x2D, 0x29, 0x05, 0xD0, + 0x30, 0x29, 0x7F, 0xF4, 0x7F, 0xAF, 0x8D, 0xF8, 0x60, 0x10, 0x7B, 0xE7, 0x0D, 0x9B, 0x43, 0xF0, + 0x08, 0x03, 0xE0, 0xE7, 0x0D, 0x9B, 0x43, 0xF0, 0x10, 0x03, 0xDC, 0xE7, 0x0D, 0x9B, 0x43, 0xF0, + 0x40, 0x03, 0xD8, 0xE7, 0x0D, 0x9D, 0x78, 0x29, 0x0A, 0xD8, 0x57, 0x29, 0x0B, 0xD8, 0x50, 0x29, + 0x70, 0xD0, 0x51, 0xD8, 0x42, 0x29, 0x00, 0xF0, 0xCE, 0x81, 0x43, 0x29, 0x00, 0xF0, 0x4D, 0x81, + 0x00, 0x23, 0x09, 0x93, 0x7C, 0xE0, 0x58, 0x39, 0x20, 0x29, 0xF9, 0xD8, 0x01, 0xA3, 0x53, 0xF8, + 0x21, 0xF0, 0x00, 0xBF, 0x41, 0xF3, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, + 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, + 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0x05, 0xF3, 0x03, 0x00, + 0x81, 0xF3, 0x03, 0x00, 0x67, 0xF3, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0x93, 0xF3, 0x03, 0x00, + 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0x67, 0xF3, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, + 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, + 0x21, 0xF3, 0x03, 0x00, 0xBB, 0xF1, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, + 0x83, 0xF1, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, 0x75, 0xF3, 0x03, 0x00, 0xE1, 0xF0, 0x03, 0x00, + 0xE1, 0xF0, 0x03, 0x00, 0x47, 0xF3, 0x03, 0x00, 0x53, 0x29, 0xB1, 0xD1, 0x45, 0xF0, 0x80, 0x05, + 0x0D, 0x95, 0x54, 0xF8, 0x04, 0x2B, 0x00, 0x2A, 0x08, 0xBF, 0x52, 0x46, 0x04, 0x92, 0x11, 0x46, + 0x13, 0x46, 0x1A, 0x46, 0x01, 0x33, 0x10, 0x78, 0x00, 0x28, 0xFA, 0xD1, 0x52, 0x1A, 0x09, 0x92, + 0x1E, 0xE0, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, 0x52, 0xB8, 0x1E, 0x85, 0xEB, 0x51, 0xE0, 0x3F, + 0xDC, 0x2F, 0x04, 0x00, 0x45, 0xF0, 0x80, 0x05, 0x0D, 0x95, 0x0D, 0x9B, 0x23, 0xF0, 0x03, 0x03, + 0x43, 0xF4, 0x00, 0x73, 0x43, 0xF0, 0x02, 0x03, 0x0D, 0x93, 0x10, 0x23, 0x8D, 0xF8, 0x5F, 0x30, + 0x08, 0x23, 0x0A, 0x93, 0x02, 0x23, 0x0E, 0x93, 0x43, 0xF6, 0x2D, 0x63, 0xAD, 0xF8, 0x3C, 0x30, + 0x0D, 0x9A, 0x93, 0x05, 0x40, 0xF1, 0x5D, 0x81, 0x0A, 0x9B, 0x0B, 0xB9, 0x01, 0x23, 0x0A, 0x93, + 0x02, 0xF4, 0x80, 0x71, 0x15, 0x05, 0x09, 0xD4, 0x02, 0xF0, 0x03, 0x03, 0x01, 0x2B, 0x02, 0xD0, + 0x02, 0x2B, 0x00, 0xD0, 0x13, 0xB9, 0x54, 0xF8, 0x04, 0x3B, 0x02, 0x93, 0x90, 0x06, 0x02, 0xD5, + 0x02, 0x9B, 0x03, 0xB9, 0x0E, 0x93, 0x89, 0xB1, 0x02, 0x9B, 0x00, 0x2B, 0x04, 0xDA, 0x5B, 0x42, + 0x42, 0xF4, 0x80, 0x62, 0x02, 0x93, 0x0D, 0x92, 0x0D, 0x9B, 0x03, 0xF4, 0x82, 0x63, 0x10, 0x2B, + 0x04, 0xD1, 0x20, 0x23, 0x8D, 0xF8, 0x3C, 0x30, 0x01, 0x23, 0x0E, 0x93, 0x0D, 0x9B, 0xD9, 0x04, + 0x02, 0xD4, 0x0D, 0xF1, 0x5E, 0x03, 0x04, 0x93, 0x02, 0xA8, 0xFF, 0xF7, 0x65, 0xFE, 0x04, 0x9B, + 0x5A, 0x1C, 0x04, 0x92, 0x0D, 0x9A, 0x12, 0xF4, 0x88, 0x6F, 0x0E, 0xD0, 0x9D, 0xF8, 0x60, 0x10, + 0x12, 0xF4, 0x80, 0x6F, 0x4F, 0xF0, 0x2D, 0x02, 0x08, 0xBF, 0x2B, 0x22, 0x30, 0x29, 0x40, 0xF0, + 0x12, 0x81, 0x01, 0x23, 0x8D, 0xF8, 0x3C, 0x20, 0x0E, 0x93, 0x09, 0x9B, 0x4F, 0xF0, 0x00, 0x0B, + 0x0E, 0x9D, 0xEA, 0x18, 0x0B, 0x9B, 0x9B, 0x1A, 0x0B, 0x93, 0x0D, 0x9B, 0x0F, 0xAA, 0x03, 0xF0, + 0x80, 0x03, 0x5D, 0x45, 0x00, 0xF3, 0x0F, 0x81, 0x0C, 0x9B, 0x25, 0xEA, 0xE5, 0x75, 0x1D, 0x44, + 0x0D, 0x9B, 0x0C, 0x95, 0x1A, 0x07, 0x0C, 0xD4, 0x0B, 0x9D, 0x9D, 0xF8, 0x60, 0x10, 0xAB, 0x46, + 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF3, 0x11, 0x81, 0x0C, 0x9B, 0x25, 0xEA, 0xE5, 0x75, 0x1D, 0x44, + 0x0C, 0x95, 0x0D, 0x9B, 0x4F, 0xF0, 0x00, 0x0B, 0x04, 0x9A, 0x09, 0x9D, 0x03, 0xF0, 0x80, 0x03, + 0x5D, 0x45, 0x00, 0xF3, 0x09, 0x81, 0x0C, 0x9B, 0x25, 0xEA, 0xE5, 0x75, 0x1D, 0x44, 0x0D, 0x9B, + 0x0C, 0x95, 0x1B, 0x07, 0x7F, 0xF5, 0x5E, 0xAE, 0x0B, 0x9D, 0x9D, 0xF8, 0x60, 0x10, 0xAB, 0x46, + 0xBB, 0xF1, 0x00, 0x0F, 0x00, 0xF3, 0x0A, 0x81, 0x0C, 0x9B, 0x25, 0xEA, 0xE5, 0x75, 0x1D, 0x44, + 0x0C, 0x95, 0x4F, 0xE6, 0x45, 0xF4, 0x00, 0x73, 0xAD, 0x06, 0x0D, 0x93, 0x4F, 0xF0, 0x02, 0x03, + 0x8D, 0xF8, 0x5F, 0x30, 0x7F, 0xF5, 0x64, 0xAF, 0x0E, 0x93, 0x46, 0xF2, 0x30, 0x23, 0x5D, 0xE7, + 0x45, 0xF4, 0x00, 0x73, 0xA8, 0x06, 0x0D, 0x93, 0x4F, 0xF0, 0x08, 0x03, 0x8D, 0xF8, 0x5F, 0x30, + 0x7F, 0xF5, 0x56, 0xAF, 0x30, 0x23, 0x8D, 0xF8, 0x3C, 0x30, 0x01, 0x23, 0x0E, 0x93, 0x4F, 0xE7, + 0x45, 0xF0, 0x80, 0x05, 0x0D, 0x95, 0x0D, 0x9B, 0x43, 0xF4, 0x00, 0x72, 0x0D, 0x92, 0x99, 0x06, + 0x4F, 0xF0, 0x10, 0x02, 0x8D, 0xF8, 0x5F, 0x20, 0x7F, 0xF5, 0x42, 0xAF, 0x02, 0x23, 0x0E, 0x93, + 0x47, 0xF6, 0x30, 0x03, 0x3A, 0xE7, 0x45, 0xF4, 0x40, 0x75, 0x0A, 0x23, 0x0D, 0x95, 0x8D, 0xF8, + 0x5F, 0x30, 0x35, 0xE7, 0x45, 0xF4, 0x00, 0x75, 0xF7, 0xE7, 0x45, 0xF0, 0x80, 0x05, 0x0D, 0x95, + 0x0D, 0xF1, 0x3E, 0x03, 0x04, 0x93, 0x54, 0xF8, 0x04, 0x3B, 0x8D, 0xF8, 0x3E, 0x30, 0x01, 0x23, + 0xA7, 0xE6, 0x6A, 0x07, 0x01, 0xD4, 0x06, 0x23, 0x0A, 0x93, 0x07, 0x34, 0x00, 0x22, 0x24, 0xF0, + 0x07, 0x04, 0x0A, 0x9B, 0xDF, 0xED, 0x5E, 0x1B, 0x11, 0x46, 0xF2, 0xEE, 0x04, 0x2B, 0x8D, 0xED, + 0x02, 0x8B, 0xF4, 0xEC, 0x02, 0x0B, 0x8B, 0x42, 0x48, 0xDC, 0x0A, 0xB1, 0xCD, 0xED, 0x02, 0x1B, + 0xF5, 0xEE, 0xC0, 0x0B, 0xDD, 0xED, 0x02, 0x1B, 0xF1, 0xEE, 0x10, 0xFA, 0x43, 0xD5, 0x70, 0xEE, + 0xE1, 0x0B, 0x45, 0xF4, 0x80, 0x65, 0x0D, 0x95, 0xFD, 0xEE, 0xE0, 0x7B, 0xF8, 0xEE, 0xE7, 0x1B, + 0xCD, 0xED, 0x08, 0x7A, 0x70, 0xEE, 0xE1, 0x0B, 0xF1, 0xEE, 0x60, 0x0B, 0x00, 0x22, 0xCD, 0xED, + 0x06, 0x0B, 0xDD, 0xED, 0x06, 0x0B, 0x11, 0x46, 0xF2, 0xEE, 0x04, 0x1B, 0x8B, 0x42, 0x35, 0xDC, + 0x0A, 0xB1, 0xCD, 0xED, 0x06, 0x0B, 0x9D, 0xED, 0x06, 0x7B, 0x0D, 0xF1, 0x5E, 0x02, 0x04, 0x92, + 0x0A, 0x22, 0x8D, 0xF8, 0x5F, 0x20, 0xBC, 0xEE, 0xC7, 0x7B, 0x8D, 0xED, 0x02, 0x7A, 0x53, 0xB1, + 0x02, 0xA8, 0xFF, 0xF7, 0x79, 0xFD, 0x04, 0x9B, 0x5A, 0x1E, 0x04, 0x92, 0x2E, 0x22, 0x1A, 0x70, + 0x09, 0x9B, 0x01, 0x33, 0x09, 0x93, 0x0D, 0x9B, 0x43, 0xF4, 0xD8, 0x53, 0x43, 0xF0, 0x01, 0x03, + 0x0D, 0x93, 0x00, 0x23, 0x0A, 0x93, 0x08, 0x9B, 0x02, 0x93, 0xC9, 0xE6, 0xC1, 0xEE, 0xA2, 0x1B, + 0x01, 0x31, 0x01, 0x22, 0xAF, 0xE7, 0x70, 0xEE, 0xA1, 0x0B, 0xFD, 0xEE, 0xE0, 0x7B, 0xF8, 0xEE, + 0x67, 0x1B, 0xCD, 0xED, 0x08, 0x7A, 0x70, 0xEE, 0xE1, 0x0B, 0xBF, 0xE7, 0x60, 0xEE, 0xA1, 0x0B, + 0x01, 0x31, 0x01, 0x22, 0xC2, 0xE7, 0x2C, 0x4A, 0x54, 0xF8, 0x04, 0x1B, 0x53, 0x1D, 0x00, 0x29, + 0x08, 0xBF, 0x1A, 0x46, 0x04, 0x92, 0x13, 0x46, 0x19, 0x46, 0x01, 0x33, 0x08, 0x78, 0x00, 0x28, + 0xFA, 0xD1, 0x8A, 0x1A, 0x83, 0xE6, 0x04, 0x93, 0x1A, 0x70, 0x09, 0x9B, 0x01, 0x33, 0x09, 0x93, + 0xEB, 0xE6, 0x0B, 0x9A, 0x00, 0x2A, 0x3F, 0xF4, 0xE8, 0xAE, 0x09, 0x9B, 0x9A, 0x42, 0xBF, 0xF6, + 0xE4, 0xAE, 0x09, 0x92, 0xE1, 0xE6, 0x12, 0xF8, 0x01, 0x1B, 0x2B, 0xB1, 0xA1, 0xF1, 0x61, 0x00, + 0x19, 0x28, 0x01, 0xD8, 0x20, 0x39, 0xC9, 0xB2, 0x38, 0x46, 0xCD, 0xE9, 0x00, 0x32, 0x0B, 0xF1, + 0x01, 0x0B, 0xB0, 0x47, 0xDD, 0xE9, 0x00, 0x32, 0xDB, 0xE6, 0x38, 0x46, 0x00, 0x91, 0x0B, 0xF1, + 0xFF, 0x3B, 0xB0, 0x47, 0x00, 0x99, 0xE3, 0xE6, 0x12, 0xF8, 0x0B, 0x10, 0x2B, 0xB1, 0xA1, 0xF1, + 0x61, 0x00, 0x19, 0x28, 0x01, 0xD8, 0x20, 0x39, 0xC9, 0xB2, 0x38, 0x46, 0xCD, 0xE9, 0x00, 0x23, + 0x0B, 0xF1, 0x01, 0x0B, 0xB0, 0x47, 0xDD, 0xE9, 0x00, 0x23, 0xE1, 0xE6, 0x38, 0x46, 0x00, 0x91, + 0x0B, 0xF1, 0xFF, 0x3B, 0xB0, 0x47, 0x00, 0x99, 0xEA, 0xE6, 0x00, 0xBF, 0xAF, 0xF3, 0x00, 0x80, + 0x52, 0xB8, 0x1E, 0x85, 0xEB, 0x51, 0xE0, 0x3F, 0xED, 0x2F, 0x04, 0x00, 0x0C, 0xB4, 0x07, 0xB5, + 0x04, 0xAB, 0x53, 0xF8, 0x04, 0x2B, 0x01, 0x93, 0xFF, 0xF7, 0x20, 0xFD, 0x03, 0xB0, 0x5D, 0xF8, + 0x04, 0xEB, 0x02, 0xB0, 0x70, 0x47, 0x00, 0xBF, 0x80, 0xEA, 0x01, 0x20, 0x08, 0x23, 0x48, 0xF2, + 0x05, 0x01, 0x42, 0x00, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x04, 0x92, 0xB2, 0x4C, 0xBF, 0x82, 0xEA, + 0x01, 0x00, 0x10, 0x46, 0x00, 0x2B, 0xF4, 0xD1, 0x70, 0x47, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x46, + 0x2C, 0x44, 0xFF, 0xF7, 0xE9, 0xFF, 0x44, 0xEA, 0x00, 0x40, 0x38, 0xBD, 0x00, 0x23, 0x73, 0xB5, + 0x01, 0x93, 0x06, 0x46, 0x13, 0x4B, 0x1B, 0x68, 0x9B, 0xB2, 0x01, 0x93, 0x01, 0x9B, 0xB3, 0xF5, + 0x00, 0x7F, 0x0A, 0xD0, 0x03, 0xDC, 0xB3, 0xB1, 0x00, 0x24, 0x05, 0x25, 0x07, 0xE0, 0xB3, 0xF5, + 0xC4, 0x6F, 0x02, 0xD0, 0xB3, 0xF5, 0x80, 0x5F, 0xF6, 0xD1, 0x01, 0x24, 0x02, 0x25, 0x01, 0x99, + 0x09, 0x48, 0xFF, 0xF7, 0x51, 0xFC, 0x4C, 0xB1, 0x29, 0x46, 0x30, 0x46, 0x02, 0xB0, 0xBD, 0xE8, + 0x70, 0x40, 0xFF, 0xF7, 0xD2, 0xBF, 0x01, 0x24, 0x25, 0x46, 0xF0, 0xE7, 0x00, 0x20, 0x02, 0xB0, + 0x70, 0xBD, 0x00, 0xBF, 0x00, 0x62, 0x00, 0x03, 0xC1, 0x34, 0x04, 0x00, 0xFF, 0xF7, 0x70, 0xBC, + 0x10, 0xB5, 0x01, 0xFB, 0x00, 0xF4, 0x4F, 0xF4, 0x7A, 0x71, 0x20, 0x46, 0x03, 0xF0, 0x52, 0xEB, + 0x03, 0x4A, 0xA4, 0xFB, 0x02, 0x23, 0x98, 0x09, 0x00, 0x29, 0x18, 0xBF, 0x01, 0x30, 0x10, 0xBD, + 0xD3, 0x4D, 0x62, 0x10, 0x01, 0x20, 0x70, 0x47, 0x40, 0x08, 0xF8, 0xB5, 0x18, 0x4A, 0x4F, 0xF0, + 0x80, 0x43, 0x00, 0x05, 0x00, 0x24, 0x17, 0x4D, 0x8C, 0x42, 0x0C, 0xD1, 0x15, 0x4F, 0x4F, 0xF0, + 0x80, 0x43, 0xDF, 0xF8, 0x4C, 0xC0, 0x00, 0x25, 0xAC, 0x42, 0x0B, 0xD1, 0x12, 0x48, 0xFF, 0xF7, + 0x13, 0xFC, 0x00, 0x20, 0x10, 0xE0, 0xA6, 0x18, 0x1E, 0x60, 0x66, 0x19, 0xC6, 0x50, 0x01, 0x34, + 0x04, 0x33, 0xE9, 0xE7, 0xC1, 0x58, 0xEA, 0x19, 0xC6, 0x18, 0x8A, 0x42, 0x05, 0xD0, 0x33, 0x46, + 0x0A, 0x48, 0xFF, 0xF7, 0x01, 0xFC, 0x01, 0x20, 0xF8, 0xBD, 0x1E, 0x46, 0x05, 0xEB, 0x0C, 0x02, + 0x56, 0xF8, 0x04, 0x1B, 0x8A, 0x42, 0xF3, 0xD1, 0x01, 0x35, 0x33, 0x46, 0xDC, 0xE7, 0x00, 0xBF, + 0x67, 0x45, 0x23, 0x01, 0x98, 0xBA, 0xDC, 0xFE, 0x08, 0x35, 0x04, 0x00, 0xD6, 0x34, 0x04, 0x00, + 0x83, 0x69, 0x10, 0xB5, 0x04, 0x46, 0xC3, 0xF3, 0x01, 0x31, 0xC3, 0xF3, 0x07, 0x12, 0x0A, 0x44, + 0xE1, 0x69, 0x03, 0xF0, 0x0F, 0x00, 0xC3, 0xF3, 0x81, 0x33, 0x02, 0x44, 0x13, 0x44, 0xC1, 0xF3, + 0x03, 0x32, 0x1A, 0x44, 0x11, 0xF0, 0x0F, 0x0F, 0x4F, 0xF0, 0x01, 0x03, 0x0C, 0xBF, 0x12, 0x3A, + 0x13, 0x3A, 0x03, 0xFA, 0x02, 0xF0, 0xB4, 0xF8, 0x7A, 0x30, 0x5B, 0x07, 0x05, 0xD0, 0x89, 0x0F, + 0x02, 0x29, 0x1C, 0xBF, 0x00, 0xEB, 0x40, 0x00, 0x80, 0x08, 0x10, 0xBD, 0x08, 0x4B, 0x1A, 0x68, + 0x42, 0xF4, 0x80, 0x32, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x05, 0x4A, + 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x00, 0x22, 0x03, 0x4B, 0x1A, 0x60, 0x70, 0x47, + 0x0C, 0x17, 0x00, 0x03, 0x04, 0x18, 0x00, 0x03, 0x20, 0x20, 0x00, 0x03, 0xF0, 0xB5, 0x8D, 0xB0, + 0x07, 0x46, 0x14, 0x46, 0x0E, 0x46, 0x30, 0x22, 0x00, 0x21, 0x68, 0x46, 0x1D, 0x46, 0xFF, 0xF7, + 0xC9, 0xFB, 0x18, 0x21, 0x0C, 0xAB, 0x61, 0x43, 0x5A, 0x18, 0x13, 0x4B, 0x42, 0xF8, 0x30, 0x3C, + 0x42, 0xF8, 0x2C, 0x7C, 0xBF, 0xF3, 0x4F, 0x8F, 0x42, 0xF8, 0x28, 0x6C, 0xBF, 0xF3, 0x4F, 0x8F, + 0x42, 0xF8, 0x24, 0x5C, 0xBF, 0xF3, 0x4F, 0x8F, 0x00, 0x23, 0x42, 0xF8, 0x20, 0x3C, 0xBF, 0xF3, + 0x4F, 0x8F, 0xA3, 0xF5, 0x00, 0x63, 0x42, 0xF8, 0x1C, 0x3C, 0xBF, 0xF3, 0x4F, 0x8F, 0x04, 0xF5, + 0x40, 0x22, 0x69, 0x44, 0x84, 0x32, 0x92, 0x01, 0x91, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x01, 0x23, + 0x13, 0x60, 0x0D, 0xB0, 0xF0, 0xBD, 0x00, 0xBF, 0xC1, 0x06, 0xC1, 0x06, 0x00, 0x23, 0x09, 0x1A, + 0x30, 0xB5, 0x93, 0x42, 0x01, 0xD1, 0x00, 0x20, 0x30, 0xBD, 0x05, 0x68, 0x0C, 0x58, 0x04, 0x30, + 0xA5, 0x42, 0x01, 0xD1, 0x01, 0x33, 0xF4, 0xE7, 0x01, 0x20, 0xF5, 0xE7, 0x2D, 0xE9, 0xF0, 0x4F, + 0x9C, 0x46, 0x5C, 0x4F, 0x0C, 0x46, 0x06, 0x46, 0x89, 0xB0, 0x02, 0xAD, 0x0F, 0xCF, 0x0F, 0xC5, + 0x97, 0xE8, 0x03, 0x00, 0x85, 0xE8, 0x03, 0x00, 0x60, 0x46, 0xFF, 0xF7, 0x69, 0xFF, 0x45, 0x08, + 0x03, 0x2C, 0x4F, 0xEA, 0x05, 0x55, 0x05, 0xF1, 0x80, 0x45, 0x05, 0xF1, 0x0C, 0x05, 0x02, 0xD9, + 0x07, 0x2C, 0x3E, 0xD8, 0x04, 0x3C, 0x00, 0x27, 0xDF, 0xF8, 0x3C, 0xB1, 0x4F, 0xEA, 0xA6, 0x09, + 0x4F, 0xF0, 0x00, 0x0A, 0x06, 0xF1, 0x80, 0x48, 0x02, 0xAB, 0x53, 0xF8, 0x2A, 0x20, 0x4F, 0xF0, + 0x80, 0x43, 0xD1, 0x43, 0x98, 0x45, 0x33, 0xD8, 0x33, 0x46, 0x00, 0x22, 0x29, 0x46, 0x4F, 0xF0, + 0x80, 0x40, 0xFF, 0xF7, 0x83, 0xFF, 0xDB, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0x01, 0x03, 0x01, 0x93, + 0xF9, 0xD1, 0x4A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, 0xAF, 0xFF, 0x00, 0x28, + 0x72, 0xD1, 0x0A, 0xF1, 0x01, 0x0A, 0xBA, 0xF1, 0x06, 0x0F, 0xDD, 0xD1, 0xE4, 0x00, 0xDF, 0xF8, + 0xE8, 0xB0, 0x4F, 0xF0, 0x01, 0x0A, 0x04, 0xF1, 0x08, 0x03, 0x3B, 0x44, 0x27, 0x46, 0x00, 0x93, + 0x00, 0x9B, 0xBB, 0x42, 0x11, 0xD8, 0x4F, 0xF0, 0x00, 0x0A, 0x27, 0x46, 0x4F, 0xF0, 0x01, 0x0B, + 0x49, 0xE0, 0x08, 0x2C, 0x02, 0xD0, 0x00, 0x27, 0x00, 0x24, 0xBD, 0xE7, 0x18, 0x27, 0xFB, 0xE7, + 0x1A, 0x60, 0x08, 0x33, 0x43, 0xF8, 0x04, 0x1C, 0xC4, 0xE7, 0x0A, 0xFA, 0x07, 0xF2, 0x4F, 0xF0, + 0x80, 0x43, 0xD1, 0x43, 0x98, 0x45, 0x13, 0xD8, 0x33, 0x46, 0x00, 0x22, 0x29, 0x46, 0x4F, 0xF0, + 0x80, 0x40, 0xFF, 0xF7, 0x43, 0xFF, 0xDB, 0xF8, 0x00, 0x30, 0xDA, 0x07, 0xFB, 0xD4, 0x4A, 0x46, + 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, 0x71, 0xFF, 0xA8, 0xBB, 0x01, 0x37, 0xCF, 0xE7, + 0x1A, 0x60, 0x08, 0x33, 0x43, 0xF8, 0x04, 0x1C, 0xE4, 0xE7, 0x0B, 0xFA, 0x07, 0xF2, 0xBA, 0xF1, + 0x00, 0x0F, 0x21, 0xD1, 0xD1, 0x43, 0x52, 0x46, 0x4F, 0xF0, 0x80, 0x43, 0x98, 0x45, 0x1E, 0xD8, + 0x33, 0x46, 0x00, 0x22, 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, 0x1F, 0xFF, 0x12, 0x4B, + 0x1B, 0x68, 0xDB, 0x07, 0xFB, 0xD4, 0x4A, 0x46, 0x29, 0x46, 0x4F, 0xF0, 0x80, 0x40, 0xFF, 0xF7, + 0x4D, 0xFF, 0x88, 0xB9, 0x01, 0x37, 0x00, 0x9B, 0xBB, 0x42, 0xDE, 0xD8, 0xBA, 0xF1, 0x00, 0x0F, + 0x0C, 0xD1, 0x4F, 0xF0, 0x01, 0x0A, 0xA8, 0xE7, 0x4F, 0xF0, 0xFF, 0x31, 0xDC, 0xE7, 0x19, 0x60, + 0x08, 0x33, 0x43, 0xF8, 0x04, 0x2C, 0xD9, 0xE7, 0x01, 0x23, 0x01, 0x93, 0x01, 0x98, 0x09, 0xB0, + 0xBD, 0xE8, 0xF0, 0x8F, 0x5C, 0x30, 0x04, 0x00, 0x30, 0x20, 0x00, 0x03, 0x03, 0x4A, 0x13, 0x68, + 0x23, 0xF4, 0x7F, 0x43, 0x43, 0xEA, 0x00, 0x20, 0x10, 0x60, 0x70, 0x47, 0x04, 0x00, 0x81, 0x04, + 0x43, 0x68, 0x10, 0xB5, 0x04, 0x46, 0x03, 0x3B, 0x05, 0x2B, 0x1F, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, + 0x03, 0x0C, 0x1E, 0x1E, 0x20, 0x23, 0x90, 0xF8, 0x64, 0x30, 0x0A, 0x24, 0x5C, 0x43, 0x40, 0xF2, + 0xDC, 0x53, 0x08, 0xBF, 0x1C, 0x46, 0x0A, 0xE0, 0x40, 0xF6, 0xC4, 0x10, 0xFF, 0xF7, 0x4C, 0xFA, + 0x94, 0xF8, 0x65, 0x30, 0x0A, 0x24, 0x5C, 0x43, 0x01, 0xD1, 0x4F, 0xF4, 0x96, 0x64, 0x20, 0x46, + 0xFF, 0xF7, 0x38, 0xFA, 0x70, 0xB1, 0x0A, 0x48, 0xFF, 0xF7, 0x76, 0xFA, 0x00, 0x24, 0x0D, 0xE0, + 0x90, 0xF8, 0x66, 0x30, 0xEE, 0xE7, 0x90, 0xF8, 0x67, 0x30, 0x0A, 0x24, 0x5C, 0x43, 0x40, 0xF2, + 0x4C, 0x43, 0xDE, 0xE7, 0x21, 0x46, 0x03, 0x48, 0xFF, 0xF7, 0x66, 0xFA, 0x20, 0x46, 0x10, 0xBD, + 0x1E, 0x35, 0x04, 0x00, 0x34, 0x35, 0x04, 0x00, 0x83, 0x6F, 0xC3, 0xF3, 0x02, 0x53, 0x05, 0x2B, + 0x16, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x06, 0x03, 0x0C, 0x0F, 0x15, 0x12, 0x0A, 0x4B, 0x0B, 0x4A, + 0x1A, 0x60, 0x0B, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x80, 0x73, 0x13, 0x60, 0x70, 0x47, 0x06, 0x4B, + 0x08, 0x4A, 0xF5, 0xE7, 0x04, 0x4B, 0x08, 0x4A, 0xF2, 0xE7, 0x03, 0x4B, 0x07, 0x4A, 0xEF, 0xE7, + 0x01, 0x4B, 0x07, 0x4A, 0xEC, 0xE7, 0x00, 0xBF, 0x10, 0x11, 0x00, 0x03, 0xCC, 0xCC, 0x86, 0xE4, + 0x10, 0x10, 0x00, 0x03, 0x99, 0x99, 0x06, 0xE9, 0x66, 0x66, 0x86, 0xED, 0x00, 0x00, 0x86, 0xF5, + 0x33, 0x33, 0x06, 0xF2, 0x38, 0xB5, 0x0F, 0x4C, 0xA0, 0xFB, 0x04, 0x45, 0x0C, 0x68, 0x10, 0x46, + 0x24, 0xF4, 0x7F, 0x44, 0x24, 0xF0, 0x03, 0x04, 0x2D, 0x09, 0x6B, 0x1E, 0x44, 0xEA, 0x03, 0x24, + 0x44, 0xF0, 0x00, 0x43, 0x0B, 0x60, 0xFF, 0xF7, 0xBF, 0xFF, 0x44, 0xF0, 0x60, 0x43, 0x44, 0xF0, + 0x20, 0x44, 0x0B, 0x60, 0x0C, 0x60, 0x0B, 0x68, 0xDB, 0x00, 0xFC, 0xD5, 0x18, 0x20, 0x68, 0x43, + 0x38, 0xBD, 0x00, 0xBF, 0xAB, 0xAA, 0xAA, 0xAA, 0x95, 0x4A, 0xF8, 0xB5, 0x04, 0x46, 0x95, 0x4E, + 0x13, 0x68, 0x95, 0x4D, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x00, 0x23, 0x2B, 0x60, 0x32, 0x68, + 0x92, 0x4B, 0x42, 0xF0, 0x01, 0x02, 0x32, 0x60, 0x1F, 0x46, 0x32, 0x68, 0x42, 0xF0, 0x20, 0x02, + 0x32, 0x60, 0x01, 0x22, 0x2A, 0x60, 0x1A, 0x68, 0xD2, 0x07, 0xFC, 0xD5, 0x00, 0x23, 0x2B, 0x60, + 0x33, 0x68, 0x23, 0xF0, 0x20, 0x03, 0x33, 0x60, 0x01, 0x23, 0x2B, 0x60, 0x3B, 0x68, 0xDB, 0x07, + 0xFC, 0xD5, 0x87, 0x4A, 0x13, 0x68, 0xD8, 0x07, 0xFC, 0xD5, 0x86, 0x4A, 0x00, 0x23, 0x2B, 0x60, + 0x13, 0x68, 0x23, 0xF0, 0x20, 0x03, 0x13, 0x60, 0x01, 0x23, 0x2B, 0x60, 0x3B, 0x68, 0xD9, 0x07, + 0xFC, 0xD5, 0x81, 0x4A, 0x13, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x01, 0x2B, 0xFA, 0xD1, 0xA3, 0x6F, + 0xDA, 0x06, 0x02, 0xD4, 0xC8, 0x20, 0xFF, 0xF7, 0x03, 0xFA, 0x00, 0x23, 0x2B, 0x60, 0x33, 0x68, + 0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x01, 0x23, 0x2B, 0x60, 0x3B, 0x68, 0xDB, 0x07, 0xFC, 0xD5, + 0x63, 0x68, 0x08, 0x2B, 0x59, 0xD1, 0x23, 0x6A, 0x74, 0x4A, 0x75, 0x49, 0x13, 0x60, 0x75, 0x4B, + 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x61, 0x6A, 0x41, 0xF4, 0x80, 0x71, 0x11, 0x60, + 0x6F, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6A, 0x41, 0xF4, 0x00, 0x71, + 0x11, 0x60, 0x6B, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xE1, 0x6A, 0x41, 0xF4, + 0x40, 0x71, 0x11, 0x60, 0x66, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x21, 0x6B, + 0x41, 0xF4, 0x80, 0x61, 0x11, 0x60, 0x62, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, + 0xE1, 0x6B, 0x41, 0xF4, 0x30, 0x61, 0x11, 0x60, 0x5D, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, + 0xFC, 0xDB, 0x21, 0x6C, 0x41, 0xF4, 0x40, 0x61, 0x11, 0x60, 0x59, 0x49, 0x19, 0x60, 0x19, 0x68, + 0x00, 0x29, 0xFC, 0xDB, 0x61, 0x6C, 0x41, 0xF4, 0x50, 0x61, 0x11, 0x60, 0x54, 0x49, 0x19, 0x60, + 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6C, 0x41, 0xF4, 0x60, 0x61, 0x11, 0x60, 0x50, 0x49, + 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0x61, 0x6D, 0x41, 0xF4, 0xB0, 0x51, 0x11, 0x60, + 0x4B, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x63, 0x68, 0x07, 0x2B, 0x25, 0xD1, + 0x63, 0x6A, 0x46, 0x4A, 0x48, 0x49, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x45, 0x4B, 0x19, 0x60, + 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6A, 0x41, 0xF4, 0x00, 0x71, 0x11, 0x60, 0x42, 0x49, + 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xE1, 0x6A, 0x41, 0xF4, 0x40, 0x71, 0x11, 0x60, + 0x3D, 0x49, 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xE1, 0x6B, 0x41, 0xF4, 0x30, 0x61, + 0x11, 0x60, 0x37, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x63, 0x68, 0x04, 0x2B, + 0x44, 0xD1, 0x23, 0x6A, 0x31, 0x48, 0x32, 0x4A, 0x03, 0x60, 0x32, 0x4B, 0x1A, 0x60, 0x1A, 0x68, + 0x00, 0x2A, 0xFC, 0xDB, 0x62, 0x6A, 0x02, 0x60, 0x30, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, + 0xFC, 0xDB, 0xA2, 0x6A, 0x02, 0x60, 0x2E, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, + 0xE2, 0x6A, 0x02, 0x60, 0x2B, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x22, 0x6B, + 0x02, 0x60, 0x29, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x62, 0x6B, 0x02, 0x60, + 0x26, 0x4A, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0xA2, 0x6B, 0x42, 0xF0, 0x80, 0x02, + 0x02, 0x60, 0x23, 0x4A, 0x1A, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6B, 0x41, 0xF0, + 0x80, 0x01, 0x01, 0x60, 0x1A, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6B, 0x21, 0xF0, + 0x80, 0x01, 0x01, 0x60, 0x1A, 0x60, 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x63, 0x68, 0x03, 0x2B, + 0x41, 0xD1, 0x23, 0x6A, 0x0D, 0x4A, 0x0E, 0x49, 0x13, 0x60, 0x0E, 0x4B, 0x19, 0x60, 0x19, 0x68, + 0x00, 0x29, 0xFC, 0xDB, 0x61, 0x6A, 0x11, 0x60, 0x0C, 0x49, 0x19, 0x60, 0x22, 0xE0, 0x00, 0xBF, + 0x20, 0x00, 0x81, 0x04, 0xB0, 0x01, 0x82, 0x04, 0x20, 0x03, 0x82, 0x04, 0x24, 0x03, 0x82, 0x04, + 0xBC, 0x01, 0x82, 0x04, 0x30, 0x00, 0x82, 0x04, 0x04, 0x00, 0x82, 0x04, 0x14, 0x00, 0x82, 0x04, + 0x30, 0x00, 0x00, 0x80, 0x10, 0x00, 0x82, 0x04, 0xF0, 0x00, 0x00, 0x80, 0x30, 0x10, 0x00, 0x80, + 0x30, 0x20, 0x00, 0x80, 0x30, 0x30, 0x00, 0x80, 0x30, 0x40, 0x00, 0x80, 0x30, 0x50, 0x00, 0x80, + 0x30, 0x60, 0x00, 0x80, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xA1, 0x6A, 0x11, 0x60, 0x08, 0x49, + 0x19, 0x60, 0x19, 0x68, 0x00, 0x29, 0xFC, 0xDB, 0xE1, 0x6A, 0x11, 0x60, 0x05, 0x4A, 0x1A, 0x60, + 0x1A, 0x68, 0x00, 0x2A, 0xFC, 0xDB, 0x04, 0x4B, 0x00, 0x22, 0x1A, 0x60, 0xF8, 0xBD, 0x00, 0xBF, + 0x30, 0x20, 0x00, 0x80, 0x30, 0x30, 0x00, 0x80, 0x54, 0x00, 0x83, 0x04, 0x43, 0x68, 0x03, 0x3B, + 0x05, 0x2B, 0x1A, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x0D, 0x19, 0x19, 0x10, 0x13, 0x90, 0xF8, + 0x68, 0x30, 0x00, 0x2B, 0x08, 0xBF, 0x80, 0x23, 0x09, 0x4A, 0x13, 0x60, 0xC2, 0xF8, 0x80, 0x30, + 0x70, 0x47, 0x90, 0xF8, 0x69, 0x30, 0xF4, 0xE7, 0x90, 0xF8, 0x6A, 0x30, 0xF1, 0xE7, 0x90, 0xF8, + 0x6B, 0x30, 0x00, 0x2B, 0x08, 0xBF, 0x33, 0x23, 0xEE, 0xE7, 0x00, 0x23, 0xEC, 0xE7, 0x00, 0xBF, + 0xDC, 0x03, 0x83, 0x04, 0xC3, 0x68, 0x51, 0x4A, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x04, 0x32, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x07, 0xD1, 0xC3, 0x6D, 0x13, 0xF0, 0x1F, 0x3F, 0x14, 0xBF, - 0xC3, 0xF3, 0x04, 0x43, 0x04, 0x23, 0x13, 0x60, 0xC3, 0x7B, 0x39, 0x4A, 0x03, 0xF0, 0x1F, 0x03, + 0x03, 0xF0, 0x1F, 0x03, 0x04, 0x23, 0x13, 0x60, 0xC3, 0x68, 0x49, 0x4A, 0xC3, 0xF3, 0x04, 0x23, 0x13, 0x60, 0x04, 0x32, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x07, 0xD1, 0xC3, 0x6D, 0x13, 0xF0, - 0x1F, 0x3F, 0x14, 0xBF, 0xC3, 0xF3, 0x04, 0x63, 0x04, 0x23, 0x13, 0x60, 0x03, 0x69, 0x31, 0x4A, - 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x40, 0x32, 0x42, 0xF8, 0x3C, 0x3C, 0x03, 0x69, 0xC3, 0xF3, - 0x04, 0x23, 0x42, 0xF8, 0x38, 0x3C, 0x42, 0xF8, 0x34, 0x3C, 0x83, 0x68, 0x03, 0xF0, 0x1F, 0x03, - 0x13, 0x60, 0x41, 0x68, 0x04, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x60, - 0x25, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x04, 0xBF, 0x00, 0x23, 0x13, 0x60, 0x83, 0x68, - 0x22, 0x4A, 0xC3, 0xF3, 0x04, 0x23, 0x13, 0x60, 0x41, 0x68, 0x04, 0x29, 0x01, 0xD0, 0x07, 0x29, - 0x01, 0xD1, 0x00, 0x21, 0x11, 0x60, 0x1E, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x04, 0xBF, - 0x00, 0x23, 0x13, 0x60, 0x43, 0x89, 0x1B, 0x4A, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x41, 0x68, - 0x04, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x60, 0x16, 0x4A, 0x13, 0x60, - 0x43, 0x68, 0x08, 0x2B, 0x04, 0xBF, 0x00, 0x23, 0x13, 0x60, 0xC3, 0x7A, 0x13, 0x4A, 0x03, 0xF0, - 0x1F, 0x03, 0x13, 0x60, 0x41, 0x68, 0x04, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x01, 0xD1, 0x00, 0x21, - 0x11, 0x60, 0x0F, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x04, 0xBF, 0x00, 0x23, 0x13, 0x60, - 0x70, 0x47, 0x00, 0xBF, 0x88, 0x03, 0x83, 0x04, 0xC8, 0x03, 0x83, 0x04, 0x08, 0x04, 0x83, 0x04, - 0x48, 0x04, 0x83, 0x04, 0x40, 0x03, 0x83, 0x04, 0x84, 0x03, 0x83, 0x04, 0xC0, 0x03, 0x83, 0x04, - 0xC4, 0x03, 0x83, 0x04, 0x00, 0x04, 0x83, 0x04, 0x04, 0x04, 0x83, 0x04, 0x40, 0x04, 0x83, 0x04, - 0x44, 0x04, 0x83, 0x04, 0x5C, 0x4B, 0xC1, 0x6E, 0x10, 0xB5, 0x1C, 0x68, 0x00, 0x29, 0x42, 0x68, - 0xA4, 0xB2, 0x0B, 0xDA, 0x83, 0x6D, 0xB4, 0xF5, 0x00, 0x6F, 0x02, 0xD0, 0xB4, 0xF5, 0x10, 0x5F, - 0x46, 0xD1, 0x03, 0x2A, 0x16, 0xD0, 0x08, 0x2A, 0x2C, 0xD0, 0x10, 0xBD, 0x4B, 0x01, 0x48, 0x02, - 0x03, 0xF4, 0xF0, 0x53, 0x00, 0xF4, 0xF0, 0x10, 0x03, 0x43, 0x48, 0x00, 0x00, 0xF0, 0x1E, 0x00, - 0x03, 0x43, 0x48, 0x03, 0x49, 0x0F, 0x00, 0xF0, 0xF0, 0x50, 0x43, 0xEA, 0x00, 0x03, 0x18, 0xBF, - 0x5B, 0x00, 0xE0, 0xE7, 0x49, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x49, 0x49, 0x42, 0xF8, 0x04, 0x0B, - 0x8A, 0x42, 0xFB, 0xD1, 0x47, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, - 0x05, 0x41, 0x45, 0x4A, 0xC3, 0xF3, 0x05, 0x63, 0x11, 0x60, 0x02, 0xF5, 0xDD, 0x52, 0x04, 0x32, - 0x13, 0x60, 0xD2, 0xE7, 0x3D, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x3D, 0x49, 0x42, 0xF8, 0x04, 0x0B, - 0x8A, 0x42, 0xFB, 0xD1, 0x3B, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, - 0x05, 0x41, 0x39, 0x4A, 0xC3, 0xF3, 0x05, 0x63, 0x11, 0x60, 0x42, 0xF8, 0x54, 0x3C, 0xBC, 0xE7, - 0x03, 0x3A, 0x05, 0x2A, 0xB9, 0xD8, 0x01, 0xA1, 0x51, 0xF8, 0x22, 0xF0, 0xD5, 0xF8, 0x03, 0x00, - 0x01, 0xF9, 0x03, 0x00, 0x2B, 0xF8, 0x03, 0x00, 0x2B, 0xF8, 0x03, 0x00, 0x23, 0xF9, 0x03, 0x00, - 0x4D, 0xF9, 0x03, 0x00, 0x29, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x29, 0x49, 0x42, 0xF8, 0x04, 0x0B, - 0x8A, 0x42, 0xFB, 0xD1, 0x27, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, - 0x05, 0x41, 0x26, 0x4A, 0xC3, 0xF3, 0x05, 0x63, 0x11, 0x60, 0x42, 0xF8, 0x34, 0x3C, 0x94, 0xE7, - 0x1E, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x1E, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, - 0x1C, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0xC3, 0xF3, 0x05, 0x43, 0x0A, 0x60, 0x4A, 0x60, 0x1C, 0x4A, - 0xAE, 0xE7, 0x16, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x15, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, - 0xFB, 0xD1, 0x14, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, 0x05, 0x41, - 0x14, 0x4A, 0xC3, 0xF3, 0x05, 0x63, 0x11, 0x60, 0x93, 0x60, 0x6E, 0xE7, 0x0B, 0x4A, 0xC3, 0xF3, - 0x05, 0x20, 0x0B, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, 0x09, 0x49, 0x03, 0xF0, - 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, 0x05, 0x41, 0x0B, 0x4A, 0xC3, 0xF3, 0x05, 0x63, - 0x11, 0x60, 0x42, 0xF8, 0x04, 0x3C, 0x58, 0xE7, 0x00, 0x62, 0x00, 0x03, 0x80, 0x07, 0x83, 0x04, - 0x00, 0x08, 0x83, 0x04, 0xDC, 0x07, 0x83, 0x04, 0xE4, 0x07, 0x83, 0x04, 0xB8, 0x07, 0x83, 0x04, - 0x84, 0x07, 0x83, 0x04, 0x88, 0x07, 0x83, 0x04, 0x90, 0x07, 0x83, 0x04, 0xC3, 0x6E, 0x10, 0xB5, - 0x5A, 0x03, 0x71, 0xD5, 0x6E, 0x4B, 0x6F, 0x49, 0x6F, 0x4C, 0x1A, 0x68, 0x22, 0xF0, 0x01, 0x02, - 0x1A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x08, 0x02, 0x0A, 0x60, 0x01, 0xF5, 0xC4, 0x71, 0x0A, 0x68, - 0x22, 0xF0, 0x10, 0x02, 0x0A, 0x60, 0x42, 0x68, 0x08, 0x2A, 0x01, 0xBF, 0xA1, 0xF5, 0xC6, 0x71, - 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x0A, 0x60, 0x02, 0x6F, 0x64, 0x49, 0x02, 0xF0, 0x3F, 0x02, - 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0x42, 0x69, 0x60, 0x4C, - 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0x50, 0x34, 0x22, 0x67, 0x0A, 0x60, 0x5D, 0x49, 0x0A, 0x60, - 0xB4, 0x39, 0x02, 0x6F, 0xC2, 0xF3, 0x05, 0x22, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, - 0xA1, 0x42, 0xF9, 0xD1, 0x42, 0x69, 0x58, 0x4C, 0xC2, 0xF3, 0x05, 0x22, 0x22, 0x60, 0x04, 0xF5, - 0x94, 0x74, 0x44, 0xF8, 0x68, 0x2C, 0x0A, 0x60, 0x54, 0x49, 0x0A, 0x60, 0x24, 0x31, 0xB0, 0xF8, - 0x72, 0x20, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, - 0xF9, 0xD1, 0xC2, 0x8A, 0x4E, 0x4C, 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0x50, 0x34, 0x22, 0x67, - 0x0A, 0x60, 0x4C, 0x49, 0x0A, 0x60, 0xB4, 0x39, 0x90, 0xF8, 0x73, 0x20, 0x02, 0xF0, 0x3F, 0x02, - 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0xC2, 0x7D, 0x46, 0x4C, - 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0xC4, 0xF8, 0xC0, 0x20, 0x0A, 0x60, 0x43, 0x49, 0x0A, 0x60, - 0x1A, 0x68, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0xC3, 0x6E, 0x9B, 0x03, 0x67, 0xD5, 0x40, 0x4B, - 0x40, 0x49, 0x41, 0x4C, 0x1A, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x1A, 0x60, 0x0A, 0x68, 0x22, 0xF0, - 0x04, 0x02, 0x0A, 0x60, 0x01, 0xF5, 0x3C, 0x71, 0x42, 0x6F, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, - 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0xC2, 0x6F, 0x37, 0x4C, 0x02, 0xF0, - 0x3F, 0x02, 0x22, 0x60, 0x0C, 0x3C, 0xC4, 0xF8, 0xCC, 0x20, 0x0A, 0x60, 0x34, 0x49, 0x0A, 0x60, - 0xB4, 0x39, 0x42, 0x6F, 0xC2, 0xF3, 0x05, 0x22, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, - 0xA1, 0x42, 0xF9, 0xD1, 0xC2, 0x6F, 0x2F, 0x4C, 0xC2, 0xF3, 0x05, 0x22, 0x22, 0x60, 0x04, 0xF5, - 0x8E, 0x74, 0x44, 0xF8, 0x5C, 0x2C, 0x0A, 0x60, 0x2B, 0x49, 0x0A, 0x60, 0x24, 0x31, 0xB0, 0xF8, - 0x76, 0x20, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, - 0xF9, 0xD1, 0xB0, 0xF8, 0x7E, 0x20, 0x25, 0x4C, 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0x0C, 0x3C, - 0xC4, 0xF8, 0xCC, 0x20, 0x0A, 0x60, 0x22, 0x49, 0x0A, 0x60, 0xB4, 0x39, 0x90, 0xF8, 0x77, 0x20, - 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, - 0x90, 0xF8, 0x7F, 0x20, 0x1B, 0x48, 0x02, 0xF0, 0x3F, 0x02, 0x02, 0x60, 0xC0, 0xF8, 0xC0, 0x20, - 0x0A, 0x60, 0x19, 0x49, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x1A, 0x60, 0x10, 0xBD, - 0x60, 0x00, 0x83, 0x04, 0x08, 0x00, 0x83, 0x04, 0xCC, 0x04, 0x83, 0x04, 0x84, 0x04, 0x83, 0x04, - 0xD0, 0x04, 0x83, 0x04, 0x8C, 0x05, 0x83, 0x04, 0x24, 0x05, 0x83, 0x04, 0xE0, 0x05, 0x83, 0x04, - 0x50, 0x06, 0x83, 0x04, 0x0C, 0x07, 0x83, 0x04, 0xA4, 0x06, 0x83, 0x04, 0x60, 0x07, 0x83, 0x04, - 0x54, 0x00, 0x83, 0x04, 0x90, 0x01, 0x83, 0x04, 0xC8, 0x04, 0x83, 0x04, 0x28, 0x05, 0x83, 0x04, - 0x88, 0x05, 0x83, 0x04, 0x2C, 0x05, 0x83, 0x04, 0xDC, 0x05, 0x83, 0x04, 0xA8, 0x06, 0x83, 0x04, - 0x08, 0x07, 0x83, 0x04, 0xAC, 0x06, 0x83, 0x04, 0x5C, 0x07, 0x83, 0x04, 0x2D, 0xE9, 0xF0, 0x4F, - 0x06, 0x46, 0xAD, 0x4D, 0xCD, 0xB0, 0x2C, 0xAC, 0x28, 0xAF, 0x0F, 0xCD, 0x0F, 0xC4, 0x95, 0xE8, - 0x0F, 0x00, 0x10, 0x35, 0x84, 0xE8, 0x0F, 0x00, 0x34, 0xAC, 0x20, 0x22, 0x00, 0x21, 0x20, 0x46, - 0xFF, 0xF7, 0x16, 0xF9, 0x20, 0x22, 0x00, 0x21, 0x3C, 0xA8, 0xFF, 0xF7, 0x11, 0xF9, 0x20, 0x22, - 0x00, 0x21, 0x44, 0xA8, 0xFF, 0xF7, 0x0C, 0xF9, 0x95, 0xE8, 0x0F, 0x00, 0x00, 0x25, 0x87, 0xE8, - 0x0F, 0x00, 0x4C, 0xF2, 0x50, 0x30, 0x31, 0x68, 0x2F, 0x46, 0x49, 0x00, 0x02, 0xF0, 0x64, 0xEC, - 0x33, 0x6F, 0x22, 0x90, 0x26, 0x94, 0x23, 0x93, 0x73, 0x6F, 0x24, 0x93, 0xB3, 0x6F, 0xC3, 0xF3, - 0x02, 0x23, 0x5B, 0x00, 0x25, 0x93, 0xF3, 0x69, 0x13, 0xF0, 0x01, 0x0F, 0x14, 0xBF, 0x04, 0x23, - 0x08, 0x23, 0x21, 0x93, 0x5B, 0x08, 0x1F, 0x93, 0xC3, 0xEB, 0x43, 0x73, 0x27, 0x93, 0x1F, 0x9B, - 0x4F, 0xF0, 0x03, 0x09, 0x4F, 0xF0, 0x00, 0x08, 0xAB, 0x42, 0x93, 0xBF, 0x27, 0x9B, 0x4F, 0xEA, - 0xC5, 0x0A, 0xDD, 0xF8, 0x8C, 0xB0, 0xDD, 0xF8, 0x90, 0xB0, 0x98, 0xBF, 0x03, 0xEB, 0x05, 0x0A, - 0x4F, 0xF0, 0xFF, 0x03, 0x98, 0xBF, 0x4F, 0xEA, 0xCA, 0x0A, 0x5C, 0x46, 0x03, 0xFA, 0x0A, 0xF3, - 0xDB, 0x43, 0x20, 0x93, 0x30, 0x46, 0xFF, 0xF7, 0x91, 0xFE, 0x33, 0x46, 0x01, 0x22, 0x29, 0x46, - 0x4F, 0xF4, 0x80, 0x60, 0xFF, 0xF7, 0x1E, 0xFA, 0x01, 0x28, 0x4F, 0xD0, 0x24, 0xFA, 0x0A, 0xF3, - 0x03, 0xF0, 0x3F, 0x03, 0xB8, 0xF1, 0x00, 0x0F, 0x40, 0xD1, 0x00, 0x2B, 0x2C, 0xAA, 0x04, 0xBF, - 0x5C, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x42, 0xF8, 0x25, 0x30, 0x4C, 0xAB, 0x24, 0xFA, 0x0A, 0xF7, - 0x03, 0xEB, 0x89, 0x03, 0xB8, 0xF1, 0x01, 0x0F, 0xFF, 0xB2, 0x53, 0xF8, 0x90, 0x3C, 0x5D, 0xD1, - 0x1F, 0x44, 0x3F, 0x2F, 0x28, 0xBF, 0x3F, 0x27, 0x20, 0x9B, 0x1C, 0x40, 0x07, 0xFA, 0x0A, 0xF3, - 0x1C, 0x43, 0x1F, 0x9B, 0xAB, 0x42, 0x8C, 0xBF, 0x34, 0x67, 0x74, 0x67, 0xB8, 0xF1, 0x02, 0x0F, - 0xC8, 0xD1, 0x26, 0x9B, 0x2C, 0xAA, 0x52, 0xF8, 0x25, 0x10, 0x3C, 0xA8, 0x53, 0xF8, 0x25, 0x30, - 0x5A, 0x1A, 0x0B, 0x44, 0x5B, 0x08, 0x44, 0xA9, 0x40, 0xF8, 0x25, 0x20, 0x41, 0xF8, 0x25, 0x30, - 0x25, 0x9B, 0x9A, 0x42, 0x3F, 0xD2, 0x14, 0x22, 0x5C, 0x48, 0x5A, 0x43, 0x29, 0x46, 0x01, 0x24, - 0xFF, 0xF7, 0x7B, 0xF8, 0x20, 0x46, 0x4D, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x26, 0x9A, 0x3F, 0x2B, - 0x08, 0xBF, 0x4F, 0xF0, 0x02, 0x08, 0x42, 0xF8, 0x25, 0x30, 0xBE, 0xE7, 0xB8, 0xF1, 0x00, 0x0F, - 0x10, 0xD1, 0xB9, 0xF1, 0x00, 0x0F, 0x19, 0xD0, 0x20, 0x9B, 0x1C, 0x40, 0x4C, 0xAB, 0x03, 0xEB, - 0x89, 0x03, 0x53, 0xF8, 0x90, 0x3C, 0x1F, 0x44, 0x07, 0xFA, 0x0A, 0xF7, 0x09, 0xF1, 0xFF, 0x39, - 0x3C, 0x43, 0xAA, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, 0x0D, 0xD0, 0x20, 0x9B, 0x1C, 0x40, 0x4C, 0xAB, - 0x03, 0xEB, 0x89, 0x03, 0x53, 0xF8, 0x90, 0x3C, 0xFF, 0x1A, 0xED, 0xE7, 0x5C, 0x46, 0x80, 0x46, - 0x4F, 0xF0, 0x03, 0x09, 0x99, 0xE7, 0x4F, 0xF0, 0x02, 0x08, 0x96, 0xE7, 0x9F, 0x42, 0x8C, 0xBF, - 0xFF, 0x1A, 0x00, 0x27, 0xA0, 0xE7, 0x22, 0x9B, 0x9A, 0x42, 0x04, 0xD9, 0x14, 0x22, 0x29, 0x46, - 0x5A, 0x43, 0x3B, 0x48, 0xBB, 0xE7, 0x23, 0x9B, 0x01, 0x35, 0x33, 0x67, 0x24, 0x9B, 0x73, 0x67, - 0x21, 0x9B, 0xAB, 0x42, 0x7F, 0xF4, 0x4B, 0xAF, 0x3C, 0x9B, 0xF4, 0x69, 0xDD, 0xE9, 0x44, 0x5E, - 0x1F, 0x93, 0x3D, 0x9B, 0x14, 0xF0, 0x01, 0x04, 0xDD, 0xE9, 0x46, 0x7C, 0x4F, 0xEA, 0x0E, 0x20, - 0x2C, 0x99, 0x24, 0x93, 0x2E, 0x9B, 0x34, 0x9A, 0xDD, 0xF8, 0xB4, 0xA0, 0x20, 0x93, 0x36, 0x9B, - 0xDD, 0xF8, 0xD4, 0xB0, 0xDD, 0xF8, 0xDC, 0x80, 0x22, 0x93, 0x3E, 0x9B, 0xDD, 0xF8, 0xFC, 0x90, - 0x23, 0x93, 0x2F, 0x9B, 0x21, 0x93, 0x4F, 0xD1, 0x40, 0xEA, 0x07, 0x40, 0x4A, 0x9B, 0x28, 0x43, - 0x40, 0xEA, 0x0C, 0x60, 0x30, 0x67, 0x18, 0x04, 0x49, 0x9B, 0x40, 0xEA, 0x03, 0x20, 0x48, 0x9B, - 0x18, 0x43, 0x4B, 0x9B, 0x1C, 0x93, 0x40, 0xEA, 0x03, 0x60, 0x4A, 0x9B, 0x70, 0x67, 0x43, 0x98, - 0x18, 0x93, 0x49, 0x9B, 0x1B, 0x90, 0x3B, 0x98, 0x14, 0x93, 0x48, 0x9B, 0x1A, 0x90, 0x33, 0x98, - 0x10, 0x93, 0x19, 0x90, 0x42, 0x98, 0x17, 0x90, 0x3A, 0x98, 0x16, 0x90, 0x32, 0x98, 0x15, 0x90, - 0x41, 0x98, 0x13, 0x90, 0x39, 0x98, 0x12, 0x90, 0x31, 0x98, 0x11, 0x90, 0x40, 0x98, 0x0F, 0x90, - 0x21, 0x9B, 0x38, 0x98, 0xCD, 0xE9, 0x00, 0x5A, 0xCD, 0xE9, 0x08, 0x73, 0x23, 0x9B, 0x0E, 0x90, - 0x30, 0x98, 0x07, 0x93, 0x22, 0x9B, 0xCD, 0xE9, 0x0C, 0xC0, 0x0A, 0x48, 0x06, 0x93, 0x20, 0x9B, - 0xCD, 0xE9, 0x0A, 0x89, 0xCD, 0xE9, 0x04, 0xE3, 0x24, 0x9B, 0xCD, 0xE9, 0x02, 0xB3, 0x1F, 0x9B, - 0xFE, 0xF7, 0xCB, 0xFF, 0x4E, 0xE7, 0x00, 0xBF, 0xAC, 0x29, 0x04, 0x00, 0x37, 0x2E, 0x04, 0x00, - 0x5F, 0x2E, 0x04, 0x00, 0x85, 0x2E, 0x04, 0x00, 0x21, 0x9B, 0x28, 0x43, 0x30, 0x67, 0x47, 0xEA, - 0x0C, 0x20, 0xCD, 0xF8, 0x28, 0x80, 0x00, 0x24, 0xCD, 0xE9, 0x08, 0x73, 0x23, 0x9B, 0x70, 0x67, - 0xCD, 0xE9, 0x00, 0x5A, 0x07, 0x93, 0x22, 0x9B, 0x06, 0x48, 0xCD, 0xE9, 0x0B, 0x9C, 0x06, 0x93, - 0x20, 0x9B, 0xCD, 0xE9, 0x04, 0xE3, 0x24, 0x9B, 0xCD, 0xE9, 0x02, 0xB3, 0x1F, 0x9B, 0xFE, 0xF7, - 0xA4, 0xFF, 0x27, 0xE7, 0x17, 0x2F, 0x04, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF5, 0x59, 0x7D, - 0x83, 0x46, 0x6C, 0x22, 0x68, 0x46, 0x0D, 0xF1, 0x6C, 0x0A, 0x55, 0x49, 0x36, 0xAE, 0xFE, 0xF7, - 0x9D, 0xFF, 0x6C, 0x22, 0x53, 0x49, 0x50, 0x46, 0x0D, 0xF5, 0xA2, 0x79, 0xFE, 0xF7, 0x96, 0xFF, - 0x6C, 0x22, 0x51, 0x49, 0x30, 0x46, 0x6C, 0xAD, 0xFE, 0xF7, 0x90, 0xFF, 0x6C, 0x22, 0x4F, 0x49, - 0x48, 0x46, 0x0D, 0xF5, 0x07, 0x78, 0xFE, 0xF7, 0x89, 0xFF, 0x6C, 0x22, 0x4C, 0x49, 0x28, 0x46, - 0xA2, 0xAC, 0xFE, 0xF7, 0x83, 0xFF, 0x6C, 0x22, 0x4A, 0x49, 0x40, 0x46, 0xBD, 0xAF, 0xFE, 0xF7, - 0x7D, 0xFF, 0x6C, 0x22, 0x48, 0x49, 0x20, 0x46, 0xFE, 0xF7, 0x78, 0xFF, 0x6C, 0x22, 0x47, 0x49, - 0x38, 0x46, 0xFE, 0xF7, 0x73, 0xFF, 0x46, 0x4B, 0x1A, 0x68, 0xDB, 0xF8, 0x04, 0x30, 0x92, 0xB2, - 0x03, 0x3B, 0xB2, 0xF5, 0x00, 0x6F, 0x02, 0xD0, 0xB2, 0xF5, 0x10, 0x5F, 0x34, 0xD1, 0x05, 0x2B, - 0x0E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x11, 0x0D, 0x0D, 0x1C, 0x27, 0x3D, 0x4B, 0x3E, 0x48, - 0x3E, 0x4A, 0x19, 0x18, 0x5A, 0xF8, 0x01, 0x10, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF8, 0xD1, - 0x0D, 0xF5, 0x59, 0x7D, 0xBD, 0xE8, 0xF0, 0x8F, 0x36, 0x4B, 0x37, 0x48, 0x37, 0x4A, 0x19, 0x18, - 0x59, 0xF8, 0x01, 0x10, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF8, 0xD1, 0xF0, 0xE7, 0x31, 0x4B, - 0x31, 0x48, 0x32, 0x4A, 0x19, 0x18, 0x58, 0xF8, 0x01, 0x10, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, - 0xF8, 0xD1, 0xE5, 0xE7, 0x2B, 0x4B, 0x2C, 0x48, 0x2C, 0x4A, 0x19, 0x18, 0x79, 0x58, 0x43, 0xF8, - 0x04, 0x1B, 0x93, 0x42, 0xF9, 0xD1, 0xDB, 0xE7, 0x05, 0x2B, 0xD9, 0xD8, 0x01, 0xA2, 0x52, 0xF8, - 0x23, 0xF0, 0x00, 0xBF, 0xDD, 0xFF, 0x03, 0x00, 0xF3, 0xFF, 0x03, 0x00, 0x71, 0xFF, 0x03, 0x00, - 0x71, 0xFF, 0x03, 0x00, 0x07, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x04, 0x00, 0x1D, 0x4B, 0x1E, 0x48, - 0x1E, 0x4A, 0x19, 0x18, 0x5D, 0xF8, 0x01, 0x10, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF8, 0xD1, - 0xBE, 0xE7, 0x18, 0x4B, 0x18, 0x48, 0x19, 0x4A, 0x19, 0x18, 0x71, 0x58, 0x43, 0xF8, 0x04, 0x1B, - 0x93, 0x42, 0xF9, 0xD1, 0xB4, 0xE7, 0x13, 0x4B, 0x13, 0x48, 0x14, 0x4A, 0x19, 0x18, 0x69, 0x58, - 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF9, 0xD1, 0xAA, 0xE7, 0x0E, 0x4B, 0x0E, 0x48, 0x0F, 0x4A, - 0x19, 0x18, 0x61, 0x58, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF9, 0xD1, 0xA0, 0xE7, 0x00, 0xBF, - 0xDC, 0x29, 0x04, 0x00, 0x48, 0x2A, 0x04, 0x00, 0xB4, 0x2A, 0x04, 0x00, 0x20, 0x2B, 0x04, 0x00, - 0x8C, 0x2B, 0x04, 0x00, 0xF8, 0x2B, 0x04, 0x00, 0x64, 0x2C, 0x04, 0x00, 0xD0, 0x2C, 0x04, 0x00, - 0x00, 0x62, 0x00, 0x03, 0xC0, 0x00, 0x83, 0x04, 0x40, 0xFF, 0x7C, 0xFB, 0x2C, 0x01, 0x83, 0x04, - 0x10, 0xB5, 0x01, 0x20, 0x06, 0x4C, 0x23, 0x68, 0x23, 0xF0, 0x80, 0x73, 0x43, 0xF4, 0x00, 0x73, - 0x23, 0x60, 0xFE, 0xF7, 0xDB, 0xFE, 0x23, 0x68, 0x43, 0xF0, 0x80, 0x73, 0x23, 0x60, 0x10, 0xBD, - 0x08, 0x00, 0x81, 0x04, 0xF8, 0xB5, 0x04, 0x46, 0x53, 0x4E, 0x45, 0x68, 0x33, 0x68, 0x53, 0x4F, - 0x08, 0x2D, 0x53, 0x4A, 0x23, 0xF0, 0x10, 0x03, 0x33, 0x60, 0x02, 0xBF, 0x3B, 0x68, 0x23, 0xF0, - 0x80, 0x03, 0x3B, 0x60, 0x13, 0x68, 0xC1, 0x69, 0x23, 0xF0, 0x0F, 0x03, 0xC8, 0x07, 0x4C, 0xBF, - 0x43, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x0F, 0x03, 0x07, 0x2D, 0x13, 0x60, 0x71, 0xD0, 0x08, 0x2D, - 0x72, 0xD0, 0x04, 0x2D, 0x4F, 0xF0, 0x0D, 0x02, 0x0C, 0xBF, 0x0A, 0x23, 0x09, 0x23, 0x45, 0x49, - 0x20, 0x46, 0x0A, 0x60, 0x04, 0x31, 0xC1, 0xF8, 0x44, 0x23, 0xC1, 0xF8, 0x50, 0x23, 0xC1, 0xF8, - 0x5C, 0x23, 0x00, 0x22, 0x0A, 0x60, 0xC1, 0xF8, 0x48, 0x23, 0xC1, 0xF8, 0x54, 0x23, 0xC1, 0xF8, - 0x60, 0x23, 0x3D, 0x4A, 0x13, 0x60, 0xC2, 0xF8, 0x48, 0x33, 0xC2, 0xF8, 0x54, 0x33, 0xC2, 0xF8, - 0x60, 0x33, 0xFF, 0xF7, 0xE1, 0xFE, 0x20, 0x46, 0xFF, 0xF7, 0x9C, 0xFA, 0xFF, 0xF7, 0xBE, 0xFA, - 0xB4, 0xF8, 0x6E, 0x30, 0x0B, 0xB1, 0xFF, 0xF7, 0x75, 0xFB, 0x3B, 0x68, 0x07, 0x2D, 0x23, 0xF0, - 0x07, 0x03, 0x49, 0xD0, 0x08, 0x2D, 0x4A, 0xD0, 0x04, 0x2D, 0x4B, 0xD1, 0x43, 0xF0, 0x04, 0x03, - 0x43, 0xF0, 0x08, 0x03, 0x2D, 0x4D, 0x3B, 0x60, 0x23, 0x68, 0xB3, 0xF5, 0x28, 0x7F, 0x9E, 0xBF, - 0x2B, 0x4B, 0x0F, 0x22, 0x1A, 0x60, 0x23, 0x68, 0xB3, 0xF5, 0xFA, 0x7F, 0x29, 0x4B, 0x1A, 0x68, - 0x3B, 0xD8, 0x42, 0xF0, 0x80, 0x02, 0x1A, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, - 0x20, 0x03, 0x25, 0x4A, 0x01, 0x20, 0x2B, 0x60, 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, - 0xFE, 0xF7, 0x5C, 0xFE, 0x2B, 0x68, 0x21, 0x4A, 0x23, 0xF0, 0x08, 0x03, 0x2B, 0x60, 0x13, 0x68, - 0x59, 0x07, 0xFC, 0xD5, 0xA3, 0x6F, 0xDB, 0x06, 0x03, 0xD4, 0x4F, 0xF4, 0x7A, 0x70, 0xFE, 0xF7, - 0x4D, 0xFE, 0x1B, 0x4B, 0x37, 0x22, 0x1A, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x33, 0x60, - 0xF8, 0xBD, 0x08, 0x23, 0x0E, 0x22, 0x92, 0xE7, 0xA2, 0x6F, 0x0A, 0x23, 0x12, 0xF0, 0x80, 0x5F, - 0x14, 0xBF, 0x16, 0x22, 0x14, 0x22, 0x8A, 0xE7, 0x43, 0xF0, 0x03, 0x03, 0xB8, 0xE7, 0x43, 0xF0, - 0x05, 0x03, 0xB5, 0xE7, 0x43, 0xF0, 0x02, 0x03, 0xB2, 0xE7, 0x22, 0xF0, 0x80, 0x02, 0x1A, 0x60, - 0x2B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0xC4, 0xE7, 0x50, 0x02, 0x01, 0x07, 0x04, 0x00, 0x83, 0x04, - 0x3C, 0x00, 0x83, 0x04, 0x14, 0x00, 0x83, 0x04, 0x1C, 0x00, 0x83, 0x04, 0x4C, 0x01, 0x83, 0x04, - 0x20, 0x00, 0x83, 0x04, 0x44, 0x01, 0x83, 0x04, 0x08, 0x00, 0x81, 0x04, 0x80, 0x01, 0x83, 0x04, - 0x58, 0x00, 0x83, 0x04, 0x3D, 0x4B, 0x41, 0x68, 0xF0, 0xB5, 0x1A, 0x68, 0x04, 0x29, 0x3C, 0x4C, - 0x22, 0xF0, 0xC0, 0x02, 0x42, 0xF0, 0x80, 0x02, 0x1A, 0x60, 0x3A, 0x4A, 0x4C, 0xD1, 0x90, 0xF8, - 0x24, 0x10, 0x21, 0x60, 0x90, 0xF8, 0x25, 0x10, 0x41, 0xF0, 0x40, 0x01, 0x11, 0x60, 0x1A, 0x68, - 0x35, 0x4C, 0x42, 0xF0, 0x04, 0x02, 0x1A, 0x60, 0xC2, 0x69, 0x12, 0xF0, 0x01, 0x0F, 0x48, 0xD0, - 0x22, 0x68, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0xFA, 0xD1, 0x1A, 0x68, 0x00, 0x21, 0x2F, 0x4F, - 0x0E, 0x46, 0x22, 0xF0, 0x04, 0x02, 0x1A, 0x60, 0x0A, 0x46, 0x3A, 0x44, 0x92, 0x00, 0x12, 0x68, - 0x00, 0x2A, 0x43, 0xD0, 0x3F, 0x2A, 0x08, 0xBF, 0x01, 0x21, 0x75, 0x1C, 0x04, 0x2D, 0x36, 0xD1, - 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, 0xC2, 0x69, 0xD5, 0x04, 0x15, 0xD5, 0x1A, 0x68, - 0x22, 0xF0, 0xC0, 0x02, 0x42, 0xF0, 0x40, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x04, 0x02, - 0x1A, 0x60, 0xC2, 0x69, 0xD2, 0x07, 0x2B, 0xD5, 0x22, 0x68, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, - 0xFA, 0xD1, 0x1A, 0x68, 0x22, 0xF0, 0x04, 0x02, 0x1A, 0x60, 0x1A, 0x68, 0x81, 0xF0, 0x01, 0x00, - 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, 0xF0, 0xBD, 0x06, 0x39, 0x02, 0x29, 0x91, 0xBF, 0x90, 0xF8, - 0x28, 0x10, 0x04, 0x21, 0x21, 0x60, 0x40, 0x21, 0x9C, 0xBF, 0x21, 0x60, 0x90, 0xF8, 0x29, 0x10, - 0xAC, 0xE7, 0x22, 0x68, 0x02, 0xF0, 0x0F, 0x02, 0x0F, 0x2A, 0xFA, 0xD1, 0xB5, 0xE7, 0x01, 0x2D, - 0x14, 0xBF, 0x06, 0xF1, 0x2F, 0x02, 0x2A, 0x46, 0x2E, 0x46, 0xB6, 0xE7, 0x01, 0x21, 0xBC, 0xE7, - 0x22, 0x68, 0x02, 0xF0, 0x0F, 0x02, 0x0F, 0x2A, 0xFA, 0xD1, 0xD2, 0xE7, 0x08, 0x00, 0x83, 0x04, - 0x0C, 0x00, 0x83, 0x04, 0x10, 0x00, 0x83, 0x04, 0x88, 0x01, 0x83, 0x04, 0x96, 0xC0, 0x20, 0x01, - 0x31, 0x4B, 0x10, 0xB5, 0x1A, 0x68, 0x22, 0xF0, 0x30, 0x02, 0x42, 0xF0, 0x20, 0x02, 0x1A, 0x60, - 0x42, 0x68, 0x04, 0x2A, 0x01, 0xBF, 0x2D, 0x49, 0x0A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x0A, 0x60, - 0x1A, 0x68, 0x2B, 0x49, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0xC2, 0x69, 0x12, 0xF0, 0x01, 0x02, - 0x0C, 0xD1, 0x0C, 0x68, 0x04, 0xF0, 0x0F, 0x04, 0x0F, 0x2C, 0x0D, 0xD0, 0x0C, 0x68, 0xA4, 0x06, - 0xF7, 0xD5, 0x01, 0x22, 0x08, 0xE0, 0x0C, 0x68, 0xA4, 0x06, 0x05, 0xD4, 0x0C, 0x68, 0x04, 0xF0, - 0x03, 0x04, 0x03, 0x2C, 0xF7, 0xD1, 0x00, 0x22, 0x1C, 0x68, 0x24, 0xF0, 0x01, 0x04, 0x1C, 0x60, - 0x1C, 0x68, 0x24, 0xF0, 0x30, 0x04, 0x1C, 0x60, 0xC4, 0x69, 0xE4, 0x04, 0x23, 0xD5, 0x1C, 0x68, - 0x24, 0xF0, 0x30, 0x04, 0x44, 0xF0, 0x10, 0x04, 0x1C, 0x60, 0x1C, 0x68, 0x44, 0xF0, 0x01, 0x04, - 0x1C, 0x60, 0xC0, 0x69, 0x10, 0xF0, 0x01, 0x00, 0x0C, 0xD1, 0x08, 0x68, 0x00, 0xF0, 0x0F, 0x00, - 0x0F, 0x28, 0x0C, 0xD0, 0x08, 0x68, 0x80, 0x06, 0xF7, 0xD5, 0x01, 0x22, 0x07, 0xE0, 0x0C, 0x68, - 0xA4, 0x06, 0x0F, 0xD4, 0x0C, 0x68, 0x04, 0xF0, 0x03, 0x04, 0x03, 0x2C, 0xF7, 0xD1, 0x19, 0x68, - 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, 0x82, 0xF0, 0x01, 0x00, 0x21, 0xF0, 0x30, 0x01, - 0x19, 0x60, 0x10, 0xBD, 0x02, 0x46, 0xF2, 0xE7, 0x08, 0x00, 0x83, 0x04, 0x54, 0x00, 0x83, 0x04, - 0x84, 0x01, 0x83, 0x04, 0x03, 0x6F, 0x2D, 0xE9, 0xF7, 0x4F, 0xCA, 0x00, 0x04, 0x6E, 0x05, 0x46, - 0x88, 0x46, 0x00, 0x93, 0x43, 0x6F, 0x18, 0x20, 0xD4, 0x40, 0x6E, 0x4E, 0x01, 0x93, 0x04, 0xF0, - 0x1F, 0x04, 0x6D, 0x4B, 0x61, 0x1C, 0x1B, 0x68, 0x1B, 0x0A, 0x01, 0x33, 0xDB, 0xB2, 0x58, 0x43, - 0x02, 0xF0, 0x62, 0xE8, 0x47, 0x00, 0x41, 0x46, 0x68, 0x48, 0x3A, 0x46, 0xFE, 0xF7, 0xF5, 0xFC, - 0x67, 0x4A, 0x33, 0x68, 0x92, 0x46, 0x43, 0xF0, 0x20, 0x03, 0x33, 0x60, 0x13, 0x68, 0x03, 0xF0, - 0x07, 0x03, 0x03, 0x2B, 0xFA, 0xD1, 0x01, 0x20, 0xDF, 0xF8, 0xB0, 0xB1, 0xFE, 0xF7, 0xF6, 0xFC, - 0xDF, 0xF8, 0xAC, 0xC1, 0xB7, 0xF5, 0x28, 0x7F, 0x5E, 0x4A, 0xDC, 0xF8, 0x00, 0x30, 0x91, 0x46, - 0x23, 0xF0, 0x10, 0x03, 0xCC, 0xF8, 0x00, 0x30, 0x4F, 0xF0, 0x00, 0x03, 0xCB, 0xF8, 0x00, 0x30, - 0x13, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x13, 0x60, 0x4F, 0xF0, 0x01, 0x03, 0xCB, 0xF8, 0x00, 0x30, - 0x55, 0x4B, 0x19, 0x68, 0x41, 0xF0, 0x08, 0x01, 0x19, 0x60, 0x54, 0x49, 0x08, 0x68, 0x20, 0xF0, - 0x20, 0x00, 0x08, 0x60, 0x52, 0x48, 0xD0, 0xF8, 0x00, 0xE0, 0x2E, 0xF0, 0x40, 0x7E, 0xC0, 0xF8, - 0x00, 0xE0, 0xD0, 0xF8, 0x00, 0xE0, 0x2E, 0xF0, 0x1F, 0x0E, 0x44, 0xEA, 0x0E, 0x04, 0x04, 0x60, - 0x44, 0xF0, 0x00, 0x64, 0x04, 0x60, 0x64, 0x46, 0x4A, 0x48, 0x7A, 0xD8, 0x02, 0xF5, 0x7E, 0x42, - 0xB7, 0xF5, 0xFA, 0x7F, 0x02, 0xF1, 0x70, 0x02, 0x4F, 0xF0, 0x0F, 0x0E, 0xC2, 0xF8, 0x00, 0xE0, - 0x6F, 0xD8, 0x02, 0x68, 0x42, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x18, 0x68, 0x20, 0xF0, 0xE0, 0x00, - 0x40, 0xF0, 0x20, 0x00, 0x18, 0x60, 0x18, 0x68, 0x20, 0xF0, 0x08, 0x00, 0x18, 0x60, 0x3E, 0x48, - 0x03, 0x68, 0x5B, 0x07, 0xFC, 0xD5, 0x32, 0x20, 0xFE, 0xF7, 0xA0, 0xFC, 0x37, 0x49, 0x3B, 0x4A, - 0x0B, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x0B, 0x60, 0x00, 0x23, 0xCB, 0xF8, 0x00, 0x30, 0xD9, 0xF8, - 0x00, 0x30, 0x23, 0xF0, 0x20, 0x03, 0xC9, 0xF8, 0x00, 0x30, 0x01, 0x23, 0xCB, 0xF8, 0x00, 0x30, - 0x13, 0x68, 0x01, 0x2B, 0xFC, 0xD1, 0x32, 0x4A, 0x13, 0x68, 0xD9, 0x07, 0xFC, 0xD5, 0x23, 0x68, - 0x43, 0xF0, 0x10, 0x03, 0x23, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x20, 0x03, 0x33, 0x60, 0xDA, 0xF8, - 0x00, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0xF9, 0xD0, 0x2A, 0x4A, 0x28, 0x46, 0x13, 0x68, - 0x23, 0xF0, 0x0C, 0x03, 0x43, 0xEA, 0x88, 0x03, 0x13, 0x60, 0xFF, 0xF7, 0xE1, 0xFE, 0x04, 0x46, - 0x20, 0xB9, 0x3A, 0x46, 0x41, 0x46, 0x24, 0x48, 0xFE, 0xF7, 0x57, 0xFC, 0xEB, 0x6C, 0xDA, 0x03, - 0x14, 0xD5, 0xB7, 0xF5, 0xB4, 0x7F, 0x11, 0xD8, 0xC3, 0xF3, 0x05, 0x21, 0x03, 0xF0, 0x3F, 0x03, - 0x0A, 0x04, 0x42, 0xEA, 0x01, 0x62, 0x0A, 0x43, 0x42, 0xEA, 0x01, 0x22, 0x2A, 0x67, 0x1A, 0x04, - 0x42, 0xEA, 0x03, 0x62, 0x1A, 0x43, 0x42, 0xEA, 0x03, 0x23, 0x6B, 0x67, 0x28, 0x46, 0xFF, 0xF7, - 0x05, 0xFA, 0x00, 0x9B, 0x20, 0x46, 0x2B, 0x67, 0x01, 0x9B, 0x6B, 0x67, 0x03, 0xB0, 0xBD, 0xE8, - 0xF0, 0x8F, 0x02, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x02, 0x60, 0x18, 0x68, 0x20, 0xF0, 0xE0, 0x00, - 0x90, 0xE7, 0x00, 0xBF, 0x30, 0x00, 0x82, 0x04, 0x10, 0x10, 0x00, 0x03, 0x6A, 0x2F, 0x04, 0x00, - 0x04, 0x00, 0x82, 0x04, 0xB0, 0x01, 0x82, 0x04, 0x4C, 0x01, 0x83, 0x04, 0x58, 0x00, 0x83, 0x04, - 0x00, 0x18, 0x00, 0x03, 0x44, 0x01, 0x83, 0x04, 0x80, 0x01, 0x83, 0x04, 0x24, 0x03, 0x82, 0x04, - 0xBC, 0x01, 0x82, 0x04, 0x54, 0x00, 0x83, 0x04, 0x7F, 0x2F, 0x04, 0x00, 0x20, 0x03, 0x82, 0x04, - 0x50, 0x02, 0x01, 0x07, 0x2D, 0xE9, 0xF8, 0x4F, 0x07, 0x46, 0x43, 0x68, 0xA4, 0x49, 0x08, 0x2B, - 0xA4, 0x4D, 0x04, 0xBF, 0xA4, 0x4A, 0x00, 0x23, 0x88, 0x46, 0x04, 0xBF, 0x13, 0x60, 0xD3, 0x61, - 0x0A, 0x68, 0x43, 0x8B, 0xA1, 0x48, 0x22, 0xF0, 0x03, 0x02, 0x42, 0xF0, 0x02, 0x02, 0x0A, 0x60, - 0x5B, 0x00, 0x02, 0x68, 0x13, 0xF0, 0x1E, 0x03, 0x08, 0xBF, 0x0F, 0x23, 0x22, 0xF0, 0x3F, 0x02, - 0x1A, 0x43, 0x02, 0x60, 0x42, 0x68, 0x22, 0xF0, 0x3F, 0x02, 0x1A, 0x43, 0x42, 0x60, 0xD0, 0xF8, - 0x00, 0x22, 0x22, 0xF0, 0x3F, 0x02, 0x1A, 0x43, 0xC0, 0xF8, 0x00, 0x22, 0xD0, 0xF8, 0x04, 0x22, - 0x22, 0xF0, 0x3F, 0x02, 0x13, 0x43, 0xC0, 0xF8, 0x04, 0x32, 0x2B, 0x68, 0x43, 0xF0, 0x06, 0x03, - 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x2B, 0x60, 0x8D, 0x4B, 0x99, 0x46, 0x1A, 0x68, - 0x02, 0xF0, 0x0C, 0x02, 0x0C, 0x2A, 0xFA, 0xD1, 0x1C, 0x68, 0x14, 0xF0, 0x03, 0x04, 0x03, 0xD0, - 0x01, 0x24, 0x88, 0x48, 0xFE, 0xF7, 0xC1, 0xFB, 0xFB, 0x69, 0xDA, 0x07, 0x0C, 0xD4, 0x86, 0x4A, - 0x13, 0x68, 0x03, 0xF0, 0x0C, 0x03, 0x0C, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0x03, 0xD0, - 0x01, 0x24, 0x82, 0x48, 0xFE, 0xF7, 0xB1, 0xFB, 0x81, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0x81, 0x4E, - 0xDF, 0xF8, 0xA4, 0xB2, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, + 0x1F, 0x3F, 0x14, 0xBF, 0xC3, 0xF3, 0x04, 0x23, 0x04, 0x23, 0x13, 0x60, 0xC3, 0x89, 0x41, 0x4A, + 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x04, 0x32, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x07, 0xD1, + 0xC3, 0x6D, 0x13, 0xF0, 0x1F, 0x3F, 0x14, 0xBF, 0xC3, 0xF3, 0x04, 0x43, 0x04, 0x23, 0x13, 0x60, + 0xC3, 0x7B, 0x39, 0x4A, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x04, 0x32, 0x13, 0x60, 0x43, 0x68, + 0x08, 0x2B, 0x07, 0xD1, 0xC3, 0x6D, 0x13, 0xF0, 0x1F, 0x3F, 0x14, 0xBF, 0xC3, 0xF3, 0x04, 0x63, + 0x04, 0x23, 0x13, 0x60, 0x03, 0x69, 0x31, 0x4A, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x40, 0x32, + 0x42, 0xF8, 0x3C, 0x3C, 0x03, 0x69, 0xC3, 0xF3, 0x04, 0x23, 0x42, 0xF8, 0x38, 0x3C, 0x42, 0xF8, + 0x34, 0x3C, 0x83, 0x68, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x41, 0x68, 0x04, 0x29, 0x01, 0xD0, + 0x07, 0x29, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x60, 0x25, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, + 0x04, 0xBF, 0x00, 0x23, 0x13, 0x60, 0x83, 0x68, 0x22, 0x4A, 0xC3, 0xF3, 0x04, 0x23, 0x13, 0x60, + 0x41, 0x68, 0x04, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x60, 0x1E, 0x4A, + 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x04, 0xBF, 0x00, 0x23, 0x13, 0x60, 0x43, 0x89, 0x1B, 0x4A, + 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x41, 0x68, 0x04, 0x29, 0x01, 0xD0, 0x07, 0x29, 0x01, 0xD1, + 0x00, 0x21, 0x11, 0x60, 0x16, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x08, 0x2B, 0x04, 0xBF, 0x00, 0x23, + 0x13, 0x60, 0xC3, 0x7A, 0x13, 0x4A, 0x03, 0xF0, 0x1F, 0x03, 0x13, 0x60, 0x41, 0x68, 0x04, 0x29, + 0x01, 0xD0, 0x07, 0x29, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x60, 0x0F, 0x4A, 0x13, 0x60, 0x43, 0x68, + 0x08, 0x2B, 0x04, 0xBF, 0x00, 0x23, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x88, 0x03, 0x83, 0x04, + 0xC8, 0x03, 0x83, 0x04, 0x08, 0x04, 0x83, 0x04, 0x48, 0x04, 0x83, 0x04, 0x40, 0x03, 0x83, 0x04, + 0x84, 0x03, 0x83, 0x04, 0xC0, 0x03, 0x83, 0x04, 0xC4, 0x03, 0x83, 0x04, 0x00, 0x04, 0x83, 0x04, + 0x04, 0x04, 0x83, 0x04, 0x40, 0x04, 0x83, 0x04, 0x44, 0x04, 0x83, 0x04, 0x5C, 0x4B, 0xC1, 0x6E, + 0x10, 0xB5, 0x1C, 0x68, 0x00, 0x29, 0x42, 0x68, 0xA4, 0xB2, 0x0B, 0xDA, 0x83, 0x6D, 0xB4, 0xF5, + 0x00, 0x6F, 0x02, 0xD0, 0xB4, 0xF5, 0x10, 0x5F, 0x46, 0xD1, 0x03, 0x2A, 0x16, 0xD0, 0x08, 0x2A, + 0x2C, 0xD0, 0x10, 0xBD, 0x4B, 0x01, 0x48, 0x02, 0x03, 0xF4, 0xF0, 0x53, 0x00, 0xF4, 0xF0, 0x10, + 0x03, 0x43, 0x48, 0x00, 0x00, 0xF0, 0x1E, 0x00, 0x03, 0x43, 0x48, 0x03, 0x49, 0x0F, 0x00, 0xF0, + 0xF0, 0x50, 0x43, 0xEA, 0x00, 0x03, 0x18, 0xBF, 0x5B, 0x00, 0xE0, 0xE7, 0x49, 0x4A, 0xC3, 0xF3, + 0x05, 0x20, 0x49, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, 0x47, 0x49, 0x03, 0xF0, + 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, 0x05, 0x41, 0x45, 0x4A, 0xC3, 0xF3, 0x05, 0x63, + 0x11, 0x60, 0x02, 0xF5, 0xDD, 0x52, 0x04, 0x32, 0x13, 0x60, 0xD2, 0xE7, 0x3D, 0x4A, 0xC3, 0xF3, + 0x05, 0x20, 0x3D, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, 0x3B, 0x49, 0x03, 0xF0, + 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, 0x05, 0x41, 0x39, 0x4A, 0xC3, 0xF3, 0x05, 0x63, + 0x11, 0x60, 0x42, 0xF8, 0x54, 0x3C, 0xBC, 0xE7, 0x03, 0x3A, 0x05, 0x2A, 0xB9, 0xD8, 0x01, 0xA1, + 0x51, 0xF8, 0x22, 0xF0, 0x9D, 0xFF, 0x03, 0x00, 0xC9, 0xFF, 0x03, 0x00, 0xF3, 0xFE, 0x03, 0x00, + 0xF3, 0xFE, 0x03, 0x00, 0xEB, 0xFF, 0x03, 0x00, 0x15, 0x00, 0x04, 0x00, 0x29, 0x4A, 0xC3, 0xF3, + 0x05, 0x20, 0x29, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, 0x27, 0x49, 0x03, 0xF0, + 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, 0x05, 0x41, 0x26, 0x4A, 0xC3, 0xF3, 0x05, 0x63, + 0x11, 0x60, 0x42, 0xF8, 0x34, 0x3C, 0x94, 0xE7, 0x1E, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x1E, 0x49, + 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, 0x1C, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0xC3, 0xF3, + 0x05, 0x43, 0x0A, 0x60, 0x4A, 0x60, 0x1C, 0x4A, 0xAE, 0xE7, 0x16, 0x4A, 0xC3, 0xF3, 0x05, 0x20, + 0x15, 0x49, 0x42, 0xF8, 0x04, 0x0B, 0x8A, 0x42, 0xFB, 0xD1, 0x14, 0x49, 0x03, 0xF0, 0x3F, 0x02, + 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, 0x05, 0x41, 0x14, 0x4A, 0xC3, 0xF3, 0x05, 0x63, 0x11, 0x60, + 0x93, 0x60, 0x6E, 0xE7, 0x0B, 0x4A, 0xC3, 0xF3, 0x05, 0x20, 0x0B, 0x49, 0x42, 0xF8, 0x04, 0x0B, + 0x8A, 0x42, 0xFB, 0xD1, 0x09, 0x49, 0x03, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x4A, 0x60, 0xC3, 0xF3, + 0x05, 0x41, 0x0B, 0x4A, 0xC3, 0xF3, 0x05, 0x63, 0x11, 0x60, 0x42, 0xF8, 0x04, 0x3C, 0x58, 0xE7, + 0x00, 0x62, 0x00, 0x03, 0x80, 0x07, 0x83, 0x04, 0x00, 0x08, 0x83, 0x04, 0xDC, 0x07, 0x83, 0x04, + 0xE4, 0x07, 0x83, 0x04, 0xB8, 0x07, 0x83, 0x04, 0x84, 0x07, 0x83, 0x04, 0x88, 0x07, 0x83, 0x04, + 0x90, 0x07, 0x83, 0x04, 0xC3, 0x6E, 0x10, 0xB5, 0x5A, 0x03, 0x71, 0xD5, 0x6E, 0x4B, 0x6F, 0x49, + 0x6F, 0x4C, 0x1A, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x0A, 0x68, 0x42, 0xF0, 0x08, 0x02, + 0x0A, 0x60, 0x01, 0xF5, 0xC4, 0x71, 0x0A, 0x68, 0x22, 0xF0, 0x10, 0x02, 0x0A, 0x60, 0x42, 0x68, + 0x08, 0x2A, 0x01, 0xBF, 0xA1, 0xF5, 0xC6, 0x71, 0x0A, 0x68, 0x22, 0xF0, 0x80, 0x02, 0x0A, 0x60, + 0x02, 0x6F, 0x64, 0x49, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, + 0xA1, 0x42, 0xF9, 0xD1, 0x42, 0x69, 0x60, 0x4C, 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0x50, 0x34, + 0x22, 0x67, 0x0A, 0x60, 0x5D, 0x49, 0x0A, 0x60, 0xB4, 0x39, 0x02, 0x6F, 0xC2, 0xF3, 0x05, 0x22, + 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0x42, 0x69, 0x58, 0x4C, + 0xC2, 0xF3, 0x05, 0x22, 0x22, 0x60, 0x04, 0xF5, 0x94, 0x74, 0x44, 0xF8, 0x68, 0x2C, 0x0A, 0x60, + 0x54, 0x49, 0x0A, 0x60, 0x24, 0x31, 0xB0, 0xF8, 0x72, 0x20, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, + 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0xC2, 0x8A, 0x4E, 0x4C, 0x02, 0xF0, + 0x3F, 0x02, 0x22, 0x60, 0x50, 0x34, 0x22, 0x67, 0x0A, 0x60, 0x4C, 0x49, 0x0A, 0x60, 0xB4, 0x39, + 0x90, 0xF8, 0x73, 0x20, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, + 0xA1, 0x42, 0xF9, 0xD1, 0xC2, 0x7D, 0x46, 0x4C, 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0xC4, 0xF8, + 0xC0, 0x20, 0x0A, 0x60, 0x43, 0x49, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, + 0xC3, 0x6E, 0x9B, 0x03, 0x67, 0xD5, 0x40, 0x4B, 0x40, 0x49, 0x41, 0x4C, 0x1A, 0x68, 0x22, 0xF0, + 0x80, 0x02, 0x1A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x04, 0x02, 0x0A, 0x60, 0x01, 0xF5, 0x3C, 0x71, + 0x42, 0x6F, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, + 0xF9, 0xD1, 0xC2, 0x6F, 0x37, 0x4C, 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0x0C, 0x3C, 0xC4, 0xF8, + 0xCC, 0x20, 0x0A, 0x60, 0x34, 0x49, 0x0A, 0x60, 0xB4, 0x39, 0x42, 0x6F, 0xC2, 0xF3, 0x05, 0x22, + 0x0A, 0x60, 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0xC2, 0x6F, 0x2F, 0x4C, + 0xC2, 0xF3, 0x05, 0x22, 0x22, 0x60, 0x04, 0xF5, 0x8E, 0x74, 0x44, 0xF8, 0x5C, 0x2C, 0x0A, 0x60, + 0x2B, 0x49, 0x0A, 0x60, 0x24, 0x31, 0xB0, 0xF8, 0x76, 0x20, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, + 0x08, 0x31, 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0xB0, 0xF8, 0x7E, 0x20, 0x25, 0x4C, + 0x02, 0xF0, 0x3F, 0x02, 0x22, 0x60, 0x0C, 0x3C, 0xC4, 0xF8, 0xCC, 0x20, 0x0A, 0x60, 0x22, 0x49, + 0x0A, 0x60, 0xB4, 0x39, 0x90, 0xF8, 0x77, 0x20, 0x02, 0xF0, 0x3F, 0x02, 0x0A, 0x60, 0x08, 0x31, + 0xC1, 0xF8, 0xB8, 0x20, 0xA1, 0x42, 0xF9, 0xD1, 0x90, 0xF8, 0x7F, 0x20, 0x1B, 0x48, 0x02, 0xF0, + 0x3F, 0x02, 0x02, 0x60, 0xC0, 0xF8, 0xC0, 0x20, 0x0A, 0x60, 0x19, 0x49, 0x0A, 0x60, 0x1A, 0x68, + 0x42, 0xF0, 0x80, 0x02, 0x1A, 0x60, 0x10, 0xBD, 0x60, 0x00, 0x83, 0x04, 0x08, 0x00, 0x83, 0x04, + 0xCC, 0x04, 0x83, 0x04, 0x84, 0x04, 0x83, 0x04, 0xD0, 0x04, 0x83, 0x04, 0x8C, 0x05, 0x83, 0x04, + 0x24, 0x05, 0x83, 0x04, 0xE0, 0x05, 0x83, 0x04, 0x50, 0x06, 0x83, 0x04, 0x0C, 0x07, 0x83, 0x04, + 0xA4, 0x06, 0x83, 0x04, 0x60, 0x07, 0x83, 0x04, 0x54, 0x00, 0x83, 0x04, 0x90, 0x01, 0x83, 0x04, + 0xC8, 0x04, 0x83, 0x04, 0x28, 0x05, 0x83, 0x04, 0x88, 0x05, 0x83, 0x04, 0x2C, 0x05, 0x83, 0x04, + 0xDC, 0x05, 0x83, 0x04, 0xA8, 0x06, 0x83, 0x04, 0x08, 0x07, 0x83, 0x04, 0xAC, 0x06, 0x83, 0x04, + 0x5C, 0x07, 0x83, 0x04, 0x2D, 0xE9, 0xF0, 0x4F, 0x06, 0x46, 0xAD, 0x4D, 0xCD, 0xB0, 0x2C, 0xAC, + 0x28, 0xAF, 0x0F, 0xCD, 0x0F, 0xC4, 0x95, 0xE8, 0x0F, 0x00, 0x10, 0x35, 0x84, 0xE8, 0x0F, 0x00, + 0x34, 0xAC, 0x20, 0x22, 0x00, 0x21, 0x20, 0x46, 0xFE, 0xF7, 0xFC, 0xFD, 0x20, 0x22, 0x00, 0x21, + 0x3C, 0xA8, 0xFE, 0xF7, 0xF7, 0xFD, 0x20, 0x22, 0x00, 0x21, 0x44, 0xA8, 0xFE, 0xF7, 0xF2, 0xFD, + 0x95, 0xE8, 0x0F, 0x00, 0x00, 0x25, 0x87, 0xE8, 0x0F, 0x00, 0x4C, 0xF2, 0x50, 0x30, 0x31, 0x68, + 0x2F, 0x46, 0x49, 0x00, 0x02, 0xF0, 0x64, 0xEC, 0x33, 0x6F, 0x22, 0x90, 0x26, 0x94, 0x23, 0x93, + 0x73, 0x6F, 0x24, 0x93, 0xB3, 0x6F, 0xC3, 0xF3, 0x02, 0x23, 0x5B, 0x00, 0x25, 0x93, 0xF3, 0x69, + 0x13, 0xF0, 0x01, 0x0F, 0x14, 0xBF, 0x04, 0x23, 0x08, 0x23, 0x21, 0x93, 0x5B, 0x08, 0x1F, 0x93, + 0xC3, 0xEB, 0x43, 0x73, 0x27, 0x93, 0x1F, 0x9B, 0x4F, 0xF0, 0x03, 0x09, 0x4F, 0xF0, 0x00, 0x08, + 0xAB, 0x42, 0x93, 0xBF, 0x27, 0x9B, 0x4F, 0xEA, 0xC5, 0x0A, 0xDD, 0xF8, 0x8C, 0xB0, 0xDD, 0xF8, + 0x90, 0xB0, 0x98, 0xBF, 0x03, 0xEB, 0x05, 0x0A, 0x4F, 0xF0, 0xFF, 0x03, 0x98, 0xBF, 0x4F, 0xEA, + 0xCA, 0x0A, 0x5C, 0x46, 0x03, 0xFA, 0x0A, 0xF3, 0xDB, 0x43, 0x20, 0x93, 0x30, 0x46, 0xFF, 0xF7, + 0x91, 0xFE, 0x33, 0x46, 0x01, 0x22, 0x29, 0x46, 0x4F, 0xF4, 0x80, 0x60, 0xFF, 0xF7, 0x1E, 0xFA, + 0x01, 0x28, 0x4F, 0xD0, 0x24, 0xFA, 0x0A, 0xF3, 0x03, 0xF0, 0x3F, 0x03, 0xB8, 0xF1, 0x00, 0x0F, + 0x40, 0xD1, 0x00, 0x2B, 0x2C, 0xAA, 0x04, 0xBF, 0x5C, 0x46, 0x4F, 0xF0, 0x01, 0x08, 0x42, 0xF8, + 0x25, 0x30, 0x4C, 0xAB, 0x24, 0xFA, 0x0A, 0xF7, 0x03, 0xEB, 0x89, 0x03, 0xB8, 0xF1, 0x01, 0x0F, + 0xFF, 0xB2, 0x53, 0xF8, 0x90, 0x3C, 0x5D, 0xD1, 0x1F, 0x44, 0x3F, 0x2F, 0x28, 0xBF, 0x3F, 0x27, + 0x20, 0x9B, 0x1C, 0x40, 0x07, 0xFA, 0x0A, 0xF3, 0x1C, 0x43, 0x1F, 0x9B, 0xAB, 0x42, 0x8C, 0xBF, + 0x34, 0x67, 0x74, 0x67, 0xB8, 0xF1, 0x02, 0x0F, 0xC8, 0xD1, 0x26, 0x9B, 0x2C, 0xAA, 0x52, 0xF8, + 0x25, 0x10, 0x3C, 0xA8, 0x53, 0xF8, 0x25, 0x30, 0x5A, 0x1A, 0x0B, 0x44, 0x5B, 0x08, 0x44, 0xA9, + 0x40, 0xF8, 0x25, 0x20, 0x41, 0xF8, 0x25, 0x30, 0x25, 0x9B, 0x9A, 0x42, 0x3F, 0xD2, 0x14, 0x22, + 0x5C, 0x48, 0x5A, 0x43, 0x29, 0x46, 0x01, 0x24, 0xFE, 0xF7, 0x3E, 0xFD, 0x20, 0x46, 0x4D, 0xB0, + 0xBD, 0xE8, 0xF0, 0x8F, 0x26, 0x9A, 0x3F, 0x2B, 0x08, 0xBF, 0x4F, 0xF0, 0x02, 0x08, 0x42, 0xF8, + 0x25, 0x30, 0xBE, 0xE7, 0xB8, 0xF1, 0x00, 0x0F, 0x10, 0xD1, 0xB9, 0xF1, 0x00, 0x0F, 0x19, 0xD0, + 0x20, 0x9B, 0x1C, 0x40, 0x4C, 0xAB, 0x03, 0xEB, 0x89, 0x03, 0x53, 0xF8, 0x90, 0x3C, 0x1F, 0x44, + 0x07, 0xFA, 0x0A, 0xF7, 0x09, 0xF1, 0xFF, 0x39, 0x3C, 0x43, 0xAA, 0xE7, 0xB9, 0xF1, 0x00, 0x0F, + 0x0D, 0xD0, 0x20, 0x9B, 0x1C, 0x40, 0x4C, 0xAB, 0x03, 0xEB, 0x89, 0x03, 0x53, 0xF8, 0x90, 0x3C, + 0xFF, 0x1A, 0xED, 0xE7, 0x5C, 0x46, 0x80, 0x46, 0x4F, 0xF0, 0x03, 0x09, 0x99, 0xE7, 0x4F, 0xF0, + 0x02, 0x08, 0x96, 0xE7, 0x9F, 0x42, 0x8C, 0xBF, 0xFF, 0x1A, 0x00, 0x27, 0xA0, 0xE7, 0x22, 0x9B, + 0x9A, 0x42, 0x04, 0xD9, 0x14, 0x22, 0x29, 0x46, 0x5A, 0x43, 0x3B, 0x48, 0xBB, 0xE7, 0x23, 0x9B, + 0x01, 0x35, 0x33, 0x67, 0x24, 0x9B, 0x73, 0x67, 0x21, 0x9B, 0xAB, 0x42, 0x7F, 0xF4, 0x4B, 0xAF, + 0x3C, 0x9B, 0xF4, 0x69, 0xDD, 0xE9, 0x44, 0x5E, 0x1F, 0x93, 0x3D, 0x9B, 0x14, 0xF0, 0x01, 0x04, + 0xDD, 0xE9, 0x46, 0x7C, 0x4F, 0xEA, 0x0E, 0x20, 0x2C, 0x99, 0x24, 0x93, 0x2E, 0x9B, 0x34, 0x9A, + 0xDD, 0xF8, 0xB4, 0xA0, 0x20, 0x93, 0x36, 0x9B, 0xDD, 0xF8, 0xD4, 0xB0, 0xDD, 0xF8, 0xDC, 0x80, + 0x22, 0x93, 0x3E, 0x9B, 0xDD, 0xF8, 0xFC, 0x90, 0x23, 0x93, 0x2F, 0x9B, 0x21, 0x93, 0x4F, 0xD1, + 0x40, 0xEA, 0x07, 0x40, 0x4A, 0x9B, 0x28, 0x43, 0x40, 0xEA, 0x0C, 0x60, 0x30, 0x67, 0x18, 0x04, + 0x49, 0x9B, 0x40, 0xEA, 0x03, 0x20, 0x48, 0x9B, 0x18, 0x43, 0x4B, 0x9B, 0x1C, 0x93, 0x40, 0xEA, + 0x03, 0x60, 0x4A, 0x9B, 0x70, 0x67, 0x43, 0x98, 0x18, 0x93, 0x49, 0x9B, 0x1B, 0x90, 0x3B, 0x98, + 0x14, 0x93, 0x48, 0x9B, 0x1A, 0x90, 0x33, 0x98, 0x10, 0x93, 0x19, 0x90, 0x42, 0x98, 0x17, 0x90, + 0x3A, 0x98, 0x16, 0x90, 0x32, 0x98, 0x15, 0x90, 0x41, 0x98, 0x13, 0x90, 0x39, 0x98, 0x12, 0x90, + 0x31, 0x98, 0x11, 0x90, 0x40, 0x98, 0x0F, 0x90, 0x21, 0x9B, 0x38, 0x98, 0xCD, 0xE9, 0x00, 0x5A, + 0xCD, 0xE9, 0x08, 0x73, 0x23, 0x9B, 0x0E, 0x90, 0x30, 0x98, 0x07, 0x93, 0x22, 0x9B, 0xCD, 0xE9, + 0x0C, 0xC0, 0x0A, 0x48, 0x06, 0x93, 0x20, 0x9B, 0xCD, 0xE9, 0x0A, 0x89, 0xCD, 0xE9, 0x04, 0xE3, + 0x24, 0x9B, 0xCD, 0xE9, 0x02, 0xB3, 0x1F, 0x9B, 0xFE, 0xF7, 0x8E, 0xFC, 0x4E, 0xE7, 0x00, 0xBF, + 0x74, 0x30, 0x04, 0x00, 0x4B, 0x35, 0x04, 0x00, 0x73, 0x35, 0x04, 0x00, 0x99, 0x35, 0x04, 0x00, + 0x21, 0x9B, 0x28, 0x43, 0x30, 0x67, 0x47, 0xEA, 0x0C, 0x20, 0xCD, 0xF8, 0x28, 0x80, 0x00, 0x24, + 0xCD, 0xE9, 0x08, 0x73, 0x23, 0x9B, 0x70, 0x67, 0xCD, 0xE9, 0x00, 0x5A, 0x07, 0x93, 0x22, 0x9B, + 0x06, 0x48, 0xCD, 0xE9, 0x0B, 0x9C, 0x06, 0x93, 0x20, 0x9B, 0xCD, 0xE9, 0x04, 0xE3, 0x24, 0x9B, + 0xCD, 0xE9, 0x02, 0xB3, 0x1F, 0x9B, 0xFE, 0xF7, 0x67, 0xFC, 0x27, 0xE7, 0x2B, 0x36, 0x04, 0x00, + 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF5, 0x59, 0x7D, 0x83, 0x46, 0x6C, 0x22, 0x68, 0x46, 0x0D, 0xF1, + 0x6C, 0x0A, 0x55, 0x49, 0x36, 0xAE, 0xFE, 0xF7, 0x83, 0xFC, 0x6C, 0x22, 0x53, 0x49, 0x50, 0x46, + 0x0D, 0xF5, 0xA2, 0x79, 0xFE, 0xF7, 0x7C, 0xFC, 0x6C, 0x22, 0x51, 0x49, 0x30, 0x46, 0x6C, 0xAD, + 0xFE, 0xF7, 0x76, 0xFC, 0x6C, 0x22, 0x4F, 0x49, 0x48, 0x46, 0x0D, 0xF5, 0x07, 0x78, 0xFE, 0xF7, + 0x6F, 0xFC, 0x6C, 0x22, 0x4C, 0x49, 0x28, 0x46, 0xA2, 0xAC, 0xFE, 0xF7, 0x69, 0xFC, 0x6C, 0x22, + 0x4A, 0x49, 0x40, 0x46, 0xBD, 0xAF, 0xFE, 0xF7, 0x63, 0xFC, 0x6C, 0x22, 0x48, 0x49, 0x20, 0x46, + 0xFE, 0xF7, 0x5E, 0xFC, 0x6C, 0x22, 0x47, 0x49, 0x38, 0x46, 0xFE, 0xF7, 0x59, 0xFC, 0x46, 0x4B, + 0x1A, 0x68, 0xDB, 0xF8, 0x04, 0x30, 0x92, 0xB2, 0x03, 0x3B, 0xB2, 0xF5, 0x00, 0x6F, 0x02, 0xD0, + 0xB2, 0xF5, 0x10, 0x5F, 0x34, 0xD1, 0x05, 0x2B, 0x0E, 0xD8, 0xDF, 0xE8, 0x03, 0xF0, 0x03, 0x11, + 0x0D, 0x0D, 0x1C, 0x27, 0x3D, 0x4B, 0x3E, 0x48, 0x3E, 0x4A, 0x19, 0x18, 0x5A, 0xF8, 0x01, 0x10, + 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF8, 0xD1, 0x0D, 0xF5, 0x59, 0x7D, 0xBD, 0xE8, 0xF0, 0x8F, + 0x36, 0x4B, 0x37, 0x48, 0x37, 0x4A, 0x19, 0x18, 0x59, 0xF8, 0x01, 0x10, 0x43, 0xF8, 0x04, 0x1B, + 0x93, 0x42, 0xF8, 0xD1, 0xF0, 0xE7, 0x31, 0x4B, 0x31, 0x48, 0x32, 0x4A, 0x19, 0x18, 0x58, 0xF8, + 0x01, 0x10, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF8, 0xD1, 0xE5, 0xE7, 0x2B, 0x4B, 0x2C, 0x48, + 0x2C, 0x4A, 0x19, 0x18, 0x79, 0x58, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF9, 0xD1, 0xDB, 0xE7, + 0x05, 0x2B, 0xD9, 0xD8, 0x01, 0xA2, 0x52, 0xF8, 0x23, 0xF0, 0x00, 0xBF, 0xA5, 0x06, 0x04, 0x00, + 0xBB, 0x06, 0x04, 0x00, 0x39, 0x06, 0x04, 0x00, 0x39, 0x06, 0x04, 0x00, 0xCF, 0x06, 0x04, 0x00, + 0xE3, 0x06, 0x04, 0x00, 0x1D, 0x4B, 0x1E, 0x48, 0x1E, 0x4A, 0x19, 0x18, 0x5D, 0xF8, 0x01, 0x10, + 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF8, 0xD1, 0xBE, 0xE7, 0x18, 0x4B, 0x18, 0x48, 0x19, 0x4A, + 0x19, 0x18, 0x71, 0x58, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF9, 0xD1, 0xB4, 0xE7, 0x13, 0x4B, + 0x13, 0x48, 0x14, 0x4A, 0x19, 0x18, 0x69, 0x58, 0x43, 0xF8, 0x04, 0x1B, 0x93, 0x42, 0xF9, 0xD1, + 0xAA, 0xE7, 0x0E, 0x4B, 0x0E, 0x48, 0x0F, 0x4A, 0x19, 0x18, 0x61, 0x58, 0x43, 0xF8, 0x04, 0x1B, + 0x93, 0x42, 0xF9, 0xD1, 0xA0, 0xE7, 0x00, 0xBF, 0xA4, 0x30, 0x04, 0x00, 0x10, 0x31, 0x04, 0x00, + 0x7C, 0x31, 0x04, 0x00, 0xE8, 0x31, 0x04, 0x00, 0x54, 0x32, 0x04, 0x00, 0xC0, 0x32, 0x04, 0x00, + 0x2C, 0x33, 0x04, 0x00, 0x98, 0x33, 0x04, 0x00, 0x00, 0x62, 0x00, 0x03, 0xC0, 0x00, 0x83, 0x04, + 0x40, 0xFF, 0x7C, 0xFB, 0x2C, 0x01, 0x83, 0x04, 0x10, 0xB5, 0x01, 0x20, 0x06, 0x4C, 0x23, 0x68, + 0x23, 0xF0, 0x80, 0x73, 0x43, 0xF4, 0x00, 0x73, 0x23, 0x60, 0xFE, 0xF7, 0xC1, 0xFB, 0x23, 0x68, + 0x43, 0xF0, 0x80, 0x73, 0x23, 0x60, 0x10, 0xBD, 0x08, 0x00, 0x81, 0x04, 0xF8, 0xB5, 0x04, 0x46, + 0x53, 0x4E, 0x45, 0x68, 0x33, 0x68, 0x53, 0x4F, 0x08, 0x2D, 0x53, 0x4A, 0x23, 0xF0, 0x10, 0x03, + 0x33, 0x60, 0x02, 0xBF, 0x3B, 0x68, 0x23, 0xF0, 0x80, 0x03, 0x3B, 0x60, 0x13, 0x68, 0xC1, 0x69, + 0x23, 0xF0, 0x0F, 0x03, 0xC8, 0x07, 0x4C, 0xBF, 0x43, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x0F, 0x03, + 0x07, 0x2D, 0x13, 0x60, 0x71, 0xD0, 0x08, 0x2D, 0x72, 0xD0, 0x04, 0x2D, 0x4F, 0xF0, 0x0D, 0x02, + 0x0C, 0xBF, 0x0A, 0x23, 0x09, 0x23, 0x45, 0x49, 0x20, 0x46, 0x0A, 0x60, 0x04, 0x31, 0xC1, 0xF8, + 0x44, 0x23, 0xC1, 0xF8, 0x50, 0x23, 0xC1, 0xF8, 0x5C, 0x23, 0x00, 0x22, 0x0A, 0x60, 0xC1, 0xF8, + 0x48, 0x23, 0xC1, 0xF8, 0x54, 0x23, 0xC1, 0xF8, 0x60, 0x23, 0x3D, 0x4A, 0x13, 0x60, 0xC2, 0xF8, + 0x48, 0x33, 0xC2, 0xF8, 0x54, 0x33, 0xC2, 0xF8, 0x60, 0x33, 0xFF, 0xF7, 0xE1, 0xFE, 0x20, 0x46, + 0xFF, 0xF7, 0x9C, 0xFA, 0xFF, 0xF7, 0xBE, 0xFA, 0xB4, 0xF8, 0x6E, 0x30, 0x0B, 0xB1, 0xFF, 0xF7, + 0x75, 0xFB, 0x3B, 0x68, 0x07, 0x2D, 0x23, 0xF0, 0x07, 0x03, 0x49, 0xD0, 0x08, 0x2D, 0x4A, 0xD0, + 0x04, 0x2D, 0x4B, 0xD1, 0x43, 0xF0, 0x04, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x2D, 0x4D, 0x3B, 0x60, + 0x23, 0x68, 0xB3, 0xF5, 0x28, 0x7F, 0x9E, 0xBF, 0x2B, 0x4B, 0x0F, 0x22, 0x1A, 0x60, 0x23, 0x68, + 0xB3, 0xF5, 0xFA, 0x7F, 0x29, 0x4B, 0x1A, 0x68, 0x3B, 0xD8, 0x42, 0xF0, 0x80, 0x02, 0x1A, 0x60, + 0x2B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0x43, 0xF0, 0x20, 0x03, 0x25, 0x4A, 0x01, 0x20, 0x2B, 0x60, + 0x13, 0x68, 0x23, 0xF4, 0x00, 0x73, 0x13, 0x60, 0xFE, 0xF7, 0x42, 0xFB, 0x2B, 0x68, 0x21, 0x4A, + 0x23, 0xF0, 0x08, 0x03, 0x2B, 0x60, 0x13, 0x68, 0x59, 0x07, 0xFC, 0xD5, 0xA3, 0x6F, 0xDB, 0x06, + 0x03, 0xD4, 0x4F, 0xF4, 0x7A, 0x70, 0xFE, 0xF7, 0x33, 0xFB, 0x1B, 0x4B, 0x37, 0x22, 0x1A, 0x60, + 0x33, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x33, 0x60, 0xF8, 0xBD, 0x08, 0x23, 0x0E, 0x22, 0x92, 0xE7, + 0xA2, 0x6F, 0x0A, 0x23, 0x12, 0xF0, 0x80, 0x5F, 0x14, 0xBF, 0x16, 0x22, 0x14, 0x22, 0x8A, 0xE7, + 0x43, 0xF0, 0x03, 0x03, 0xB8, 0xE7, 0x43, 0xF0, 0x05, 0x03, 0xB5, 0xE7, 0x43, 0xF0, 0x02, 0x03, + 0xB2, 0xE7, 0x22, 0xF0, 0x80, 0x02, 0x1A, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0xE0, 0x03, 0xC4, 0xE7, + 0x50, 0x02, 0x01, 0x07, 0x04, 0x00, 0x83, 0x04, 0x3C, 0x00, 0x83, 0x04, 0x14, 0x00, 0x83, 0x04, + 0x1C, 0x00, 0x83, 0x04, 0x4C, 0x01, 0x83, 0x04, 0x20, 0x00, 0x83, 0x04, 0x44, 0x01, 0x83, 0x04, + 0x08, 0x00, 0x81, 0x04, 0x80, 0x01, 0x83, 0x04, 0x58, 0x00, 0x83, 0x04, 0x3D, 0x4B, 0x41, 0x68, + 0xF0, 0xB5, 0x1A, 0x68, 0x04, 0x29, 0x3C, 0x4C, 0x22, 0xF0, 0xC0, 0x02, 0x42, 0xF0, 0x80, 0x02, + 0x1A, 0x60, 0x3A, 0x4A, 0x4C, 0xD1, 0x90, 0xF8, 0x24, 0x10, 0x21, 0x60, 0x90, 0xF8, 0x25, 0x10, + 0x41, 0xF0, 0x40, 0x01, 0x11, 0x60, 0x1A, 0x68, 0x35, 0x4C, 0x42, 0xF0, 0x04, 0x02, 0x1A, 0x60, + 0xC2, 0x69, 0x12, 0xF0, 0x01, 0x0F, 0x48, 0xD0, 0x22, 0x68, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, + 0xFA, 0xD1, 0x1A, 0x68, 0x00, 0x21, 0x2F, 0x4F, 0x0E, 0x46, 0x22, 0xF0, 0x04, 0x02, 0x1A, 0x60, + 0x0A, 0x46, 0x3A, 0x44, 0x92, 0x00, 0x12, 0x68, 0x00, 0x2A, 0x43, 0xD0, 0x3F, 0x2A, 0x08, 0xBF, + 0x01, 0x21, 0x75, 0x1C, 0x04, 0x2D, 0x36, 0xD1, 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, + 0xC2, 0x69, 0xD5, 0x04, 0x15, 0xD5, 0x1A, 0x68, 0x22, 0xF0, 0xC0, 0x02, 0x42, 0xF0, 0x40, 0x02, + 0x1A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x04, 0x02, 0x1A, 0x60, 0xC2, 0x69, 0xD2, 0x07, 0x2B, 0xD5, + 0x22, 0x68, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0xFA, 0xD1, 0x1A, 0x68, 0x22, 0xF0, 0x04, 0x02, + 0x1A, 0x60, 0x1A, 0x68, 0x81, 0xF0, 0x01, 0x00, 0x22, 0xF0, 0xC0, 0x02, 0x1A, 0x60, 0xF0, 0xBD, + 0x06, 0x39, 0x02, 0x29, 0x91, 0xBF, 0x90, 0xF8, 0x28, 0x10, 0x04, 0x21, 0x21, 0x60, 0x40, 0x21, + 0x9C, 0xBF, 0x21, 0x60, 0x90, 0xF8, 0x29, 0x10, 0xAC, 0xE7, 0x22, 0x68, 0x02, 0xF0, 0x0F, 0x02, + 0x0F, 0x2A, 0xFA, 0xD1, 0xB5, 0xE7, 0x01, 0x2D, 0x14, 0xBF, 0x06, 0xF1, 0x2F, 0x02, 0x2A, 0x46, + 0x2E, 0x46, 0xB6, 0xE7, 0x01, 0x21, 0xBC, 0xE7, 0x22, 0x68, 0x02, 0xF0, 0x0F, 0x02, 0x0F, 0x2A, + 0xFA, 0xD1, 0xD2, 0xE7, 0x08, 0x00, 0x83, 0x04, 0x0C, 0x00, 0x83, 0x04, 0x10, 0x00, 0x83, 0x04, + 0x88, 0x01, 0x83, 0x04, 0x96, 0xC0, 0x20, 0x01, 0x31, 0x4B, 0x10, 0xB5, 0x1A, 0x68, 0x22, 0xF0, + 0x30, 0x02, 0x42, 0xF0, 0x20, 0x02, 0x1A, 0x60, 0x42, 0x68, 0x04, 0x2A, 0x01, 0xBF, 0x2D, 0x49, + 0x0A, 0x68, 0x42, 0xF0, 0x02, 0x02, 0x0A, 0x60, 0x1A, 0x68, 0x2B, 0x49, 0x42, 0xF0, 0x01, 0x02, + 0x1A, 0x60, 0xC2, 0x69, 0x12, 0xF0, 0x01, 0x02, 0x0C, 0xD1, 0x0C, 0x68, 0x04, 0xF0, 0x0F, 0x04, + 0x0F, 0x2C, 0x0D, 0xD0, 0x0C, 0x68, 0xA4, 0x06, 0xF7, 0xD5, 0x01, 0x22, 0x08, 0xE0, 0x0C, 0x68, + 0xA4, 0x06, 0x05, 0xD4, 0x0C, 0x68, 0x04, 0xF0, 0x03, 0x04, 0x03, 0x2C, 0xF7, 0xD1, 0x00, 0x22, + 0x1C, 0x68, 0x24, 0xF0, 0x01, 0x04, 0x1C, 0x60, 0x1C, 0x68, 0x24, 0xF0, 0x30, 0x04, 0x1C, 0x60, + 0xC4, 0x69, 0xE4, 0x04, 0x23, 0xD5, 0x1C, 0x68, 0x24, 0xF0, 0x30, 0x04, 0x44, 0xF0, 0x10, 0x04, + 0x1C, 0x60, 0x1C, 0x68, 0x44, 0xF0, 0x01, 0x04, 0x1C, 0x60, 0xC0, 0x69, 0x10, 0xF0, 0x01, 0x00, + 0x0C, 0xD1, 0x08, 0x68, 0x00, 0xF0, 0x0F, 0x00, 0x0F, 0x28, 0x0C, 0xD0, 0x08, 0x68, 0x80, 0x06, + 0xF7, 0xD5, 0x01, 0x22, 0x07, 0xE0, 0x0C, 0x68, 0xA4, 0x06, 0x0F, 0xD4, 0x0C, 0x68, 0x04, 0xF0, + 0x03, 0x04, 0x03, 0x2C, 0xF7, 0xD1, 0x19, 0x68, 0x21, 0xF0, 0x01, 0x01, 0x19, 0x60, 0x19, 0x68, + 0x82, 0xF0, 0x01, 0x00, 0x21, 0xF0, 0x30, 0x01, 0x19, 0x60, 0x10, 0xBD, 0x02, 0x46, 0xF2, 0xE7, + 0x08, 0x00, 0x83, 0x04, 0x54, 0x00, 0x83, 0x04, 0x84, 0x01, 0x83, 0x04, 0x03, 0x6F, 0x2D, 0xE9, + 0xF7, 0x4F, 0xCA, 0x00, 0x04, 0x6E, 0x05, 0x46, 0x88, 0x46, 0x00, 0x93, 0x43, 0x6F, 0x18, 0x20, + 0xD4, 0x40, 0x6E, 0x4E, 0x01, 0x93, 0x04, 0xF0, 0x1F, 0x04, 0x6D, 0x4B, 0x61, 0x1C, 0x1B, 0x68, + 0x1B, 0x0A, 0x01, 0x33, 0xDB, 0xB2, 0x58, 0x43, 0x02, 0xF0, 0x62, 0xE8, 0x47, 0x00, 0x41, 0x46, + 0x68, 0x48, 0x3A, 0x46, 0xFE, 0xF7, 0xB8, 0xF9, 0x67, 0x4A, 0x33, 0x68, 0x92, 0x46, 0x43, 0xF0, + 0x20, 0x03, 0x33, 0x60, 0x13, 0x68, 0x03, 0xF0, 0x07, 0x03, 0x03, 0x2B, 0xFA, 0xD1, 0x01, 0x20, + 0xDF, 0xF8, 0xB0, 0xB1, 0xFE, 0xF7, 0xDC, 0xF9, 0xDF, 0xF8, 0xAC, 0xC1, 0xB7, 0xF5, 0x28, 0x7F, + 0x5E, 0x4A, 0xDC, 0xF8, 0x00, 0x30, 0x91, 0x46, 0x23, 0xF0, 0x10, 0x03, 0xCC, 0xF8, 0x00, 0x30, + 0x4F, 0xF0, 0x00, 0x03, 0xCB, 0xF8, 0x00, 0x30, 0x13, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x13, 0x60, + 0x4F, 0xF0, 0x01, 0x03, 0xCB, 0xF8, 0x00, 0x30, 0x55, 0x4B, 0x19, 0x68, 0x41, 0xF0, 0x08, 0x01, + 0x19, 0x60, 0x54, 0x49, 0x08, 0x68, 0x20, 0xF0, 0x20, 0x00, 0x08, 0x60, 0x52, 0x48, 0xD0, 0xF8, + 0x00, 0xE0, 0x2E, 0xF0, 0x40, 0x7E, 0xC0, 0xF8, 0x00, 0xE0, 0xD0, 0xF8, 0x00, 0xE0, 0x2E, 0xF0, + 0x1F, 0x0E, 0x44, 0xEA, 0x0E, 0x04, 0x04, 0x60, 0x44, 0xF0, 0x00, 0x64, 0x04, 0x60, 0x64, 0x46, + 0x4A, 0x48, 0x7A, 0xD8, 0x02, 0xF5, 0x7E, 0x42, 0xB7, 0xF5, 0xFA, 0x7F, 0x02, 0xF1, 0x70, 0x02, + 0x4F, 0xF0, 0x0F, 0x0E, 0xC2, 0xF8, 0x00, 0xE0, 0x6F, 0xD8, 0x02, 0x68, 0x42, 0xF0, 0x80, 0x02, + 0x02, 0x60, 0x18, 0x68, 0x20, 0xF0, 0xE0, 0x00, 0x40, 0xF0, 0x20, 0x00, 0x18, 0x60, 0x18, 0x68, + 0x20, 0xF0, 0x08, 0x00, 0x18, 0x60, 0x3E, 0x48, 0x03, 0x68, 0x5B, 0x07, 0xFC, 0xD5, 0x32, 0x20, + 0xFE, 0xF7, 0x86, 0xF9, 0x37, 0x49, 0x3B, 0x4A, 0x0B, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x0B, 0x60, + 0x00, 0x23, 0xCB, 0xF8, 0x00, 0x30, 0xD9, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x20, 0x03, 0xC9, 0xF8, + 0x00, 0x30, 0x01, 0x23, 0xCB, 0xF8, 0x00, 0x30, 0x13, 0x68, 0x01, 0x2B, 0xFC, 0xD1, 0x32, 0x4A, + 0x13, 0x68, 0xD9, 0x07, 0xFC, 0xD5, 0x23, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x23, 0x60, 0x33, 0x68, + 0x23, 0xF0, 0x20, 0x03, 0x33, 0x60, 0xDA, 0xF8, 0x00, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, + 0xF9, 0xD0, 0x2A, 0x4A, 0x28, 0x46, 0x13, 0x68, 0x23, 0xF0, 0x0C, 0x03, 0x43, 0xEA, 0x88, 0x03, + 0x13, 0x60, 0xFF, 0xF7, 0xE1, 0xFE, 0x04, 0x46, 0x20, 0xB9, 0x3A, 0x46, 0x41, 0x46, 0x24, 0x48, + 0xFE, 0xF7, 0x1A, 0xF9, 0xEB, 0x6C, 0xDA, 0x03, 0x14, 0xD5, 0xB7, 0xF5, 0xB4, 0x7F, 0x11, 0xD8, + 0xC3, 0xF3, 0x05, 0x21, 0x03, 0xF0, 0x3F, 0x03, 0x0A, 0x04, 0x42, 0xEA, 0x01, 0x62, 0x0A, 0x43, + 0x42, 0xEA, 0x01, 0x22, 0x2A, 0x67, 0x1A, 0x04, 0x42, 0xEA, 0x03, 0x62, 0x1A, 0x43, 0x42, 0xEA, + 0x03, 0x23, 0x6B, 0x67, 0x28, 0x46, 0xFF, 0xF7, 0x05, 0xFA, 0x00, 0x9B, 0x20, 0x46, 0x2B, 0x67, + 0x01, 0x9B, 0x6B, 0x67, 0x03, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x02, 0x68, 0x22, 0xF0, 0x80, 0x02, + 0x02, 0x60, 0x18, 0x68, 0x20, 0xF0, 0xE0, 0x00, 0x90, 0xE7, 0x00, 0xBF, 0x30, 0x00, 0x82, 0x04, + 0x10, 0x10, 0x00, 0x03, 0x7E, 0x36, 0x04, 0x00, 0x04, 0x00, 0x82, 0x04, 0xB0, 0x01, 0x82, 0x04, + 0x4C, 0x01, 0x83, 0x04, 0x58, 0x00, 0x83, 0x04, 0x00, 0x18, 0x00, 0x03, 0x44, 0x01, 0x83, 0x04, + 0x80, 0x01, 0x83, 0x04, 0x24, 0x03, 0x82, 0x04, 0xBC, 0x01, 0x82, 0x04, 0x54, 0x00, 0x83, 0x04, + 0x93, 0x36, 0x04, 0x00, 0x20, 0x03, 0x82, 0x04, 0x50, 0x02, 0x01, 0x07, 0x2D, 0xE9, 0xF8, 0x4F, + 0x07, 0x46, 0x43, 0x68, 0xA4, 0x49, 0x08, 0x2B, 0xA4, 0x4D, 0x04, 0xBF, 0xA4, 0x4A, 0x00, 0x23, + 0x88, 0x46, 0x04, 0xBF, 0x13, 0x60, 0xD3, 0x61, 0x0A, 0x68, 0x43, 0x8B, 0xA1, 0x48, 0x22, 0xF0, + 0x03, 0x02, 0x42, 0xF0, 0x02, 0x02, 0x0A, 0x60, 0x5B, 0x00, 0x02, 0x68, 0x13, 0xF0, 0x1E, 0x03, + 0x08, 0xBF, 0x0F, 0x23, 0x22, 0xF0, 0x3F, 0x02, 0x1A, 0x43, 0x02, 0x60, 0x42, 0x68, 0x22, 0xF0, + 0x3F, 0x02, 0x1A, 0x43, 0x42, 0x60, 0xD0, 0xF8, 0x00, 0x22, 0x22, 0xF0, 0x3F, 0x02, 0x1A, 0x43, + 0xC0, 0xF8, 0x00, 0x22, 0xD0, 0xF8, 0x04, 0x22, 0x22, 0xF0, 0x3F, 0x02, 0x13, 0x43, 0xC0, 0xF8, + 0x04, 0x32, 0x2B, 0x68, 0x43, 0xF0, 0x06, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x01, 0x03, + 0x2B, 0x60, 0x8D, 0x4B, 0x99, 0x46, 0x1A, 0x68, 0x02, 0xF0, 0x0C, 0x02, 0x0C, 0x2A, 0xFA, 0xD1, + 0x1C, 0x68, 0x14, 0xF0, 0x03, 0x04, 0x03, 0xD0, 0x01, 0x24, 0x88, 0x48, 0xFE, 0xF7, 0x84, 0xF8, + 0xFB, 0x69, 0xDA, 0x07, 0x0C, 0xD4, 0x86, 0x4A, 0x13, 0x68, 0x03, 0xF0, 0x0C, 0x03, 0x0C, 0x2B, + 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0x03, 0xD0, 0x01, 0x24, 0x82, 0x48, 0xFE, 0xF7, 0x74, 0xF8, + 0x81, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0x81, 0x4E, 0xDF, 0xF8, 0xA4, 0xB2, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, - 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, - 0x52, 0x1A, 0x06, 0x2A, 0x09, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFE, 0xF7, 0x8E, 0xFB, 0xFA, 0x6E, - 0x79, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, - 0x5E, 0x45, 0xE9, 0xD1, 0x75, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, 0x50, 0xB2, 0x1B, 0x68, - 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, + 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, 0x1B, 0x68, 0x80, 0x4B, + 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x09, 0xD8, 0x18, 0x46, + 0x51, 0x46, 0xFE, 0xF7, 0x51, 0xF8, 0xFA, 0x6E, 0x79, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, + 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE9, 0xD1, 0x75, 0x4B, 0x4F, 0xF0, + 0xFF, 0x3A, 0xDF, 0xF8, 0x50, 0xB2, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, - 0x73, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x09, 0xD8, - 0x18, 0x46, 0x51, 0x46, 0xFE, 0xF7, 0x61, 0xFB, 0xFA, 0x6E, 0x6D, 0x4B, 0x12, 0xF0, 0x80, 0x5F, - 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE9, 0xD1, 0xFB, 0x69, - 0xDE, 0x07, 0x5A, 0xD4, 0x67, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0x67, 0x4E, 0xDF, 0xF8, 0xF0, 0xB1, - 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, + 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x1B, 0x68, 0x73, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, + 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x09, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFE, 0xF7, 0x24, 0xF8, + 0xFA, 0x6E, 0x6D, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, + 0x01, 0x0A, 0x5E, 0x45, 0xE9, 0xD1, 0xFB, 0x69, 0xDE, 0x07, 0x5A, 0xD4, 0x67, 0x4B, 0x4F, 0xF0, + 0xFF, 0x3A, 0x67, 0x4E, 0xDF, 0xF8, 0xF0, 0xB1, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, - 0x1B, 0x68, 0x66, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, - 0x09, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFE, 0xF7, 0x30, 0xFB, 0xFA, 0x6E, 0x5F, 0x4B, 0x12, 0xF0, - 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE9, 0xD1, - 0x5B, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, 0x9C, 0xB1, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, + 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x1B, 0x68, 0x66, 0x4B, 0x32, 0x68, 0x56, 0xF8, + 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x09, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFD, 0xF7, + 0xF3, 0xFF, 0xFA, 0x6E, 0x5F, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, + 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE9, 0xD1, 0x5B, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, + 0x9C, 0xB1, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, - 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x32, 0x68, - 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x09, 0xD8, 0x18, 0x46, 0x51, 0x46, - 0xFE, 0xF7, 0x03, 0xFB, 0xFA, 0x6E, 0x53, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, - 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE9, 0xD1, 0x2B, 0x68, 0x23, 0xF0, 0x03, 0x03, - 0x2B, 0x60, 0xFB, 0x69, 0xD8, 0x04, 0x40, 0xF1, 0x9F, 0x80, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, - 0x03, 0x03, 0x43, 0xF0, 0x02, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0x2B, 0x68, 0x43, 0xF0, 0x06, 0x03, - 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x2B, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x03, 0xF0, - 0x0C, 0x03, 0x0C, 0x2B, 0xF9, 0xD1, 0xD9, 0xF8, 0x00, 0x30, 0x99, 0x07, 0x03, 0xD0, 0x01, 0x24, - 0x10, 0x48, 0xFE, 0xF7, 0xD2, 0xFA, 0xFB, 0x69, 0xDA, 0x07, 0x0C, 0xD4, 0x0E, 0x4A, 0x13, 0x68, - 0x03, 0xF0, 0x0C, 0x03, 0x0C, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x9B, 0x07, 0x03, 0xD0, 0x01, 0x24, - 0x0A, 0x48, 0xFE, 0xF7, 0xC2, 0xFA, 0x2B, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x2B, 0x60, 0x6B, 0xE0, - 0x98, 0x01, 0x83, 0x04, 0x90, 0x01, 0x83, 0x04, 0x00, 0x08, 0x83, 0x04, 0x04, 0x08, 0x83, 0x04, - 0x40, 0x08, 0x83, 0x04, 0xAC, 0x2F, 0x04, 0x00, 0x40, 0x0A, 0x83, 0x04, 0xD0, 0x2F, 0x04, 0x00, - 0x50, 0x08, 0x83, 0x04, 0x98, 0x08, 0x83, 0x04, 0x54, 0x08, 0x83, 0x04, 0x58, 0x08, 0x83, 0x04, - 0x5C, 0x08, 0x83, 0x04, 0x60, 0x08, 0x83, 0x04, 0x64, 0x08, 0x83, 0x04, 0x68, 0x08, 0x83, 0x04, - 0x6C, 0x08, 0x83, 0x04, 0x70, 0x08, 0x83, 0x04, 0xF5, 0x2F, 0x04, 0x00, 0x74, 0x08, 0x83, 0x04, - 0x78, 0x08, 0x83, 0x04, 0x7C, 0x08, 0x83, 0x04, 0x80, 0x08, 0x83, 0x04, 0x84, 0x08, 0x83, 0x04, - 0x88, 0x08, 0x83, 0x04, 0x8C, 0x08, 0x83, 0x04, 0x90, 0x08, 0x83, 0x04, 0x94, 0x08, 0x83, 0x04, - 0x1D, 0x30, 0x04, 0x00, 0x50, 0x0A, 0x83, 0x04, 0x98, 0x0A, 0x83, 0x04, 0x54, 0x0A, 0x83, 0x04, - 0x58, 0x0A, 0x83, 0x04, 0x5C, 0x0A, 0x83, 0x04, 0x60, 0x0A, 0x83, 0x04, 0x64, 0x0A, 0x83, 0x04, - 0x68, 0x0A, 0x83, 0x04, 0x6C, 0x0A, 0x83, 0x04, 0x70, 0x0A, 0x83, 0x04, 0x45, 0x30, 0x04, 0x00, - 0x74, 0x0A, 0x83, 0x04, 0x78, 0x0A, 0x83, 0x04, 0x7C, 0x0A, 0x83, 0x04, 0x80, 0x0A, 0x83, 0x04, - 0x84, 0x0A, 0x83, 0x04, 0x88, 0x0A, 0x83, 0x04, 0x8C, 0x0A, 0x83, 0x04, 0x90, 0x0A, 0x83, 0x04, - 0x94, 0x0A, 0x83, 0x04, 0x6D, 0x30, 0x04, 0x00, 0xBC, 0x08, 0x83, 0x04, 0xE0, 0x08, 0x83, 0x04, - 0xBC, 0x0A, 0x83, 0x04, 0xE0, 0x0A, 0x83, 0x04, 0xD8, 0xF8, 0x00, 0x30, 0x84, 0xF0, 0x01, 0x00, - 0x23, 0xF0, 0x03, 0x03, 0xC8, 0xF8, 0x00, 0x30, 0xBD, 0xE8, 0xF8, 0x8F, 0x9D, 0x4A, 0x2D, 0xE9, - 0xF8, 0x4F, 0x00, 0x23, 0x9C, 0x4F, 0x80, 0x46, 0x13, 0x60, 0x53, 0x60, 0x93, 0x66, 0xD3, 0x66, - 0x3B, 0x68, 0x9A, 0x4D, 0x23, 0xF0, 0x0C, 0x03, 0x43, 0xF0, 0x08, 0x03, 0x3B, 0x60, 0x2B, 0x68, - 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x2B, 0x60, 0x94, 0x4B, - 0x99, 0x46, 0x1A, 0x68, 0x02, 0xF0, 0x03, 0x02, 0x03, 0x2A, 0xFA, 0xD1, 0x1C, 0x68, 0x14, 0xF0, - 0x0C, 0x04, 0x03, 0xD0, 0x01, 0x24, 0x8F, 0x48, 0xFE, 0xF7, 0x1F, 0xFA, 0xD8, 0xF8, 0x1C, 0x30, - 0xD8, 0x07, 0x0D, 0xD4, 0x8C, 0x4A, 0x13, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0xFA, 0xD1, - 0x13, 0x68, 0x13, 0xF0, 0x0C, 0x0F, 0x03, 0xD0, 0x01, 0x24, 0x88, 0x48, 0xFE, 0xF7, 0x0D, 0xFA, - 0x87, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0x87, 0x4E, 0xDF, 0xF8, 0xBC, 0xB2, 0x1B, 0x68, 0x86, 0x4B, + 0x59, 0x4B, 0x1B, 0x68, 0x59, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, + 0x06, 0x2A, 0x09, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFD, 0xF7, 0xC6, 0xFF, 0xFA, 0x6E, 0x53, 0x4B, + 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, + 0xE9, 0xD1, 0x2B, 0x68, 0x23, 0xF0, 0x03, 0x03, 0x2B, 0x60, 0xFB, 0x69, 0xD8, 0x04, 0x40, 0xF1, + 0x9F, 0x80, 0xD8, 0xF8, 0x00, 0x30, 0x23, 0xF0, 0x03, 0x03, 0x43, 0xF0, 0x02, 0x03, 0xC8, 0xF8, + 0x00, 0x30, 0x2B, 0x68, 0x43, 0xF0, 0x06, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x01, 0x03, + 0x2B, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x03, 0xF0, 0x0C, 0x03, 0x0C, 0x2B, 0xF9, 0xD1, 0xD9, 0xF8, + 0x00, 0x30, 0x99, 0x07, 0x03, 0xD0, 0x01, 0x24, 0x10, 0x48, 0xFD, 0xF7, 0x95, 0xFF, 0xFB, 0x69, + 0xDA, 0x07, 0x0C, 0xD4, 0x0E, 0x4A, 0x13, 0x68, 0x03, 0xF0, 0x0C, 0x03, 0x0C, 0x2B, 0xFA, 0xD1, + 0x13, 0x68, 0x9B, 0x07, 0x03, 0xD0, 0x01, 0x24, 0x0A, 0x48, 0xFD, 0xF7, 0x85, 0xFF, 0x2B, 0x68, + 0x23, 0xF0, 0x03, 0x03, 0x2B, 0x60, 0x6B, 0xE0, 0x98, 0x01, 0x83, 0x04, 0x90, 0x01, 0x83, 0x04, + 0x00, 0x08, 0x83, 0x04, 0x04, 0x08, 0x83, 0x04, 0x40, 0x08, 0x83, 0x04, 0xC0, 0x36, 0x04, 0x00, + 0x40, 0x0A, 0x83, 0x04, 0xE4, 0x36, 0x04, 0x00, 0x50, 0x08, 0x83, 0x04, 0x98, 0x08, 0x83, 0x04, + 0x54, 0x08, 0x83, 0x04, 0x58, 0x08, 0x83, 0x04, 0x5C, 0x08, 0x83, 0x04, 0x60, 0x08, 0x83, 0x04, + 0x64, 0x08, 0x83, 0x04, 0x68, 0x08, 0x83, 0x04, 0x6C, 0x08, 0x83, 0x04, 0x70, 0x08, 0x83, 0x04, + 0x09, 0x37, 0x04, 0x00, 0x74, 0x08, 0x83, 0x04, 0x78, 0x08, 0x83, 0x04, 0x7C, 0x08, 0x83, 0x04, + 0x80, 0x08, 0x83, 0x04, 0x84, 0x08, 0x83, 0x04, 0x88, 0x08, 0x83, 0x04, 0x8C, 0x08, 0x83, 0x04, + 0x90, 0x08, 0x83, 0x04, 0x94, 0x08, 0x83, 0x04, 0x31, 0x37, 0x04, 0x00, 0x50, 0x0A, 0x83, 0x04, + 0x98, 0x0A, 0x83, 0x04, 0x54, 0x0A, 0x83, 0x04, 0x58, 0x0A, 0x83, 0x04, 0x5C, 0x0A, 0x83, 0x04, + 0x60, 0x0A, 0x83, 0x04, 0x64, 0x0A, 0x83, 0x04, 0x68, 0x0A, 0x83, 0x04, 0x6C, 0x0A, 0x83, 0x04, + 0x70, 0x0A, 0x83, 0x04, 0x59, 0x37, 0x04, 0x00, 0x74, 0x0A, 0x83, 0x04, 0x78, 0x0A, 0x83, 0x04, + 0x7C, 0x0A, 0x83, 0x04, 0x80, 0x0A, 0x83, 0x04, 0x84, 0x0A, 0x83, 0x04, 0x88, 0x0A, 0x83, 0x04, + 0x8C, 0x0A, 0x83, 0x04, 0x90, 0x0A, 0x83, 0x04, 0x94, 0x0A, 0x83, 0x04, 0x81, 0x37, 0x04, 0x00, + 0xBC, 0x08, 0x83, 0x04, 0xE0, 0x08, 0x83, 0x04, 0xBC, 0x0A, 0x83, 0x04, 0xE0, 0x0A, 0x83, 0x04, + 0xD8, 0xF8, 0x00, 0x30, 0x84, 0xF0, 0x01, 0x00, 0x23, 0xF0, 0x03, 0x03, 0xC8, 0xF8, 0x00, 0x30, + 0xBD, 0xE8, 0xF8, 0x8F, 0x9D, 0x4A, 0x2D, 0xE9, 0xF8, 0x4F, 0x00, 0x23, 0x9C, 0x4F, 0x80, 0x46, + 0x13, 0x60, 0x53, 0x60, 0x93, 0x66, 0xD3, 0x66, 0x3B, 0x68, 0x9A, 0x4D, 0x23, 0xF0, 0x0C, 0x03, + 0x43, 0xF0, 0x08, 0x03, 0x3B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, + 0x43, 0xF0, 0x20, 0x03, 0x2B, 0x60, 0x94, 0x4B, 0x99, 0x46, 0x1A, 0x68, 0x02, 0xF0, 0x03, 0x02, + 0x03, 0x2A, 0xFA, 0xD1, 0x1C, 0x68, 0x14, 0xF0, 0x0C, 0x04, 0x03, 0xD0, 0x01, 0x24, 0x8F, 0x48, + 0xFD, 0xF7, 0xE2, 0xFE, 0xD8, 0xF8, 0x1C, 0x30, 0xD8, 0x07, 0x0D, 0xD4, 0x8C, 0x4A, 0x13, 0x68, + 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x13, 0xF0, 0x0C, 0x0F, 0x03, 0xD0, + 0x01, 0x24, 0x88, 0x48, 0xFD, 0xF7, 0xD0, 0xFE, 0x87, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0x87, 0x4E, + 0xDF, 0xF8, 0xBC, 0xB2, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, - 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, - 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x0A, 0xD8, 0x18, 0x46, - 0x51, 0x46, 0xFE, 0xF7, 0xEA, 0xF9, 0xD8, 0xF8, 0x6C, 0x20, 0x7F, 0x4B, 0x12, 0xF0, 0x80, 0x5F, - 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE8, 0xD1, 0x7B, 0x4B, - 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, 0x64, 0xB2, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, + 0x1B, 0x68, 0x86, 0x4B, 0x1B, 0x68, 0x86, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, + 0x52, 0x1A, 0x06, 0x2A, 0x0A, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFD, 0xF7, 0xAD, 0xFE, 0xD8, 0xF8, + 0x6C, 0x20, 0x7F, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, + 0x01, 0x0A, 0x5E, 0x45, 0xE8, 0xD1, 0x7B, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, 0x64, 0xB2, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, - 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, 0x32, 0x68, 0x56, 0xF8, - 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x0A, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFE, 0xF7, - 0xBC, 0xF9, 0xD8, 0xF8, 0x6C, 0x20, 0x72, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, - 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE8, 0xD1, 0xD8, 0xF8, 0x1C, 0x30, 0xD9, 0x07, - 0x5C, 0xD4, 0x6C, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0x6B, 0x4E, 0xDF, 0xF8, 0x04, 0xB2, 0x1B, 0x68, - 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, + 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, 0x1B, 0x68, 0x79, 0x4B, + 0x1B, 0x68, 0x79, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, + 0x0A, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFD, 0xF7, 0x7F, 0xFE, 0xD8, 0xF8, 0x6C, 0x20, 0x72, 0x4B, + 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, + 0xE8, 0xD1, 0xD8, 0xF8, 0x1C, 0x30, 0xD9, 0x07, 0x5C, 0xD4, 0x6C, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, + 0x6B, 0x4E, 0xDF, 0xF8, 0x04, 0xB2, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, - 0x6A, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x0A, 0xD8, - 0x18, 0x46, 0x51, 0x46, 0xFE, 0xF7, 0x89, 0xF9, 0xD8, 0xF8, 0x6C, 0x20, 0x63, 0x4B, 0x12, 0xF0, - 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE8, 0xD1, - 0x5F, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, 0xAC, 0xB1, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, + 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x1B, 0x68, 0x6A, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, + 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x0A, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFD, 0xF7, 0x4C, 0xFE, + 0xD8, 0xF8, 0x6C, 0x20, 0x63, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, + 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE8, 0xD1, 0x5F, 0x4B, 0x4F, 0xF0, 0xFF, 0x3A, 0xDF, 0xF8, + 0xAC, 0xB1, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, - 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x32, 0x68, - 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, 0x06, 0x2A, 0x0A, 0xD8, 0x18, 0x46, 0x51, 0x46, - 0xFE, 0xF7, 0x5B, 0xF9, 0xD8, 0xF8, 0x6C, 0x20, 0x56, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, - 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, 0x5E, 0x45, 0xE8, 0xD1, 0x2B, 0x68, 0x23, 0xF0, - 0x60, 0x03, 0x2B, 0x60, 0xD8, 0xF8, 0x1C, 0x30, 0xDA, 0x04, 0x32, 0xD5, 0x3B, 0x68, 0x23, 0xF0, - 0x0C, 0x03, 0x43, 0xF0, 0x04, 0x03, 0x3B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, - 0x2B, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x2B, 0x60, 0xD9, 0xF8, 0x00, 0x30, 0x03, 0xF0, 0x03, 0x03, - 0x03, 0x2B, 0xF9, 0xD1, 0xD9, 0xF8, 0x00, 0x30, 0x13, 0xF0, 0x0C, 0x0F, 0x03, 0xD0, 0x01, 0x24, - 0x14, 0x48, 0xFE, 0xF7, 0x2A, 0xF9, 0xD8, 0xF8, 0x1C, 0x30, 0xDB, 0x07, 0x0D, 0xD4, 0x12, 0x4A, - 0x13, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0xFA, 0xD1, 0x13, 0x68, 0x13, 0xF0, 0x0C, 0x0F, - 0x03, 0xD0, 0x01, 0x24, 0x0D, 0x48, 0xFE, 0xF7, 0x18, 0xF9, 0x2B, 0x68, 0x23, 0xF0, 0x60, 0x03, - 0x2B, 0x60, 0x3B, 0x68, 0x84, 0xF0, 0x01, 0x00, 0x23, 0xF0, 0x0C, 0x03, 0x3B, 0x60, 0xBD, 0xE8, - 0xF8, 0x8F, 0x00, 0xBF, 0x34, 0x01, 0x83, 0x04, 0x98, 0x01, 0x83, 0x04, 0x90, 0x01, 0x83, 0x04, - 0xE0, 0x08, 0x83, 0x04, 0x95, 0x30, 0x04, 0x00, 0xE0, 0x0A, 0x83, 0x04, 0xBA, 0x30, 0x04, 0x00, - 0xF0, 0x08, 0x83, 0x04, 0x38, 0x09, 0x83, 0x04, 0xF4, 0x08, 0x83, 0x04, 0xF8, 0x08, 0x83, 0x04, - 0xFC, 0x08, 0x83, 0x04, 0x00, 0x09, 0x83, 0x04, 0x04, 0x09, 0x83, 0x04, 0x08, 0x09, 0x83, 0x04, - 0x0C, 0x09, 0x83, 0x04, 0x10, 0x09, 0x83, 0x04, 0xE0, 0x30, 0x04, 0x00, 0x14, 0x09, 0x83, 0x04, - 0x18, 0x09, 0x83, 0x04, 0x1C, 0x09, 0x83, 0x04, 0x20, 0x09, 0x83, 0x04, 0x24, 0x09, 0x83, 0x04, - 0x28, 0x09, 0x83, 0x04, 0x2C, 0x09, 0x83, 0x04, 0x30, 0x09, 0x83, 0x04, 0x34, 0x09, 0x83, 0x04, - 0x09, 0x31, 0x04, 0x00, 0xF0, 0x0A, 0x83, 0x04, 0x38, 0x0B, 0x83, 0x04, 0xF4, 0x0A, 0x83, 0x04, - 0xF8, 0x0A, 0x83, 0x04, 0xFC, 0x0A, 0x83, 0x04, 0x00, 0x0B, 0x83, 0x04, 0x04, 0x0B, 0x83, 0x04, - 0x08, 0x0B, 0x83, 0x04, 0x0C, 0x0B, 0x83, 0x04, 0x10, 0x0B, 0x83, 0x04, 0x32, 0x31, 0x04, 0x00, - 0x14, 0x0B, 0x83, 0x04, 0x18, 0x0B, 0x83, 0x04, 0x1C, 0x0B, 0x83, 0x04, 0x20, 0x0B, 0x83, 0x04, - 0x24, 0x0B, 0x83, 0x04, 0x28, 0x0B, 0x83, 0x04, 0x2C, 0x0B, 0x83, 0x04, 0x30, 0x0B, 0x83, 0x04, - 0x34, 0x0B, 0x83, 0x04, 0x5B, 0x31, 0x04, 0x00, 0x5C, 0x09, 0x83, 0x04, 0x80, 0x09, 0x83, 0x04, - 0x5C, 0x0B, 0x83, 0x04, 0x80, 0x0B, 0x83, 0x04, 0x0A, 0x4B, 0x0B, 0x49, 0x1A, 0x68, 0x42, 0xF0, - 0x20, 0x02, 0x1A, 0x60, 0x0A, 0x68, 0xD2, 0x07, 0xFC, 0xD5, 0x1A, 0x68, 0x22, 0xF0, 0x20, 0x02, - 0x1A, 0x60, 0xFF, 0x23, 0x05, 0x4A, 0x13, 0x60, 0x13, 0x64, 0xC2, 0xF8, 0x80, 0x30, 0xC2, 0xF8, - 0xC0, 0x30, 0x70, 0x47, 0x50, 0x00, 0x83, 0x04, 0xAC, 0x01, 0x83, 0x04, 0x94, 0x03, 0x83, 0x04, - 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x00, 0xBF, - 0x60, 0x00, 0x82, 0x04, 0x10, 0xB5, 0x00, 0x23, 0x06, 0x4C, 0x01, 0x46, 0x18, 0x46, 0x23, 0x60, - 0xFF, 0xF7, 0xEE, 0xFF, 0x04, 0x4A, 0x01, 0x23, 0x23, 0x60, 0x13, 0x68, 0xDB, 0x07, 0xFC, 0xD5, - 0x10, 0xBD, 0x00, 0xBF, 0x20, 0x03, 0x82, 0x04, 0x24, 0x03, 0x82, 0x04, 0x01, 0x46, 0x08, 0xB5, - 0x01, 0x20, 0xFF, 0xF7, 0xDD, 0xFF, 0x06, 0x4B, 0x00, 0x22, 0x06, 0x49, 0x1A, 0x60, 0x0A, 0x68, - 0x22, 0xF0, 0x01, 0x02, 0x0A, 0x60, 0x1A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x1A, 0x60, 0x08, 0xBD, - 0x30, 0x00, 0x82, 0x04, 0xB0, 0x01, 0x82, 0x04, 0x83, 0x6F, 0x9B, 0x00, 0x41, 0xBF, 0x03, 0x4A, - 0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, 0x70, 0x47, 0x00, 0xBF, 0xC0, 0x01, 0x82, 0x04, - 0x0E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, 0x13, 0x60, 0x52, 0xF8, 0x20, 0x3C, 0x43, 0xF0, - 0x40, 0x43, 0x42, 0xF8, 0x20, 0x3C, 0x02, 0xF5, 0xFF, 0x52, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, - 0x13, 0x60, 0x02, 0xF5, 0x80, 0x52, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, 0x13, 0x60, 0x02, 0xF5, - 0x80, 0x52, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, 0x13, 0x60, 0x70, 0x47, 0xA0, 0x01, 0x82, 0x04, - 0x43, 0x68, 0x18, 0x21, 0x2D, 0xE9, 0xF0, 0x4F, 0xA3, 0xB0, 0x08, 0x26, 0x4F, 0xF0, 0x0E, 0x0A, - 0x03, 0x27, 0x83, 0x46, 0x00, 0x93, 0x3D, 0x46, 0xBB, 0x4B, 0xB8, 0x46, 0x4F, 0xF0, 0x06, 0x09, - 0x1B, 0x68, 0x12, 0x97, 0xCD, 0xF8, 0x28, 0x90, 0x01, 0x97, 0x1B, 0x0A, 0xCD, 0xF8, 0x24, 0x90, - 0x01, 0x33, 0xDB, 0xB2, 0x4B, 0x43, 0x1B, 0x93, 0x9B, 0x08, 0x21, 0x93, 0x04, 0x23, 0x05, 0x93, - 0xCD, 0xE9, 0x1E, 0x33, 0x08, 0x23, 0x1D, 0x93, 0x20, 0x93, 0x01, 0x23, 0x0D, 0x93, 0x02, 0x23, - 0x1A, 0x93, 0x04, 0x23, 0x02, 0x93, 0x04, 0x93, 0x0C, 0x93, 0x1B, 0x23, 0xCD, 0xE9, 0x18, 0x36, - 0x0C, 0x23, 0x11, 0x93, 0x80, 0x23, 0x17, 0x93, 0x62, 0x23, 0x10, 0x93, 0x0A, 0x23, 0x0B, 0x93, - 0x10, 0x23, 0xCD, 0xE9, 0x15, 0x3A, 0x14, 0x23, 0x14, 0x93, 0x00, 0x23, 0x02, 0x26, 0x08, 0x93, - 0x01, 0x23, 0x13, 0x96, 0x0F, 0x96, 0x03, 0x97, 0x0E, 0x97, 0xCD, 0xE9, 0x06, 0x33, 0x7B, 0x1C, - 0x02, 0xD1, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xDB, 0xF8, 0x78, 0x30, 0x1C, 0x93, 0x23, 0xF4, - 0xFF, 0x63, 0x23, 0xF0, 0x02, 0x03, 0x1B, 0x05, 0x1B, 0x0D, 0x05, 0x2B, 0x1C, 0x9B, 0x18, 0xBF, - 0x00, 0x27, 0x13, 0xF0, 0x04, 0x0A, 0x68, 0xD0, 0xDB, 0xF8, 0x60, 0x10, 0x00, 0x2F, 0x50, 0xD1, - 0x01, 0xF0, 0x1F, 0x01, 0x1B, 0x98, 0x01, 0x31, 0xBA, 0x46, 0x01, 0xF0, 0x26, 0xEB, 0x04, 0x46, - 0x00, 0x9B, 0x03, 0x2B, 0x5D, 0xD1, 0x21, 0x46, 0x32, 0x20, 0xFE, 0xF7, 0x3D, 0xF8, 0xC3, 0xB2, - 0x21, 0x46, 0x0A, 0x20, 0x15, 0x93, 0xFE, 0xF7, 0x37, 0xF8, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, - 0x38, 0xBF, 0x02, 0x20, 0x01, 0x90, 0x0F, 0x20, 0xFE, 0xF7, 0x2E, 0xF8, 0xC3, 0xB2, 0x21, 0x46, - 0x35, 0x20, 0x0A, 0x93, 0xFE, 0xF7, 0x28, 0xF8, 0xC3, 0xB2, 0x21, 0x46, 0x08, 0x20, 0x14, 0x93, - 0xFE, 0xF7, 0x22, 0xF8, 0xC5, 0xB2, 0x21, 0x46, 0x26, 0x20, 0x02, 0x2D, 0x38, 0xBF, 0x02, 0x25, - 0xFE, 0xF7, 0x1A, 0xF8, 0xC3, 0xB2, 0x21, 0x46, 0x41, 0xF6, 0x78, 0x60, 0x16, 0x93, 0xA8, 0x46, - 0xFE, 0xF7, 0x12, 0xF8, 0x21, 0x46, 0xC0, 0xF3, 0x4F, 0x13, 0x4F, 0xF4, 0xAF, 0x70, 0x10, 0x93, - 0xFE, 0xF7, 0x0A, 0xF8, 0x83, 0xB2, 0x21, 0x46, 0x4F, 0xF4, 0xB4, 0x70, 0x17, 0x93, 0xFE, 0xF7, - 0x03, 0xF8, 0xDD, 0xF8, 0x28, 0x90, 0xC0, 0xF3, 0x47, 0x13, 0x1F, 0x93, 0x0B, 0x95, 0x02, 0x23, - 0x74, 0xE0, 0x01, 0x2F, 0x0A, 0xD1, 0xC1, 0xF3, 0x04, 0x21, 0x01, 0x31, 0x1B, 0x98, 0x01, 0xF0, - 0xD4, 0xEA, 0x04, 0x46, 0x7B, 0x1C, 0x4F, 0xEA, 0x03, 0x3A, 0xA9, 0xE7, 0x02, 0x2F, 0x0C, 0xBF, - 0xC1, 0xF3, 0x04, 0x41, 0xC1, 0xF3, 0x04, 0x61, 0xEF, 0xE7, 0x21, 0x9C, 0x00, 0x2F, 0x9F, 0xD0, - 0xF0, 0xE7, 0x00, 0x9B, 0x04, 0x2B, 0x67, 0xD1, 0x21, 0x46, 0x23, 0x20, 0xFD, 0xF7, 0xDC, 0xFF, - 0xC3, 0xB2, 0x21, 0x46, 0x08, 0x20, 0x15, 0x93, 0xFD, 0xF7, 0xD6, 0xFF, 0xC0, 0xB2, 0x21, 0x46, - 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x01, 0x90, 0x06, 0x20, 0xFD, 0xF7, 0xCD, 0xFF, 0xC0, 0xB2, - 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x0B, 0x90, 0x0A, 0x20, 0xFD, 0xF7, 0xC4, 0xFF, - 0xC0, 0xB2, 0x21, 0x46, 0x08, 0x28, 0x38, 0xBF, 0x08, 0x20, 0x1D, 0x90, 0x0F, 0x20, 0xFD, 0xF7, - 0xBB, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x31, 0x20, 0x0A, 0x93, 0xFD, 0xF7, 0xB5, 0xFF, 0xC3, 0xB2, - 0x21, 0x46, 0x03, 0x20, 0x14, 0x93, 0xFD, 0xF7, 0xAF, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x22, 0x20, - 0x00, 0x2B, 0x08, 0xBF, 0x01, 0x23, 0x0D, 0x93, 0xFD, 0xF7, 0xA6, 0xFF, 0xC3, 0xB2, 0x21, 0x46, - 0x41, 0xF6, 0x78, 0x60, 0x16, 0x93, 0xFD, 0xF7, 0x9F, 0xFF, 0x21, 0x46, 0xC0, 0xF3, 0x4F, 0x13, - 0x4F, 0xF4, 0xAF, 0x70, 0x10, 0x93, 0xFD, 0xF7, 0x97, 0xFF, 0x83, 0xB2, 0x21, 0x46, 0x4F, 0xF4, - 0xB4, 0x70, 0x17, 0x93, 0xFD, 0xF7, 0x90, 0xFF, 0xC0, 0xF3, 0x47, 0x13, 0xDD, 0xF8, 0x04, 0x80, - 0x1F, 0x93, 0x0B, 0x9B, 0xDD, 0xF8, 0x28, 0x90, 0x1A, 0x93, 0x03, 0x23, 0x13, 0x93, 0x00, 0x9B, - 0xD9, 0x1E, 0x05, 0x29, 0x00, 0xF2, 0x15, 0x81, 0xDF, 0xE8, 0x11, 0xF0, 0x9A, 0x01, 0xBA, 0x00, - 0x13, 0x01, 0x13, 0x01, 0xD9, 0x01, 0xFC, 0x01, 0x00, 0x9B, 0x07, 0x2B, 0x4E, 0xD1, 0x21, 0x46, - 0x32, 0x20, 0xFD, 0xF7, 0x71, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x04, 0x28, 0x38, 0xBF, 0x04, 0x20, - 0x15, 0x90, 0x0A, 0x20, 0xFD, 0xF7, 0x68, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x18, 0x20, 0x00, 0x2B, - 0x08, 0xBF, 0x01, 0x23, 0x01, 0x93, 0xFD, 0xF7, 0x5F, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, - 0x38, 0xBF, 0x02, 0x20, 0x0A, 0x90, 0x46, 0x20, 0xFD, 0xF7, 0x56, 0xFF, 0xC3, 0xB2, 0x21, 0x46, - 0x08, 0x20, 0x14, 0x93, 0xFD, 0xF7, 0x50, 0xFF, 0xC5, 0xB2, 0x21, 0x46, 0x1B, 0x20, 0x02, 0x2D, - 0x38, 0xBF, 0x02, 0x25, 0xFD, 0xF7, 0x48, 0xFF, 0x21, 0x46, 0x5F, 0xFA, 0x80, 0xF9, 0x2A, 0x20, - 0xFD, 0xF7, 0x42, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x40, 0xF6, 0x3C, 0x70, 0x16, 0x93, 0xA8, 0x46, - 0xFD, 0xF7, 0x3A, 0xFF, 0x21, 0x46, 0xC0, 0xF3, 0x4F, 0x13, 0xD2, 0x20, 0x10, 0x93, 0xFD, 0xF7, - 0x33, 0xFF, 0x83, 0xB2, 0x21, 0x46, 0xDC, 0x20, 0x17, 0x93, 0xFD, 0xF7, 0x2D, 0xFF, 0xC3, 0xB2, - 0x0B, 0x95, 0x1E, 0x93, 0x2B, 0xE7, 0x00, 0xBF, 0x10, 0x10, 0x00, 0x03, 0x00, 0x9B, 0x08, 0x2B, - 0x9D, 0xD1, 0x21, 0x46, 0x28, 0x20, 0xFD, 0xF7, 0x1F, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x0A, 0x20, - 0x15, 0x93, 0xFD, 0xF7, 0x19, 0xFF, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x46, 0x12, 0x20, 0x43, 0x46, - 0x02, 0x2B, 0x38, 0xBF, 0x02, 0x23, 0x01, 0x93, 0xFD, 0xF7, 0x0E, 0xFF, 0xC0, 0xB2, 0x21, 0x46, - 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x0A, 0x90, 0x41, 0x20, 0xFD, 0xF7, 0x05, 0xFF, 0xC3, 0xB2, - 0x21, 0x46, 0x00, 0x98, 0x14, 0x93, 0xFD, 0xF7, 0xFF, 0xFE, 0xC5, 0xB2, 0x02, 0x2D, 0x2B, 0x46, - 0x38, 0xBF, 0x02, 0x23, 0x0B, 0x93, 0x1C, 0x9B, 0xD8, 0x00, 0x05, 0xD5, 0x21, 0x46, 0x0C, 0x20, - 0xFD, 0xF7, 0xF2, 0xFE, 0x5F, 0xFA, 0x80, 0xF8, 0xB8, 0xF1, 0x04, 0x0F, 0x21, 0x46, 0x38, 0xBF, - 0x4F, 0xF0, 0x04, 0x08, 0x15, 0x20, 0x04, 0x2D, 0x38, 0xBF, 0x04, 0x25, 0xFD, 0xF7, 0xE4, 0xFE, - 0x21, 0x46, 0x5F, 0xFA, 0x80, 0xF9, 0x2A, 0x20, 0xFD, 0xF7, 0xDE, 0xFE, 0xC3, 0xB2, 0x21, 0x46, - 0x4F, 0xF4, 0x74, 0x60, 0x16, 0x93, 0xFD, 0xF7, 0xD7, 0xFE, 0x21, 0x46, 0xC0, 0xF3, 0x4F, 0x13, - 0x4F, 0xF4, 0x8C, 0x70, 0x10, 0x93, 0xFD, 0xF7, 0xCF, 0xFE, 0x83, 0xB2, 0x21, 0x46, 0x4F, 0xF4, - 0x91, 0x70, 0x17, 0x93, 0xFD, 0xF7, 0xC8, 0xFE, 0xC3, 0xB2, 0x1E, 0x93, 0x04, 0x23, 0x3D, 0xE7, - 0x21, 0x46, 0x0F, 0x20, 0xFD, 0xF7, 0xC0, 0xFE, 0xC0, 0xB2, 0x21, 0x46, 0x0C, 0x28, 0x38, 0xBF, - 0x0C, 0x20, 0x09, 0x90, 0x05, 0x20, 0xFD, 0xF7, 0xB7, 0xFE, 0xC6, 0xB2, 0x21, 0x46, 0x0A, 0x20, - 0x02, 0x2E, 0x38, 0xBF, 0x02, 0x26, 0xFD, 0xF7, 0xAF, 0xFE, 0xC0, 0xB2, 0x71, 0x1C, 0xCB, 0xB2, - 0x21, 0x46, 0x03, 0x28, 0x38, 0xBF, 0x03, 0x20, 0x12, 0x93, 0x04, 0x90, 0xAA, 0x20, 0xFD, 0xF7, - 0xA3, 0xFE, 0x21, 0x46, 0xC0, 0xF3, 0x47, 0x13, 0xBC, 0x48, 0x05, 0x93, 0xFD, 0xF7, 0x9C, 0xFE, - 0xDB, 0xF8, 0x28, 0x10, 0xC0, 0xF3, 0x87, 0x23, 0x18, 0x93, 0xB9, 0xF1, 0x04, 0x0F, 0x94, 0xBF, - 0xC9, 0xF1, 0x09, 0x05, 0x04, 0x25, 0x21, 0xF0, 0x38, 0x01, 0x98, 0xBF, 0xED, 0xB2, 0x41, 0xF0, - 0x08, 0x01, 0xCB, 0xF8, 0x28, 0x10, 0x08, 0xF1, 0x07, 0x01, 0xCB, 0xB2, 0x4F, 0xF4, 0xA4, 0x60, - 0xCB, 0xF8, 0x20, 0x00, 0x19, 0x93, 0x0D, 0x9B, 0xD9, 0x1D, 0xCB, 0xB2, 0x20, 0x93, 0x04, 0x9B, - 0x02, 0x93, 0x05, 0x23, 0x0C, 0x93, 0x0E, 0x23, 0x11, 0x93, 0x04, 0x23, 0x0F, 0x93, 0x00, 0x23, - 0x08, 0x93, 0x05, 0x23, 0x03, 0x93, 0x07, 0x23, 0x0E, 0x93, 0x06, 0x23, 0x07, 0x93, 0x0A, 0x23, - 0x06, 0x93, 0xDD, 0xE9, 0x15, 0x23, 0xA2, 0x48, 0x43, 0xEA, 0x02, 0x41, 0x11, 0x9B, 0x0B, 0x9A, - 0x41, 0xEA, 0x03, 0x61, 0x18, 0x9B, 0x41, 0xEA, 0x03, 0x21, 0x9E, 0x4B, 0x4A, 0xF8, 0x03, 0x10, - 0x14, 0x9B, 0x43, 0xEA, 0x02, 0x41, 0x9C, 0x4B, 0x41, 0xEA, 0x05, 0x21, 0x4A, 0xF8, 0x03, 0x10, - 0x0E, 0x9B, 0x19, 0x04, 0x03, 0x9B, 0x41, 0xEA, 0x03, 0x61, 0x19, 0x9B, 0x19, 0x43, 0x0C, 0x9B, - 0x41, 0xEA, 0x03, 0x21, 0x95, 0x4B, 0x4A, 0xF8, 0x03, 0x10, 0x0F, 0x9B, 0x19, 0x03, 0x08, 0x9B, - 0x41, 0xEA, 0x03, 0x51, 0x09, 0x9B, 0x19, 0x43, 0x91, 0x4B, 0x4A, 0xF8, 0x03, 0x10, 0x13, 0x9B, - 0x19, 0x04, 0x0A, 0x9B, 0x41, 0xEA, 0x03, 0x61, 0x01, 0x9B, 0x41, 0xEA, 0x09, 0x01, 0x41, 0xEA, - 0x03, 0x21, 0x8C, 0x4B, 0x4A, 0xF8, 0x03, 0x10, 0x02, 0x9B, 0x19, 0x04, 0x04, 0x9B, 0x41, 0xEA, - 0x03, 0x61, 0x12, 0x9B, 0x31, 0x43, 0x41, 0xEA, 0x03, 0x21, 0x87, 0x4B, 0x4A, 0xF8, 0x03, 0x10, - 0x91, 0x1C, 0x86, 0x4B, 0x41, 0xF0, 0x00, 0x71, 0x41, 0xF4, 0x00, 0x31, 0x1A, 0x9A, 0x4A, 0xF8, - 0x03, 0x10, 0x1F, 0x9B, 0x43, 0xF4, 0x80, 0x51, 0x05, 0x9B, 0x41, 0xEA, 0x03, 0x61, 0x41, 0xEA, - 0x03, 0x41, 0x20, 0x9B, 0x4A, 0xF8, 0x00, 0x10, 0x04, 0x30, 0x43, 0xEA, 0x02, 0x21, 0x41, 0xF4, - 0x00, 0x31, 0x4A, 0xF8, 0x00, 0x10, 0x7A, 0x49, 0x7A, 0x48, 0x4A, 0xF8, 0x01, 0x00, 0x04, 0x31, - 0x79, 0x48, 0x1D, 0x9B, 0x4A, 0xF8, 0x01, 0x00, 0x04, 0x31, 0x78, 0x48, 0x4A, 0xF8, 0x01, 0x30, - 0x04, 0x31, 0x1E, 0x9B, 0x4A, 0xF8, 0x01, 0x00, 0x04, 0x31, 0x4A, 0xF8, 0x01, 0x30, 0x74, 0x4B, - 0x18, 0x68, 0x00, 0x9B, 0x07, 0x2B, 0x40, 0xF0, 0xE7, 0x80, 0x20, 0xF0, 0x43, 0x40, 0x20, 0xF4, - 0x7F, 0x00, 0x40, 0xF4, 0x9E, 0x00, 0x6F, 0x49, 0x01, 0x40, 0x41, 0xF4, 0x89, 0x71, 0xE2, 0xE0, - 0x21, 0x46, 0x08, 0x20, 0xFD, 0xF7, 0xE0, 0xFD, 0x21, 0x46, 0x06, 0x46, 0x0A, 0x20, 0xFD, 0xF7, - 0xDB, 0xFD, 0xC3, 0xB2, 0x02, 0x2B, 0x04, 0x93, 0x2F, 0xD9, 0xF6, 0xB2, 0x02, 0x2E, 0x38, 0xBF, - 0x02, 0x26, 0x71, 0x1C, 0x20, 0x46, 0xCB, 0xB2, 0x0F, 0x21, 0x12, 0x93, 0x01, 0xF0, 0x36, 0xE9, - 0xDB, 0xF8, 0x28, 0x10, 0xC3, 0xB2, 0x41, 0xF6, 0x14, 0x70, 0x18, 0x93, 0x21, 0xF0, 0x38, 0x01, - 0xCB, 0xF8, 0x20, 0x00, 0x41, 0xF0, 0x20, 0x01, 0xCB, 0xF8, 0x28, 0x10, 0x00, 0x21, 0xCB, 0xF8, - 0x2C, 0x10, 0x05, 0xEB, 0x09, 0x01, 0x08, 0x29, 0x08, 0xF1, 0x07, 0x01, 0xCB, 0xB2, 0xDC, 0xBF, - 0xC9, 0xF1, 0x09, 0x05, 0xED, 0xB2, 0x19, 0x93, 0x04, 0x9B, 0x02, 0x93, 0x05, 0x23, 0x0C, 0x93, - 0x0E, 0x23, 0x11, 0x93, 0x0C, 0x23, 0x09, 0x93, 0x2F, 0xE7, 0x06, 0x26, 0xD1, 0xE7, 0x83, 0x23, - 0x1C, 0x21, 0xCB, 0xE9, 0x09, 0x31, 0x00, 0x21, 0xCB, 0xF8, 0x20, 0x10, 0x08, 0xF1, 0x09, 0x01, - 0xCB, 0xB2, 0x03, 0x26, 0x19, 0x93, 0x05, 0x23, 0x02, 0x93, 0x04, 0x93, 0x12, 0x93, 0x0D, 0x23, - 0x0C, 0x93, 0x18, 0x23, 0x18, 0x93, 0x10, 0x23, 0x11, 0x93, 0x0C, 0x23, 0x09, 0x93, 0x05, 0x23, - 0x0F, 0x93, 0x08, 0x93, 0x04, 0x23, 0x03, 0x93, 0x07, 0x23, 0x0E, 0x93, 0x06, 0x23, 0x07, 0x93, - 0x0C, 0x23, 0x15, 0xE7, 0x21, 0x46, 0x0E, 0x20, 0xFD, 0xF7, 0x7E, 0xFD, 0xC0, 0xB2, 0x21, 0x46, - 0x05, 0x28, 0x38, 0xBF, 0x05, 0x20, 0x08, 0x90, 0x0F, 0x20, 0xFD, 0xF7, 0x75, 0xFD, 0xC6, 0xB2, - 0x21, 0x46, 0x02, 0x20, 0x02, 0x2E, 0x38, 0xBF, 0x02, 0x26, 0xFD, 0xF7, 0x6D, 0xFD, 0xC0, 0xB2, - 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x04, 0x90, 0x05, 0x20, 0xFD, 0xF7, 0x64, 0xFD, - 0x10, 0x9B, 0xC0, 0xB2, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x03, 0xEB, 0xC3, 0x01, 0x02, 0x90, - 0x04, 0x20, 0xC1, 0xF3, 0x47, 0x13, 0x21, 0x46, 0x18, 0x93, 0xFD, 0xF7, 0x55, 0xFD, 0x05, 0x46, - 0x21, 0x46, 0x01, 0x20, 0x11, 0x35, 0xFD, 0xF7, 0x4F, 0xFD, 0x2D, 0x1A, 0x1B, 0x21, 0xEB, 0xB2, - 0x34, 0x24, 0xCB, 0xE9, 0x09, 0x41, 0x08, 0xF1, 0x0E, 0x01, 0x0C, 0x93, 0xCB, 0xB2, 0x12, 0x96, - 0x04, 0x25, 0x19, 0x93, 0x1C, 0x9B, 0x13, 0xF0, 0x80, 0x5F, 0x08, 0x9B, 0x0F, 0x93, 0x4F, 0xF0, - 0x18, 0x03, 0x11, 0x93, 0x4F, 0xF0, 0x0C, 0x03, 0x09, 0x93, 0x4F, 0xF0, 0x05, 0x03, 0x03, 0x93, - 0x05, 0xD1, 0x0A, 0x23, 0x0E, 0x93, 0x05, 0x23, 0x07, 0x93, 0x11, 0x23, 0xC0, 0xE6, 0x0B, 0x23, - 0x0E, 0x93, 0x05, 0x23, 0x07, 0x93, 0x13, 0x23, 0xBA, 0xE6, 0x00, 0xBF, 0x38, 0x12, 0x01, 0x00, - 0x20, 0x01, 0x82, 0x04, 0x00, 0x01, 0x82, 0x04, 0x04, 0x01, 0x82, 0x04, 0x08, 0x01, 0x82, 0x04, - 0x0C, 0x01, 0x82, 0x04, 0x10, 0x01, 0x82, 0x04, 0x14, 0x01, 0x82, 0x04, 0x18, 0x01, 0x82, 0x04, - 0x28, 0x01, 0x82, 0x04, 0x05, 0x0C, 0x0E, 0x00, 0x1C, 0x02, 0x0C, 0x44, 0x02, 0x00, 0x10, 0x0A, - 0xD0, 0x00, 0x82, 0x04, 0x00, 0xF0, 0xFF, 0x3F, 0x00, 0x9B, 0x08, 0x2B, 0x5C, 0xD1, 0x4A, 0x49, - 0x01, 0x40, 0x41, 0xF4, 0x7C, 0x71, 0x49, 0x4B, 0x00, 0x9A, 0x49, 0x4C, 0x19, 0x60, 0xDB, 0xF8, - 0x78, 0x10, 0x48, 0x4B, 0x11, 0xF0, 0x08, 0x0F, 0x47, 0x49, 0x14, 0xBF, 0x4F, 0xF4, 0x84, 0x00, - 0x4F, 0xF0, 0xF9, 0x70, 0x08, 0x60, 0x45, 0x48, 0x01, 0x68, 0x21, 0xF4, 0x7F, 0x41, 0x21, 0xF0, - 0x0F, 0x01, 0x41, 0xF4, 0x50, 0x61, 0x41, 0xF0, 0x05, 0x01, 0x01, 0x60, 0x00, 0x20, 0x40, 0x49, - 0x08, 0x60, 0x91, 0x1F, 0x02, 0x29, 0xDB, 0xF8, 0x24, 0x20, 0x38, 0xD8, 0xDB, 0xF8, 0x28, 0x10, - 0x41, 0xEA, 0x02, 0x41, 0x4A, 0xF8, 0x03, 0x10, 0xDB, 0xF8, 0x2C, 0x10, 0x00, 0x9B, 0x09, 0x04, - 0x08, 0x2B, 0x4A, 0xF8, 0x04, 0x10, 0x46, 0xD0, 0x36, 0x48, 0x5A, 0xF8, 0x00, 0x10, 0x21, 0xF4, - 0x7F, 0x61, 0x41, 0xF4, 0xCC, 0x61, 0x4A, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x78, 0x10, 0x11, 0xF0, - 0x20, 0x0F, 0x31, 0x49, 0x48, 0xD1, 0x06, 0x9B, 0x58, 0x1E, 0x07, 0x9B, 0x5C, 0x1E, 0x44, 0xF0, - 0x00, 0x74, 0x44, 0xEA, 0x00, 0x40, 0x01, 0x43, 0x2C, 0x48, 0x17, 0x9B, 0x01, 0x3F, 0x10, 0x9A, - 0x4A, 0xF8, 0x00, 0x10, 0x2A, 0x49, 0x2B, 0x48, 0x4A, 0xF8, 0x01, 0x00, 0x43, 0xEA, 0x02, 0x41, - 0x29, 0x48, 0x4A, 0xF8, 0x00, 0x10, 0x42, 0xE4, 0x20, 0xF0, 0x40, 0x40, 0xBB, 0xE6, 0xDB, 0xF8, - 0x20, 0x00, 0x42, 0xEA, 0x00, 0x40, 0x4A, 0xF8, 0x03, 0x00, 0xDB, 0xE9, 0x0A, 0x01, 0x00, 0x9B, - 0x41, 0xEA, 0x00, 0x41, 0x04, 0x2B, 0x4A, 0xF8, 0x04, 0x10, 0xC5, 0xD1, 0xDB, 0xE9, 0x0C, 0x01, - 0x41, 0xEA, 0x00, 0x41, 0x1D, 0x48, 0x4A, 0xF8, 0x00, 0x10, 0x1D, 0x49, 0xDB, 0xF8, 0x38, 0x00, - 0x4A, 0xF8, 0x01, 0x00, 0xB8, 0xE7, 0xDB, 0xE9, 0x0F, 0x01, 0x41, 0xEA, 0x00, 0x41, 0x17, 0x48, - 0x4A, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x54, 0x00, 0xDB, 0xF8, 0x48, 0x10, 0x41, 0xEA, 0x00, 0x41, - 0x13, 0x48, 0x4A, 0xF8, 0x00, 0x10, 0xA7, 0xE7, 0x07, 0x9B, 0x43, 0xF0, 0x00, 0x70, 0x06, 0x9B, - 0x40, 0xEA, 0x03, 0x40, 0xB7, 0xE7, 0x00, 0xBF, 0x00, 0xF0, 0xFF, 0x3F, 0xD0, 0x00, 0x82, 0x04, - 0xE0, 0x00, 0x82, 0x04, 0xDC, 0x00, 0x82, 0x04, 0xD4, 0x00, 0x82, 0x04, 0xD8, 0x00, 0x82, 0x04, - 0xB0, 0x01, 0x82, 0x04, 0xF4, 0x00, 0x82, 0x04, 0x00, 0x80, 0x80, 0x00, 0x90, 0x01, 0x82, 0x04, - 0x94, 0x01, 0x82, 0x04, 0x02, 0x02, 0x10, 0x00, 0x64, 0x00, 0x82, 0x04, 0xE8, 0x00, 0x82, 0x04, - 0xEC, 0x00, 0x82, 0x04, 0x83, 0x69, 0xC2, 0x69, 0x2D, 0xE9, 0xF0, 0x47, 0xC3, 0xF3, 0x01, 0x31, - 0x03, 0xF0, 0x0F, 0x04, 0xC3, 0xF3, 0x07, 0x16, 0xC3, 0xF3, 0x81, 0x33, 0x15, 0x07, 0x4F, 0xEA, - 0x03, 0x49, 0x4F, 0xEA, 0x03, 0x25, 0x64, 0x4F, 0x4F, 0xEA, 0x03, 0x62, 0x18, 0xBF, 0x04, 0xF1, - 0xFF, 0x34, 0x45, 0xEA, 0x09, 0x0E, 0x4E, 0xEA, 0x02, 0x0C, 0xA4, 0xF1, 0x08, 0x08, 0xC7, 0xF8, - 0x00, 0xC0, 0x08, 0x37, 0xDF, 0xF8, 0x88, 0xC1, 0xB8, 0xF1, 0x03, 0x0F, 0x53, 0xD8, 0xDF, 0xE8, - 0x08, 0xF0, 0x02, 0x3D, 0x44, 0x4A, 0x43, 0xF0, 0xF8, 0x5E, 0x4E, 0xF4, 0xF8, 0x1E, 0x4E, 0xEA, - 0x05, 0x05, 0xCC, 0xF8, 0x00, 0x50, 0x41, 0xF6, 0x1F, 0x72, 0x3A, 0x60, 0x02, 0x2B, 0x4A, 0xD0, - 0x43, 0xF6, 0x3F, 0x72, 0x43, 0xF6, 0x01, 0x75, 0x01, 0x2B, 0x08, 0xBF, 0x2A, 0x46, 0x4F, 0x4D, - 0x03, 0x29, 0x4F, 0x4F, 0x2A, 0x60, 0xA3, 0xF1, 0x02, 0x02, 0x22, 0x44, 0x0B, 0x44, 0x4F, 0xEA, - 0x02, 0x25, 0x18, 0xBF, 0x42, 0xF4, 0x7C, 0x12, 0x23, 0x44, 0x4A, 0x49, 0x08, 0xBF, 0x45, 0xEA, - 0x02, 0x45, 0x2A, 0x43, 0x04, 0x31, 0x3A, 0x60, 0x9A, 0x1F, 0x42, 0xEA, 0x02, 0x2C, 0xA6, 0xF1, - 0x0E, 0x07, 0x45, 0x4D, 0x4C, 0xEA, 0x02, 0x48, 0x48, 0xEA, 0x02, 0x6E, 0x41, 0xF8, 0x04, 0xEC, - 0x03, 0x2F, 0x6F, 0xD8, 0xDF, 0xE8, 0x07, 0xF0, 0x22, 0x3A, 0x54, 0x69, 0x43, 0xF0, 0xF8, 0x5E, - 0x4E, 0xEA, 0x05, 0x05, 0x45, 0xEA, 0x09, 0x05, 0xC3, 0xE7, 0x1A, 0x43, 0x42, 0xEA, 0x0E, 0x02, - 0xCC, 0xF8, 0x00, 0x20, 0xBF, 0xE7, 0x1A, 0x43, 0x42, 0xEA, 0x0E, 0x02, 0xCC, 0xF8, 0x00, 0x20, - 0x43, 0xF4, 0xF8, 0x52, 0xB9, 0xE7, 0x1D, 0x43, 0x49, 0xEA, 0x02, 0x02, 0x2A, 0x43, 0xCC, 0xF8, - 0x00, 0x20, 0x3D, 0x60, 0xB2, 0xE7, 0x40, 0xF2, 0x01, 0x12, 0xB8, 0xE7, 0x4C, 0xF0, 0x70, 0x62, - 0x42, 0xF4, 0x70, 0x22, 0x0A, 0x60, 0x40, 0xF6, 0x0F, 0x72, 0x2A, 0x60, 0xC2, 0x69, 0xD2, 0x04, - 0x45, 0xD5, 0xB0, 0xF8, 0x7A, 0x20, 0x02, 0xF0, 0x07, 0x02, 0x01, 0x3A, 0x02, 0x2A, 0x03, 0xD9, - 0x06, 0x3E, 0x1E, 0x44, 0x25, 0x4B, 0x1E, 0x60, 0xBD, 0xE8, 0xF0, 0x87, 0xB0, 0xF8, 0x7A, 0x70, - 0x07, 0xF0, 0x07, 0x07, 0x01, 0x2F, 0x0C, 0xD1, 0x0B, 0x2C, 0x0E, 0xD1, 0x5C, 0x1F, 0x42, 0xF0, - 0x70, 0x62, 0x42, 0xEA, 0x04, 0x22, 0x42, 0xEA, 0x04, 0x42, 0x0A, 0x60, 0xDA, 0x1D, 0x1B, 0x49, - 0xD8, 0xE7, 0x02, 0x2F, 0x01, 0xD1, 0x0A, 0x2C, 0xEF, 0xE7, 0x48, 0xF0, 0x70, 0x62, 0xD1, 0xE7, - 0xB0, 0xF8, 0x7A, 0x70, 0x07, 0xF0, 0x07, 0x07, 0x01, 0x2F, 0x0B, 0xD1, 0x0A, 0x2C, 0x09, 0xD1, - 0x5C, 0x1F, 0x22, 0x06, 0x42, 0xEA, 0x04, 0x42, 0x42, 0xEA, 0x0C, 0x02, 0x0A, 0x60, 0x03, 0xF1, - 0x08, 0x02, 0xE4, 0xE7, 0xC1, 0xF8, 0x00, 0xE0, 0xBD, 0xE7, 0xC1, 0xF8, 0x00, 0xE0, 0x42, 0xF4, - 0x70, 0x62, 0xBA, 0xE7, 0xC1, 0xF8, 0x00, 0xE0, 0xC5, 0xF8, 0x00, 0xC0, 0xB6, 0xE7, 0x07, 0x4B, - 0x1F, 0x22, 0x1A, 0x60, 0xC0, 0xE7, 0x00, 0xBF, 0x08, 0x02, 0x82, 0x04, 0x20, 0x02, 0x82, 0x04, - 0x04, 0x02, 0x82, 0x04, 0x14, 0x02, 0x82, 0x04, 0x1C, 0x02, 0x82, 0x04, 0x00, 0x02, 0x82, 0x04, - 0x0C, 0x02, 0x82, 0x04, 0xC3, 0x69, 0x40, 0xF2, 0x01, 0x22, 0x30, 0xB5, 0x13, 0xF4, 0x80, 0x5F, - 0x40, 0xF2, 0x03, 0x33, 0x08, 0xBF, 0x13, 0x46, 0x1D, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x03, 0xF0, - 0x07, 0x03, 0x04, 0x2B, 0x12, 0xD0, 0x07, 0x2B, 0x1C, 0xD0, 0x03, 0x2B, 0x19, 0x4B, 0x18, 0xBF, - 0x4F, 0xF0, 0x04, 0x23, 0x18, 0x4A, 0x13, 0x60, 0x02, 0xF5, 0x00, 0x52, 0x13, 0x60, 0x02, 0xF5, - 0x80, 0x52, 0x13, 0x60, 0x02, 0xF5, 0x80, 0x52, 0x13, 0x60, 0x30, 0xBD, 0x02, 0x6B, 0xC2, 0xF3, - 0x00, 0x33, 0x99, 0x1D, 0x93, 0x02, 0x03, 0xF4, 0xE0, 0x23, 0x43, 0xF4, 0x80, 0x63, 0x43, 0xEA, - 0x01, 0x63, 0xE7, 0xE7, 0x01, 0x68, 0x0D, 0x4C, 0xB1, 0xF5, 0xC8, 0x7F, 0xC1, 0xEB, 0xC1, 0x02, - 0x34, 0xBF, 0x03, 0x21, 0x04, 0x21, 0x82, 0xFB, 0x04, 0x45, 0xD2, 0x17, 0xC2, 0xEB, 0xE5, 0x12, - 0xD3, 0x1D, 0x8A, 0x1A, 0x1B, 0x06, 0x43, 0xF4, 0x80, 0x63, 0x43, 0xEA, 0x02, 0x43, 0xD1, 0xE7, - 0x44, 0x02, 0x82, 0x04, 0x00, 0x04, 0x00, 0x06, 0x40, 0x02, 0x82, 0x04, 0xD3, 0x4D, 0x62, 0x10, - 0x06, 0x4A, 0x13, 0x68, 0x19, 0x05, 0x03, 0xD5, 0x23, 0xF4, 0x80, 0x63, 0x13, 0x60, 0x70, 0x47, - 0x81, 0x6F, 0x89, 0x06, 0xF8, 0xD4, 0x43, 0xF4, 0x80, 0x63, 0xF7, 0xE7, 0x00, 0x00, 0x82, 0x04, - 0x03, 0x4A, 0x83, 0x6F, 0x11, 0x68, 0xC3, 0xF3, 0x80, 0x73, 0x0B, 0x43, 0x13, 0x60, 0x70, 0x47, - 0x00, 0x00, 0x82, 0x04, 0x43, 0x68, 0x03, 0xF0, 0x0F, 0x03, 0x04, 0x3B, 0x04, 0x2B, 0x97, 0xBF, - 0x0A, 0x4A, 0x0B, 0x49, 0x02, 0xEB, 0x83, 0x03, 0xD3, 0xF8, 0xA8, 0x13, 0xC3, 0x69, 0xDA, 0x0A, - 0x1B, 0x03, 0x02, 0xF0, 0x06, 0x02, 0x03, 0xF4, 0x80, 0x53, 0x01, 0x32, 0x43, 0xF0, 0x40, 0x43, - 0x43, 0xEA, 0x02, 0x63, 0x03, 0x4A, 0x0B, 0x43, 0x13, 0x60, 0x70, 0x47, 0x94, 0x29, 0x04, 0x00, - 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0x04, 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0xDA, 0xFF, - 0x43, 0x68, 0x04, 0x2B, 0x01, 0xD1, 0xFF, 0xF7, 0xCB, 0xFF, 0x63, 0x68, 0x03, 0x3B, 0x01, 0x2B, - 0x02, 0xD8, 0x20, 0x46, 0xFF, 0xF7, 0xB4, 0xFF, 0x20, 0x46, 0xFF, 0xF7, 0x63, 0xFF, 0xFF, 0xF7, - 0x79, 0xFE, 0xFF, 0xF7, 0x1D, 0xFA, 0x09, 0x4B, 0x00, 0x22, 0x20, 0x46, 0x1A, 0x60, 0xFF, 0xF7, - 0xF7, 0xF9, 0x63, 0x68, 0x04, 0x2B, 0x01, 0xD0, 0x08, 0x2B, 0x02, 0xD1, 0x20, 0x46, 0xFF, 0xF7, - 0xE3, 0xF9, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0xC8, 0xB9, 0x30, 0x00, 0x82, 0x04, - 0x43, 0x68, 0x08, 0x2B, 0x01, 0xBF, 0x0D, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, - 0x0B, 0x4B, 0x1A, 0x68, 0x22, 0xF4, 0x7F, 0x42, 0x42, 0xF4, 0x40, 0x52, 0x1A, 0x60, 0x82, 0x6F, - 0xD2, 0x00, 0x09, 0xD5, 0x1A, 0x68, 0x07, 0x48, 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x01, 0x02, - 0x1A, 0x60, 0x19, 0x68, 0xFD, 0xF7, 0x11, 0xBA, 0x70, 0x47, 0x00, 0xBF, 0xA8, 0x2E, 0x10, 0x03, - 0x50, 0x02, 0x82, 0x04, 0x84, 0x31, 0x04, 0x00, 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0x27, 0x4D, - 0x05, 0x20, 0x27, 0x4E, 0x2B, 0x68, 0x27, 0x4F, 0x27, 0x4C, 0x23, 0xF0, 0x00, 0x43, 0x2B, 0x60, - 0x2B, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x2B, 0x60, 0x33, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, - 0x33, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x33, 0x60, 0x3B, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x3B, 0x60, - 0x23, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x23, 0x60, 0xFD, 0xF7, 0xF8, 0xF9, 0xD8, 0xF8, 0x00, 0x00, - 0x42, 0x46, 0x39, 0x46, 0x40, 0x00, 0xFD, 0xF7, 0x71, 0xFC, 0x23, 0x68, 0x05, 0x20, 0x23, 0xF0, - 0x40, 0x73, 0x23, 0x60, 0x23, 0x68, 0x23, 0xF0, 0x1F, 0x03, 0x43, 0xF0, 0x03, 0x02, 0x43, 0xF0, - 0x00, 0x63, 0x43, 0xF0, 0x03, 0x03, 0x22, 0x60, 0x23, 0x60, 0x33, 0x68, 0x43, 0xF4, 0x80, 0x33, - 0x33, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x80, 0x43, - 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x00, 0x43, 0x2B, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x80, 0x43, - 0x23, 0x60, 0xBD, 0xE8, 0xF0, 0x41, 0xFD, 0xF7, 0xC9, 0xB9, 0x00, 0xBF, 0x40, 0x15, 0x00, 0x03, - 0x0C, 0x18, 0x00, 0x03, 0x10, 0x10, 0x00, 0x03, 0x00, 0x18, 0x00, 0x03, 0x10, 0xB5, 0x04, 0x46, - 0xFF, 0xF7, 0xA2, 0xFF, 0x20, 0x46, 0x00, 0xF0, 0x01, 0xFC, 0x63, 0x68, 0x04, 0x2B, 0x04, 0xBF, - 0x4F, 0xF0, 0x80, 0x43, 0x1B, 0x68, 0x10, 0xBD, 0x2D, 0xE9, 0xF8, 0x4F, 0x04, 0x46, 0x69, 0x4D, - 0xD0, 0xF8, 0x00, 0xA0, 0xD0, 0xE9, 0x1C, 0x67, 0xFD, 0xF7, 0x94, 0xFA, 0x20, 0x46, 0xFF, 0xF7, - 0xE5, 0xFF, 0xE0, 0xB1, 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, - 0xE9, 0xFA, 0xA0, 0xB9, 0xDF, 0xF8, 0xA8, 0xB1, 0x4F, 0xF0, 0x05, 0x08, 0x21, 0x68, 0x5E, 0x48, - 0xFD, 0xF7, 0x83, 0xF9, 0x23, 0x68, 0x53, 0x45, 0x1A, 0xD9, 0xA3, 0x6F, 0x01, 0x25, 0xC4, 0xF8, - 0x00, 0xA0, 0x1A, 0x02, 0x5C, 0xBF, 0x23, 0xF4, 0x00, 0x63, 0xA3, 0x67, 0x0D, 0xE0, 0x21, 0x68, - 0x28, 0x46, 0xFD, 0xF7, 0x72, 0xF9, 0x23, 0x68, 0x60, 0x3B, 0xB3, 0xF5, 0xB4, 0x7F, 0x23, 0x60, - 0xD4, 0xD2, 0x52, 0x48, 0x00, 0x25, 0xFD, 0xF7, 0x68, 0xF9, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, - 0xB8, 0xF1, 0x01, 0x08, 0x01, 0xD1, 0x4E, 0x48, 0xF4, 0xE7, 0x20, 0x46, 0xFE, 0xF7, 0x36, 0xF8, - 0x00, 0x28, 0x35, 0xD0, 0x4F, 0xF0, 0x04, 0x09, 0x21, 0x68, 0x4A, 0x48, 0xFD, 0xF7, 0x55, 0xF9, - 0xB9, 0xF1, 0x01, 0x09, 0x05, 0xD1, 0x48, 0x48, 0xE4, 0xE7, 0x23, 0x68, 0x60, 0x3B, 0x23, 0x60, - 0xF6, 0xE7, 0xC4, 0xE9, 0x1C, 0x67, 0x20, 0x46, 0xFF, 0xF7, 0x98, 0xFF, 0x05, 0x46, 0x00, 0x28, - 0xDB, 0xD0, 0x20, 0x46, 0xFE, 0xF7, 0x1A, 0xF8, 0x00, 0x28, 0xEE, 0xD1, 0xD4, 0xE9, 0x1C, 0x12, - 0x3E, 0x48, 0xFD, 0xF7, 0x3A, 0xF9, 0x23, 0x68, 0x60, 0x33, 0x53, 0x45, 0x23, 0x60, 0xB1, 0xD8, - 0x20, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0x00, 0x28, 0x3B, 0xD0, 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, - 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, 0x86, 0xFA, 0x98, 0xBB, 0xD4, 0xE9, 0x1C, 0x67, 0xA1, 0xE7, - 0x20, 0x46, 0xFF, 0xF7, 0x73, 0xFF, 0x50, 0xB1, 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, - 0x80, 0x50, 0xFD, 0xF7, 0x77, 0xFA, 0x10, 0xB9, 0xD4, 0xE9, 0x1C, 0x67, 0xD6, 0xE7, 0x22, 0x68, - 0x03, 0x25, 0x58, 0x46, 0xA2, 0xF1, 0x60, 0x01, 0xFD, 0xF7, 0x0F, 0xF9, 0xC4, 0xE9, 0x1C, 0x67, - 0x23, 0x68, 0x01, 0x3D, 0xA3, 0xF1, 0x60, 0x03, 0x23, 0x60, 0x03, 0xD1, 0x24, 0x48, 0xFD, 0xF7, - 0x04, 0xF9, 0x9A, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x51, 0xFF, 0x00, 0x28, 0xF0, 0xD0, 0x23, 0x46, - 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, 0x54, 0xFA, 0x00, 0x28, 0xE7, 0xD1, - 0xB4, 0xE7, 0xA1, 0x6F, 0x03, 0x25, 0x1B, 0x48, 0xFD, 0xF7, 0xEF, 0xF8, 0x22, 0x68, 0x58, 0x46, - 0xA2, 0xF1, 0x60, 0x01, 0xFD, 0xF7, 0xE9, 0xF8, 0xD4, 0xE9, 0x1C, 0x12, 0x16, 0x48, 0xFD, 0xF7, - 0xE4, 0xF8, 0xC4, 0xE9, 0x1C, 0x67, 0x23, 0x68, 0x01, 0x3D, 0xA3, 0xF1, 0x60, 0x03, 0x23, 0x60, - 0x01, 0xD1, 0x12, 0x48, 0xD3, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x28, 0xFF, 0x00, 0x28, 0xF2, 0xD0, - 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, 0x2B, 0xFA, 0x00, 0x28, - 0xE9, 0xD1, 0x47, 0xE7, 0xD4, 0x31, 0x04, 0x00, 0xA0, 0x31, 0x04, 0x00, 0x08, 0x32, 0x04, 0x00, - 0x40, 0x32, 0x04, 0x00, 0x61, 0x32, 0x04, 0x00, 0x87, 0x32, 0x04, 0x00, 0x0A, 0x33, 0x04, 0x00, - 0xE8, 0x32, 0x04, 0x00, 0x44, 0x33, 0x04, 0x00, 0x5C, 0x33, 0x04, 0x00, 0x8A, 0x33, 0x04, 0x00, - 0xA4, 0x32, 0x04, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, 0x04, 0x46, 0xC6, 0x6E, 0x85, 0x69, 0x46, 0xF0, - 0x80, 0x53, 0xC3, 0x66, 0x43, 0x68, 0x04, 0x2B, 0x0C, 0xBF, 0x4B, 0xF2, 0xEB, 0x03, 0x43, 0xF2, - 0xEB, 0x03, 0x83, 0x61, 0xD0, 0xE9, 0x06, 0x73, 0x13, 0xF0, 0x0F, 0x0F, 0x14, 0xBF, 0x4F, 0xF0, - 0x01, 0x09, 0x4F, 0xF0, 0x02, 0x09, 0xFF, 0xF7, 0xE9, 0xFE, 0x10, 0xB9, 0x00, 0x20, 0xBD, 0xE8, - 0xF8, 0x8F, 0x4F, 0xF0, 0x80, 0x42, 0x00, 0x23, 0xD9, 0x07, 0x54, 0xBF, 0xD1, 0x43, 0x11, 0x46, - 0x42, 0xF8, 0x04, 0x1B, 0xBF, 0xF3, 0x4F, 0x8F, 0x01, 0x33, 0x10, 0x2B, 0xF4, 0xD1, 0x4F, 0xF0, - 0x80, 0x43, 0x00, 0x21, 0xC8, 0x07, 0x40, 0xF1, 0x89, 0x80, 0x1A, 0x46, 0x18, 0x6C, 0x82, 0x42, - 0x40, 0xF0, 0x86, 0x80, 0x01, 0x31, 0x04, 0x33, 0x10, 0x29, 0xF3, 0xD1, 0x4F, 0xF0, 0x01, 0x08, - 0xC7, 0xF3, 0x81, 0x32, 0x4F, 0xF0, 0x01, 0x0E, 0x4A, 0x44, 0x07, 0x27, 0xD0, 0x19, 0x4F, 0xF0, - 0x80, 0x43, 0x0E, 0xFA, 0x00, 0xF0, 0x00, 0x21, 0x50, 0xF8, 0x03, 0x90, 0x11, 0xF0, 0x01, 0x0F, - 0x0C, 0xBF, 0x6F, 0xEA, 0x03, 0x0C, 0x9C, 0x46, 0xE1, 0x45, 0x40, 0xF0, 0x84, 0x80, 0x01, 0x31, - 0x04, 0x33, 0x10, 0x29, 0xF0, 0xD1, 0x01, 0x23, 0x0D, 0x32, 0x03, 0xFA, 0x02, 0xF2, 0x4F, 0xF0, - 0x80, 0x41, 0x00, 0x23, 0x52, 0xF8, 0x01, 0xC0, 0xD8, 0x07, 0x54, 0xBF, 0xC8, 0x43, 0x08, 0x46, - 0x84, 0x45, 0x6D, 0xD1, 0x01, 0x33, 0x04, 0x31, 0x10, 0x2B, 0xF3, 0xD1, 0x4F, 0xF0, 0x02, 0x0A, - 0x63, 0x68, 0x20, 0x46, 0x04, 0x2B, 0x0C, 0xBF, 0x46, 0xF2, 0x18, 0x13, 0x42, 0xF2, 0x18, 0x13, - 0xA3, 0x61, 0xD4, 0xE9, 0x06, 0x93, 0x13, 0xF0, 0x0F, 0x0F, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, - 0x4F, 0xF0, 0x02, 0x0B, 0xFF, 0xF7, 0x82, 0xFE, 0x00, 0x28, 0x97, 0xD0, 0x4F, 0xF0, 0x80, 0x42, - 0x00, 0x23, 0xD9, 0x07, 0x54, 0xBF, 0xD1, 0x43, 0x11, 0x46, 0x42, 0xF8, 0x04, 0x1B, 0xBF, 0xF3, - 0x4F, 0x8F, 0x01, 0x33, 0x10, 0x2B, 0xF4, 0xD1, 0xC9, 0xF3, 0x81, 0x39, 0x0C, 0x21, 0x09, 0xF1, - 0x0A, 0x09, 0x4F, 0xF0, 0x01, 0x0E, 0xD9, 0x44, 0x09, 0xEB, 0x01, 0x00, 0x4F, 0xF0, 0x80, 0x42, - 0x0E, 0xFA, 0x00, 0xF0, 0x00, 0x23, 0x50, 0xF8, 0x02, 0xB0, 0x13, 0xF0, 0x01, 0x0F, 0x0C, 0xBF, - 0x6F, 0xEA, 0x02, 0x0C, 0x94, 0x46, 0xE3, 0x45, 0x32, 0xD1, 0x01, 0x33, 0x04, 0x32, 0x10, 0x2B, - 0xF1, 0xD1, 0x2B, 0x0C, 0xE6, 0x66, 0x01, 0x20, 0x1B, 0x04, 0x43, 0xEA, 0x88, 0x33, 0x3B, 0x43, - 0x43, 0xEA, 0x0A, 0x33, 0x43, 0xEA, 0x01, 0x13, 0xA3, 0x61, 0x60, 0xE7, 0xDA, 0x43, 0x75, 0xE7, - 0x4F, 0xF0, 0x80, 0x43, 0x00, 0x21, 0xCA, 0x07, 0x10, 0xD5, 0x1A, 0x46, 0xD3, 0xF8, 0x80, 0x00, - 0x82, 0x42, 0x03, 0xD1, 0x01, 0x31, 0x04, 0x33, 0x10, 0x29, 0xF4, 0xD1, 0x63, 0x68, 0x04, 0x2B, - 0x14, 0xBF, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, 0x02, 0x08, 0x69, 0xE7, 0xDA, 0x43, 0xED, 0xE7, - 0x4F, 0xF0, 0x03, 0x0A, 0x94, 0xE7, 0x01, 0x37, 0x0B, 0x2F, 0x7F, 0xF4, 0x67, 0xAF, 0x7A, 0xE7, - 0x01, 0x31, 0x11, 0x29, 0xB8, 0xD1, 0xCC, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0xC7, 0x6E, - 0xD0, 0xF8, 0x78, 0x80, 0x47, 0xF0, 0x80, 0x53, 0xD0, 0xE9, 0x06, 0x96, 0xC3, 0x66, 0x48, 0xF0, - 0x01, 0x03, 0x83, 0x67, 0x43, 0x68, 0x04, 0x2B, 0x0C, 0xBF, 0x46, 0xF2, 0xB7, 0x03, 0x42, 0xF2, - 0xB7, 0x03, 0x83, 0x61, 0x4F, 0xF4, 0x80, 0x53, 0xC3, 0x61, 0xFF, 0xF7, 0x07, 0xFE, 0x05, 0x46, - 0x88, 0xB1, 0x34, 0x48, 0xFC, 0xF7, 0xB1, 0xFF, 0x33, 0x0C, 0xE2, 0x69, 0x4F, 0xF0, 0x01, 0x0A, - 0xC4, 0xF8, 0x78, 0x80, 0x1B, 0x04, 0xC4, 0xF8, 0x18, 0x90, 0xE7, 0x66, 0x13, 0x43, 0xE3, 0x61, - 0x50, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xA3, 0x6F, 0x98, 0x07, 0x0A, 0xD5, 0x20, 0x46, 0xFE, 0xF7, - 0x1F, 0xFA, 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, - 0xDF, 0xD1, 0x00, 0x23, 0x20, 0x46, 0xE3, 0x61, 0xFF, 0xF7, 0xE0, 0xFD, 0x05, 0x46, 0x08, 0xB1, - 0x21, 0x48, 0xD7, 0xE7, 0xA3, 0x6F, 0x99, 0x07, 0x0A, 0xD5, 0x20, 0x46, 0xFE, 0xF7, 0x08, 0xFA, - 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xEF, 0xD1, - 0x41, 0xF2, 0x01, 0x03, 0x20, 0x46, 0xE3, 0x61, 0xFF, 0xF7, 0xC8, 0xFD, 0x05, 0x46, 0x08, 0xB1, - 0x16, 0x48, 0xBF, 0xE7, 0xA3, 0x6F, 0x9A, 0x07, 0x0A, 0xD5, 0x20, 0x46, 0xFE, 0xF7, 0xF0, 0xF9, - 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xEF, 0xD1, - 0x01, 0x23, 0x20, 0x46, 0xE3, 0x61, 0xFF, 0xF7, 0xB1, 0xFD, 0x82, 0x46, 0x08, 0xB1, 0x0C, 0x48, - 0xA8, 0xE7, 0xA3, 0x6F, 0x9B, 0x07, 0xB3, 0xD5, 0x05, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0xD8, 0xF9, - 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xA7, 0xD0, - 0xED, 0xE7, 0x00, 0xBF, 0xAB, 0x33, 0x04, 0x00, 0xD8, 0x33, 0x04, 0x00, 0x05, 0x34, 0x04, 0x00, - 0x33, 0x34, 0x04, 0x00, 0x83, 0x6F, 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0x06, 0x68, 0xDD, 0x04, - 0x05, 0xD5, 0xB6, 0xF5, 0xB4, 0x7F, 0x84, 0xBF, 0x4F, 0xF4, 0xB4, 0x72, 0x02, 0x60, 0x13, 0xF0, - 0x00, 0x75, 0x14, 0xD0, 0x44, 0x4A, 0x65, 0x69, 0x44, 0x48, 0x62, 0x61, 0x44, 0x4A, 0xD4, 0xE9, - 0x1C, 0x98, 0xE7, 0x6F, 0xC4, 0xE9, 0x1C, 0x02, 0x42, 0x4A, 0xE2, 0x67, 0x5B, 0x04, 0x0A, 0xD5, - 0x20, 0x46, 0xFF, 0xF7, 0x6F, 0xFE, 0x60, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x2F, 0x46, - 0xA8, 0x46, 0xA9, 0x46, 0xF2, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x46, 0xFF, 0x00, 0x28, 0xEF, 0xD1, - 0xF2, 0xE7, 0xA3, 0x6F, 0x18, 0x04, 0x5E, 0xBF, 0x43, 0xF4, 0xC0, 0x43, 0x43, 0xF0, 0x01, 0x03, - 0xA3, 0x67, 0xA3, 0x6F, 0x19, 0x03, 0x1F, 0xD5, 0x20, 0x46, 0xFF, 0xF7, 0x57, 0xFD, 0x00, 0x28, - 0xE2, 0xD0, 0x20, 0x46, 0xFC, 0xF7, 0xD8, 0xFF, 0xA3, 0x6F, 0xB0, 0xF5, 0x80, 0x5F, 0x23, 0xF4, - 0x00, 0x23, 0xA3, 0x67, 0x1D, 0xD1, 0x4F, 0xF0, 0x20, 0x43, 0x4F, 0xF0, 0xA0, 0x32, 0x1A, 0x60, - 0xBF, 0xF3, 0x4F, 0x8F, 0x1B, 0x68, 0x93, 0x42, 0x06, 0xD0, 0xA1, 0x6F, 0x26, 0x48, 0x41, 0xF4, - 0x80, 0x31, 0xA1, 0x67, 0xFC, 0xF7, 0xE9, 0xFE, 0xA3, 0x6F, 0x9A, 0x01, 0x06, 0xD5, 0xE3, 0x69, - 0xDB, 0x04, 0x30, 0xD5, 0x65, 0x61, 0xC4, 0xE9, 0x1C, 0x98, 0xE7, 0x67, 0x26, 0x60, 0x01, 0x20, - 0xBB, 0xE7, 0xB0, 0xF5, 0x00, 0x6F, 0xEF, 0xD1, 0x4F, 0xF0, 0xE0, 0x43, 0x4F, 0xF0, 0x70, 0x32, - 0x1A, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x1B, 0x68, 0x93, 0x42, 0x05, 0xD0, 0xA1, 0x6F, 0x41, 0xF4, - 0x00, 0x31, 0xA1, 0x67, 0x15, 0x48, 0xDD, 0xE7, 0x4F, 0xF0, 0x20, 0x4A, 0x4F, 0xF0, 0xA0, 0x33, - 0xCA, 0xF8, 0x00, 0x30, 0x4F, 0xF0, 0x80, 0x32, 0x4F, 0xF0, 0x00, 0x43, 0x01, 0x20, 0x1A, 0x60, - 0xFC, 0xF7, 0xCC, 0xFE, 0xDA, 0xF8, 0x00, 0x30, 0xB3, 0xF1, 0xA0, 0x3F, 0xCC, 0xD0, 0xA1, 0x6F, - 0x41, 0xF4, 0xA0, 0x21, 0xE5, 0xE7, 0x23, 0x6D, 0x63, 0x61, 0xE3, 0x6D, 0x23, 0x67, 0x23, 0x6E, - 0x63, 0x67, 0x63, 0x6D, 0xE3, 0x67, 0xC9, 0xE7, 0x1C, 0x1A, 0x15, 0x14, 0x19, 0x16, 0x13, 0x0E, - 0x17, 0x18, 0x17, 0x18, 0x2B, 0x28, 0x28, 0x2A, 0x61, 0x34, 0x04, 0x00, 0x92, 0x34, 0x04, 0x00, - 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0x6D, 0x4E, 0x00, 0x27, 0x01, 0x24, 0xFD, 0xF7, 0xD2, 0xFF, - 0x28, 0x46, 0xFD, 0xF7, 0x45, 0xF9, 0x37, 0x60, 0x29, 0x46, 0x38, 0x46, 0xFE, 0xF7, 0x08, 0xFE, - 0x34, 0x60, 0xEB, 0x6E, 0x13, 0xF4, 0x80, 0x16, 0x11, 0xD0, 0x18, 0x03, 0x71, 0xD5, 0x28, 0x46, - 0xFE, 0xF7, 0x80, 0xF8, 0x01, 0x28, 0x04, 0x46, 0x08, 0xBF, 0x05, 0x27, 0x01, 0x37, 0x04, 0x2F, - 0xF5, 0xD9, 0x00, 0x2C, 0x6A, 0xD1, 0x01, 0x26, 0x5D, 0x48, 0xFC, 0xF7, 0x76, 0xFE, 0xEB, 0x6E, - 0x13, 0xF4, 0x00, 0x17, 0x0F, 0xD0, 0x19, 0x03, 0x62, 0xD5, 0x00, 0x27, 0x28, 0x46, 0xFE, 0xF7, - 0xEF, 0xF8, 0x01, 0x28, 0x04, 0x46, 0x08, 0xBF, 0x05, 0x27, 0x01, 0x37, 0x04, 0x2F, 0xF5, 0xD9, - 0xB4, 0xFA, 0x84, 0xF7, 0x7F, 0x09, 0xEB, 0x6E, 0x13, 0xF4, 0x80, 0x09, 0x18, 0xD0, 0x01, 0x2F, - 0x58, 0xD0, 0x1A, 0x03, 0x51, 0xD5, 0xB8, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0x4B, 0xFA, 0x01, 0x28, - 0x04, 0x46, 0x08, 0xBF, 0x4F, 0xF0, 0x05, 0x08, 0x08, 0xF1, 0x01, 0x08, 0xB8, 0xF1, 0x04, 0x0F, - 0xF2, 0xD9, 0x00, 0x2C, 0x49, 0xD1, 0x4F, 0xF0, 0x01, 0x09, 0x46, 0x48, 0xFC, 0xF7, 0x45, 0xFE, - 0xEA, 0x6E, 0x12, 0xF4, 0x00, 0x03, 0x16, 0xD0, 0x01, 0x2F, 0x45, 0xD0, 0x13, 0x03, 0x3E, 0xD5, - 0xB8, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0xF2, 0xFB, 0x01, 0x28, 0x04, 0x46, 0x08, 0xBF, 0x4F, 0xF0, - 0x05, 0x08, 0x08, 0xF1, 0x01, 0x08, 0xB8, 0xF1, 0x04, 0x0F, 0xF2, 0xD9, 0xB4, 0xBB, 0x3A, 0x48, - 0xFC, 0xF7, 0x2B, 0xFE, 0x01, 0x23, 0xE8, 0x6E, 0x3E, 0x43, 0x46, 0xEA, 0x09, 0x06, 0x1E, 0x43, - 0x10, 0xF4, 0x00, 0x20, 0x5F, 0xD0, 0x86, 0xB3, 0x34, 0x4F, 0x00, 0x26, 0x3B, 0x68, 0x01, 0x33, - 0x0A, 0x2B, 0x3B, 0x60, 0x24, 0xD1, 0x32, 0x48, 0xFC, 0xF7, 0x17, 0xFE, 0x30, 0x46, 0xBD, 0xE8, - 0xF8, 0x83, 0x28, 0x46, 0xFE, 0xF7, 0x0E, 0xF8, 0x04, 0x46, 0x92, 0xE7, 0x00, 0x26, 0x96, 0xE7, - 0x28, 0x46, 0xFE, 0xF7, 0x8D, 0xF8, 0x04, 0x46, 0xA2, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xFA, 0xF9, - 0x04, 0x46, 0xB6, 0xE7, 0x4F, 0xF0, 0x00, 0x09, 0xBA, 0xE7, 0xB9, 0x46, 0xB8, 0xE7, 0x28, 0x46, - 0xFE, 0xF7, 0xB4, 0xFB, 0x04, 0x46, 0xC9, 0xE7, 0x00, 0x23, 0xCC, 0xE7, 0x3B, 0x46, 0xCA, 0xE7, - 0x28, 0x46, 0xFF, 0xF7, 0x43, 0xFC, 0x04, 0x46, 0x3E, 0x60, 0x28, 0x46, 0xFD, 0xF7, 0xB6, 0xFB, - 0xAB, 0x6F, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, 0x02, 0x03, 0x1B, 0x05, 0x1B, 0x0D, 0x05, 0x2B, - 0x14, 0xD1, 0x01, 0x21, 0x28, 0x46, 0xFE, 0xF7, 0xCD, 0xF8, 0x02, 0x21, 0x06, 0x46, 0x28, 0x46, - 0xFE, 0xF7, 0xC8, 0xF8, 0x30, 0x40, 0x03, 0x21, 0x04, 0x40, 0x28, 0x46, 0xFE, 0xF7, 0xC2, 0xF8, - 0x00, 0x21, 0x04, 0x40, 0x28, 0x46, 0xFE, 0xF7, 0xBD, 0xF8, 0x04, 0x40, 0x0D, 0x4A, 0x20, 0x46, - 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x52, 0xF8, 0x0C, 0x3C, 0x23, 0xF0, 0x07, 0x03, - 0x42, 0xF8, 0x0C, 0x3C, 0xAB, 0xE7, 0x00, 0x2E, 0xCF, 0xD0, 0xA8, 0xE7, 0x20, 0x03, 0x82, 0x04, - 0xC5, 0x34, 0x04, 0x00, 0xDC, 0x34, 0x04, 0x00, 0xF2, 0x34, 0x04, 0x00, 0x50, 0x36, 0x04, 0x00, - 0x09, 0x35, 0x04, 0x00, 0x60, 0x00, 0x83, 0x04, 0x10, 0xB5, 0x04, 0x46, 0xFD, 0xF7, 0xD8, 0xFE, - 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, 0x0B, 0xBF, 0x00, 0x00, 0x0E, 0x4A, 0x38, 0xB5, - 0x04, 0x46, 0x13, 0x68, 0x23, 0xF0, 0x80, 0x73, 0x43, 0xF0, 0x02, 0x23, 0x13, 0x60, 0x93, 0x69, - 0x43, 0xF4, 0x00, 0x43, 0x93, 0x61, 0xFF, 0xF7, 0x6B, 0xFB, 0x08, 0x4B, 0x00, 0x22, 0x20, 0x46, - 0x1A, 0x60, 0xFF, 0xF7, 0x39, 0xFB, 0x20, 0x46, 0xFF, 0xF7, 0xDE, 0xFF, 0x05, 0x46, 0x20, 0x46, - 0xFE, 0xF7, 0x10, 0xFD, 0x28, 0x46, 0x38, 0xBD, 0x08, 0x00, 0x81, 0x04, 0x38, 0x00, 0x82, 0x04, - 0x2D, 0xE9, 0xF3, 0x41, 0x0C, 0x46, 0x8F, 0x6F, 0x48, 0x48, 0x17, 0xF4, 0x00, 0x07, 0x14, 0xBF, - 0xD1, 0xE9, 0x1C, 0x78, 0xB8, 0x46, 0x46, 0x49, 0xFC, 0xF7, 0x77, 0xFD, 0x45, 0x4A, 0x13, 0x68, - 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x93, 0x68, 0x23, 0xF0, 0x3F, 0x03, 0x93, 0x60, 0x00, 0xF0, - 0xAF, 0xF8, 0x18, 0xB9, 0x40, 0x48, 0xFC, 0xF7, 0x68, 0xFD, 0x06, 0xE0, 0x3F, 0x48, 0xFC, 0xF7, - 0x64, 0xFD, 0x20, 0x46, 0xFC, 0xF7, 0x88, 0xFF, 0x18, 0xB9, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, - 0xF0, 0x81, 0xA3, 0x6F, 0xDD, 0x07, 0x10, 0xD5, 0xA3, 0x6F, 0x18, 0x05, 0x13, 0xD4, 0x21, 0x68, - 0x37, 0x48, 0xFC, 0xF7, 0x52, 0xFD, 0x61, 0x68, 0x36, 0x48, 0xFC, 0xF7, 0x4E, 0xFD, 0x20, 0x46, - 0xFF, 0xF7, 0x9C, 0xFB, 0x68, 0xB9, 0x34, 0x48, 0xDD, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x02, 0xFE, - 0x00, 0x28, 0xE9, 0xD1, 0xE1, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x9E, 0xFB, 0x00, 0x28, 0xE6, 0xD1, - 0xDB, 0xE7, 0xE6, 0x69, 0xB3, 0x0F, 0x03, 0x2B, 0x0C, 0xD1, 0x20, 0x46, 0xFC, 0xF7, 0x0C, 0xFE, - 0xC6, 0xF3, 0x0D, 0x42, 0x05, 0x46, 0x82, 0x42, 0x08, 0xD0, 0x01, 0x46, 0x27, 0x48, 0xFC, 0xF7, - 0x2C, 0xFD, 0xCA, 0xE7, 0x02, 0x2B, 0x20, 0xD1, 0xC6, 0xF3, 0x0D, 0x45, 0x24, 0x4B, 0x29, 0x46, - 0x24, 0x48, 0x1B, 0x68, 0xA3, 0x6F, 0x00, 0x93, 0xD4, 0xE9, 0x06, 0x23, 0xFC, 0xF7, 0x1D, 0xFD, - 0xA3, 0x6F, 0x28, 0x46, 0xD9, 0x01, 0x4F, 0xF4, 0x80, 0x51, 0x41, 0xBF, 0x1E, 0x4A, 0x13, 0x68, - 0x43, 0xF0, 0x09, 0x03, 0x13, 0x60, 0xA3, 0x6F, 0x1A, 0x02, 0x48, 0xBF, 0xC4, 0xE9, 0x1C, 0x78, - 0xFC, 0xF7, 0xA6, 0xFD, 0x50, 0xB9, 0x28, 0x46, 0xA8, 0xE7, 0xB6, 0xB2, 0x20, 0x46, 0xFC, 0xF7, - 0xDB, 0xFD, 0x46, 0xEA, 0x00, 0x46, 0x05, 0x46, 0xE6, 0x61, 0xD7, 0xE7, 0xA3, 0x6F, 0x5B, 0x06, - 0x9B, 0xD4, 0x20, 0x46, 0xFF, 0xF7, 0x4A, 0xFB, 0x00, 0x28, 0xAC, 0xD0, 0x4F, 0xF4, 0x80, 0x51, - 0x28, 0x46, 0xFC, 0xF7, 0x8D, 0xFD, 0x00, 0x28, 0xE5, 0xD0, 0x8E, 0xE7, 0x26, 0x35, 0x04, 0x00, - 0x1F, 0x35, 0x04, 0x00, 0x60, 0x01, 0x00, 0x03, 0x40, 0x35, 0x04, 0x00, 0x64, 0x35, 0x04, 0x00, - 0x76, 0x35, 0x04, 0x00, 0x88, 0x35, 0x04, 0x00, 0xB9, 0x35, 0x04, 0x00, 0xD3, 0x35, 0x04, 0x00, - 0x00, 0x62, 0x00, 0x03, 0x13, 0x36, 0x04, 0x00, 0x30, 0x00, 0x82, 0x04, 0x80, 0xEA, 0x01, 0x20, - 0x08, 0x23, 0x48, 0xF2, 0x05, 0x01, 0x42, 0x00, 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x04, 0x92, 0xB2, - 0x4C, 0xBF, 0x82, 0xEA, 0x01, 0x00, 0x10, 0x46, 0x00, 0x2B, 0xF4, 0xD1, 0x70, 0x47, 0x38, 0xB5, - 0x0D, 0x46, 0x04, 0x46, 0x2C, 0x44, 0xFF, 0xF7, 0xE9, 0xFF, 0x44, 0xEA, 0x00, 0x40, 0x38, 0xBD, - 0x70, 0xB5, 0x00, 0x20, 0xFC, 0xF7, 0x0E, 0xFD, 0x01, 0x25, 0x04, 0x46, 0x29, 0x46, 0x00, 0x20, - 0xFF, 0xF7, 0xED, 0xFF, 0x84, 0x42, 0x05, 0xD0, 0x01, 0x35, 0xED, 0xB2, 0x11, 0x2D, 0xF5, 0xD1, - 0x00, 0x20, 0x0F, 0xE0, 0x01, 0x24, 0x20, 0x46, 0xFC, 0xF7, 0xFC, 0xFC, 0x29, 0x46, 0x06, 0x46, - 0x20, 0x46, 0xFF, 0xF7, 0xDC, 0xFF, 0x86, 0x42, 0xF2, 0xD1, 0x01, 0x34, 0xA4, 0xB2, 0x05, 0x2C, - 0xF1, 0xD1, 0x01, 0x20, 0x70, 0xBD, 0x00, 0x00, 0x01, 0x20, 0x51, 0xE2, 0x1E, 0xFF, 0x2F, 0x01, - 0x36, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x50, 0xE1, 0x22, 0x00, 0x00, 0x9A, 0x02, 0x00, 0x11, 0xE1, - 0x23, 0x00, 0x00, 0x0A, 0x0E, 0x02, 0x11, 0xE3, 0x81, 0x11, 0xA0, 0x01, 0x08, 0x30, 0xA0, 0x03, - 0x01, 0x30, 0xA0, 0x13, 0x01, 0x02, 0x51, 0xE3, 0x00, 0x00, 0x51, 0x31, 0x01, 0x12, 0xA0, 0x31, - 0x03, 0x32, 0xA0, 0x31, 0xFA, 0xFF, 0xFF, 0x3A, 0x02, 0x01, 0x51, 0xE3, 0x00, 0x00, 0x51, 0x31, - 0x81, 0x10, 0xA0, 0x31, 0x83, 0x30, 0xA0, 0x31, 0xFA, 0xFF, 0xFF, 0x3A, 0x00, 0x20, 0xA0, 0xE3, - 0x01, 0x00, 0x50, 0xE1, 0x01, 0x00, 0x40, 0x20, 0x03, 0x20, 0x82, 0x21, 0xA1, 0x00, 0x50, 0xE1, - 0xA1, 0x00, 0x40, 0x20, 0xA3, 0x20, 0x82, 0x21, 0x21, 0x01, 0x50, 0xE1, 0x21, 0x01, 0x40, 0x20, - 0x23, 0x21, 0x82, 0x21, 0xA1, 0x01, 0x50, 0xE1, 0xA1, 0x01, 0x40, 0x20, 0xA3, 0x21, 0x82, 0x21, - 0x00, 0x00, 0x50, 0xE3, 0x23, 0x32, 0xB0, 0x11, 0x21, 0x12, 0xA0, 0x11, 0xEF, 0xFF, 0xFF, 0x1A, - 0x02, 0x00, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x00, 0xA0, 0x03, 0x00, 0x00, 0xA0, 0x13, - 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x08, 0x51, 0xE3, 0x21, 0x18, 0xA0, 0x21, 0x10, 0x20, 0xA0, 0x23, - 0x00, 0x20, 0xA0, 0x33, 0x01, 0x0C, 0x51, 0xE3, 0x21, 0x14, 0xA0, 0x21, 0x08, 0x20, 0x82, 0x22, - 0x10, 0x00, 0x51, 0xE3, 0x21, 0x12, 0xA0, 0x21, 0x04, 0x20, 0x82, 0x22, 0x04, 0x00, 0x51, 0xE3, - 0x03, 0x20, 0x82, 0x82, 0xA1, 0x20, 0x82, 0x90, 0x30, 0x02, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, - 0x00, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xE0, 0x13, 0x59, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x51, 0xE3, - 0xFA, 0xFF, 0xFF, 0x0A, 0x03, 0x40, 0x2D, 0xE9, 0xBE, 0xFF, 0xFF, 0xEB, 0x06, 0x40, 0xBD, 0xE8, - 0x92, 0x00, 0x03, 0xE0, 0x03, 0x10, 0x41, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x51, 0xE3, - 0x43, 0x00, 0x00, 0x0A, 0x01, 0xC0, 0x20, 0xE0, 0x00, 0x10, 0x61, 0x42, 0x01, 0x20, 0x51, 0xE2, - 0x27, 0x00, 0x00, 0x0A, 0x00, 0x30, 0xB0, 0xE1, 0x00, 0x30, 0x60, 0x42, 0x01, 0x00, 0x53, 0xE1, - 0x26, 0x00, 0x00, 0x9A, 0x02, 0x00, 0x11, 0xE1, 0x28, 0x00, 0x00, 0x0A, 0x0E, 0x02, 0x11, 0xE3, - 0x81, 0x11, 0xA0, 0x01, 0x08, 0x20, 0xA0, 0x03, 0x01, 0x20, 0xA0, 0x13, 0x01, 0x02, 0x51, 0xE3, - 0x03, 0x00, 0x51, 0x31, 0x01, 0x12, 0xA0, 0x31, 0x02, 0x22, 0xA0, 0x31, 0xFA, 0xFF, 0xFF, 0x3A, - 0x02, 0x01, 0x51, 0xE3, 0x03, 0x00, 0x51, 0x31, 0x81, 0x10, 0xA0, 0x31, 0x82, 0x20, 0xA0, 0x31, - 0xFA, 0xFF, 0xFF, 0x3A, 0x00, 0x00, 0xA0, 0xE3, 0x01, 0x00, 0x53, 0xE1, 0x01, 0x30, 0x43, 0x20, - 0x02, 0x00, 0x80, 0x21, 0xA1, 0x00, 0x53, 0xE1, 0xA1, 0x30, 0x43, 0x20, 0xA2, 0x00, 0x80, 0x21, - 0x21, 0x01, 0x53, 0xE1, 0x21, 0x31, 0x43, 0x20, 0x22, 0x01, 0x80, 0x21, 0xA1, 0x01, 0x53, 0xE1, - 0xA1, 0x31, 0x43, 0x20, 0xA2, 0x01, 0x80, 0x21, 0x00, 0x00, 0x53, 0xE3, 0x22, 0x22, 0xB0, 0x11, - 0x21, 0x12, 0xA0, 0x11, 0xEF, 0xFF, 0xFF, 0x1A, 0x00, 0x00, 0x5C, 0xE3, 0x00, 0x00, 0x60, 0x42, - 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x3C, 0xE1, 0x00, 0x00, 0x60, 0x42, 0x1E, 0xFF, 0x2F, 0xE1, - 0x00, 0x00, 0xA0, 0x33, 0xCC, 0x0F, 0xA0, 0x01, 0x01, 0x00, 0x80, 0x03, 0x1E, 0xFF, 0x2F, 0xE1, - 0x01, 0x08, 0x51, 0xE3, 0x21, 0x18, 0xA0, 0x21, 0x10, 0x20, 0xA0, 0x23, 0x00, 0x20, 0xA0, 0x33, - 0x01, 0x0C, 0x51, 0xE3, 0x21, 0x14, 0xA0, 0x21, 0x08, 0x20, 0x82, 0x22, 0x10, 0x00, 0x51, 0xE3, - 0x21, 0x12, 0xA0, 0x21, 0x04, 0x20, 0x82, 0x22, 0x04, 0x00, 0x51, 0xE3, 0x03, 0x20, 0x82, 0x82, - 0xA1, 0x20, 0x82, 0x90, 0x00, 0x00, 0x5C, 0xE3, 0x33, 0x02, 0xA0, 0xE1, 0x00, 0x00, 0x60, 0x42, - 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x50, 0xE3, 0x02, 0x01, 0xE0, 0xC3, 0x02, 0x01, 0xA0, 0xB3, - 0x07, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x51, 0xE3, 0xF9, 0xFF, 0xFF, 0x0A, 0x03, 0x40, 0x2D, 0xE9, - 0xB3, 0xFF, 0xFF, 0xEB, 0x06, 0x40, 0xBD, 0xE8, 0x92, 0x00, 0x03, 0xE0, 0x03, 0x10, 0x41, 0xE0, - 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x53, 0xE3, 0x00, 0x00, 0x52, 0x03, - 0x04, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x51, 0xE3, 0x00, 0x00, 0x50, 0x03, 0x00, 0x10, 0xE0, 0x13, - 0x00, 0x00, 0xE0, 0x13, 0xF6, 0xFF, 0xFF, 0xEA, 0x08, 0xD0, 0x4D, 0xE2, 0x00, 0x60, 0x2D, 0xE9, - 0x03, 0x00, 0x00, 0xEB, 0x04, 0xE0, 0x9D, 0xE5, 0x08, 0xD0, 0x8D, 0xE2, 0x0C, 0x00, 0xBD, 0xE8, - 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x47, 0x2D, 0xE9, 0x03, 0x60, 0xA0, 0xE1, 0x02, 0x00, 0x50, 0xE1, - 0x06, 0x30, 0xD1, 0xE0, 0x00, 0x40, 0xA0, 0xE1, 0x00, 0x00, 0xA0, 0x33, 0x01, 0x50, 0xA0, 0xE1, - 0x20, 0x70, 0x9D, 0xE5, 0x00, 0x10, 0xA0, 0x31, 0x3B, 0x00, 0x00, 0x3A, 0x06, 0x10, 0xA0, 0xE1, - 0x02, 0x00, 0xA0, 0xE1, 0x02, 0x80, 0xA0, 0xE1, 0x3B, 0x00, 0x00, 0xEB, 0x05, 0x10, 0xA0, 0xE1, - 0x00, 0x90, 0xA0, 0xE1, 0x04, 0x00, 0xA0, 0xE1, 0x37, 0x00, 0x00, 0xEB, 0x00, 0xC0, 0x49, 0xE0, - 0x16, 0x3C, 0xA0, 0xE1, 0x20, 0x60, 0x4C, 0xE2, 0x18, 0x36, 0x83, 0xE1, 0x20, 0xE0, 0x6C, 0xE2, - 0x18, 0x2C, 0xA0, 0xE1, 0x38, 0x3E, 0x83, 0xE1, 0x02, 0x00, 0x54, 0xE1, 0x03, 0x10, 0xD5, 0xE0, - 0x00, 0x00, 0xA0, 0x33, 0x00, 0x10, 0xA0, 0x31, 0x05, 0x00, 0x00, 0x3A, 0x01, 0x00, 0xA0, 0xE3, - 0x02, 0x40, 0x54, 0xE0, 0x10, 0x16, 0xA0, 0xE1, 0x30, 0x1E, 0x81, 0xE1, 0x03, 0x50, 0xC5, 0xE0, - 0x10, 0x0C, 0xA0, 0xE1, 0x00, 0x00, 0x5C, 0xE3, 0x1F, 0x00, 0x00, 0x0A, 0xA2, 0x20, 0xA0, 0xE1, - 0x83, 0x2F, 0x82, 0xE1, 0x0C, 0x80, 0xA0, 0xE1, 0xA3, 0x30, 0xA0, 0xE1, 0x07, 0x00, 0x00, 0xEA, - 0x02, 0x40, 0x54, 0xE0, 0x03, 0x50, 0xC5, 0xE0, 0x04, 0x40, 0x94, 0xE0, 0x05, 0x50, 0xA5, 0xE0, - 0x01, 0x40, 0x94, 0xE2, 0x00, 0x50, 0xA5, 0xE2, 0x01, 0x80, 0x58, 0xE2, 0x06, 0x00, 0x00, 0x0A, - 0x02, 0x00, 0x54, 0xE1, 0x03, 0x90, 0xD5, 0xE0, 0xF4, 0xFF, 0xFF, 0x2A, 0x04, 0x40, 0x94, 0xE0, - 0x05, 0x50, 0xA5, 0xE0, 0x01, 0x80, 0x58, 0xE2, 0xF8, 0xFF, 0xFF, 0x1A, 0x04, 0x00, 0x90, 0xE0, - 0x34, 0x4C, 0xA0, 0xE1, 0x15, 0x4E, 0x84, 0xE1, 0x35, 0x46, 0x84, 0xE1, 0x05, 0x10, 0xA1, 0xE0, - 0x35, 0x5C, 0xA0, 0xE1, 0x15, 0x3C, 0xA0, 0xE1, 0x14, 0x36, 0x83, 0xE1, 0x14, 0xCC, 0xA0, 0xE1, - 0x34, 0x3E, 0x83, 0xE1, 0x0C, 0x00, 0x50, 0xE0, 0x03, 0x10, 0xC1, 0xE0, 0x00, 0x00, 0x57, 0xE3, - 0x30, 0x00, 0x87, 0x18, 0xF0, 0x47, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x10, 0x40, 0x2D, 0xE9, - 0x00, 0x00, 0x51, 0xE3, 0x02, 0x00, 0x00, 0x1A, 0x05, 0x00, 0x00, 0xEB, 0x20, 0x00, 0x80, 0xE2, - 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0xA0, 0xE1, 0x01, 0x00, 0x00, 0xEB, 0x10, 0x40, 0xBD, 0xE8, - 0x1E, 0xFF, 0x2F, 0xE1, 0x1C, 0x10, 0xA0, 0xE3, 0x01, 0x08, 0x50, 0xE3, 0x20, 0x08, 0xA0, 0x21, - 0x10, 0x10, 0x41, 0x22, 0x01, 0x0C, 0x50, 0xE3, 0x20, 0x04, 0xA0, 0x21, 0x08, 0x10, 0x41, 0x22, - 0x10, 0x00, 0x50, 0xE3, 0x20, 0x02, 0xA0, 0x21, 0x04, 0x10, 0x41, 0x22, 0x08, 0x20, 0x8F, 0xE2, - 0x00, 0x00, 0xD2, 0xE7, 0x01, 0x00, 0x80, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0x03, 0x02, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFE, 0xFF, 0x7F, - 0x01, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x00, 0x00, 0x0C, 0x05, 0x0A, 0x0D, 0xFA, 0x30, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, - 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x48, - 0x33, 0x33, 0x27, 0x00, 0x1F, 0x18, 0x1C, 0x20, 0x13, 0x15, 0x15, 0x13, 0x21, 0x75, 0x00, 0x00, - 0x1F, 0x21, 0x23, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x0F, 0x0F, 0x0F, 0x0F, 0x5A, 0x5A, 0x5A, 0x5A, 0x55, 0x55, 0x55, 0x55, 0x3F, 0x00, 0x00, 0x00, + 0x5D, 0x4B, 0x1B, 0x68, 0x5D, 0x4B, 0x32, 0x68, 0x56, 0xF8, 0x48, 0x1C, 0x32, 0x68, 0x52, 0x1A, + 0x06, 0x2A, 0x0A, 0xD8, 0x18, 0x46, 0x51, 0x46, 0xFD, 0xF7, 0x1E, 0xFE, 0xD8, 0xF8, 0x6C, 0x20, + 0x56, 0x4B, 0x12, 0xF0, 0x80, 0x5F, 0x08, 0xBF, 0x01, 0x24, 0x04, 0x36, 0x0A, 0xF1, 0x01, 0x0A, + 0x5E, 0x45, 0xE8, 0xD1, 0x2B, 0x68, 0x23, 0xF0, 0x60, 0x03, 0x2B, 0x60, 0xD8, 0xF8, 0x1C, 0x30, + 0xDA, 0x04, 0x32, 0xD5, 0x3B, 0x68, 0x23, 0xF0, 0x0C, 0x03, 0x43, 0xF0, 0x04, 0x03, 0x3B, 0x60, + 0x2B, 0x68, 0x43, 0xF0, 0x10, 0x03, 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x20, 0x03, 0x2B, 0x60, + 0xD9, 0xF8, 0x00, 0x30, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, 0xF9, 0xD1, 0xD9, 0xF8, 0x00, 0x30, + 0x13, 0xF0, 0x0C, 0x0F, 0x03, 0xD0, 0x01, 0x24, 0x14, 0x48, 0xFD, 0xF7, 0xED, 0xFD, 0xD8, 0xF8, + 0x1C, 0x30, 0xDB, 0x07, 0x0D, 0xD4, 0x12, 0x4A, 0x13, 0x68, 0x03, 0xF0, 0x03, 0x03, 0x03, 0x2B, + 0xFA, 0xD1, 0x13, 0x68, 0x13, 0xF0, 0x0C, 0x0F, 0x03, 0xD0, 0x01, 0x24, 0x0D, 0x48, 0xFD, 0xF7, + 0xDB, 0xFD, 0x2B, 0x68, 0x23, 0xF0, 0x60, 0x03, 0x2B, 0x60, 0x3B, 0x68, 0x84, 0xF0, 0x01, 0x00, + 0x23, 0xF0, 0x0C, 0x03, 0x3B, 0x60, 0xBD, 0xE8, 0xF8, 0x8F, 0x00, 0xBF, 0x34, 0x01, 0x83, 0x04, + 0x98, 0x01, 0x83, 0x04, 0x90, 0x01, 0x83, 0x04, 0xE0, 0x08, 0x83, 0x04, 0xA9, 0x37, 0x04, 0x00, + 0xE0, 0x0A, 0x83, 0x04, 0xCE, 0x37, 0x04, 0x00, 0xF0, 0x08, 0x83, 0x04, 0x38, 0x09, 0x83, 0x04, + 0xF4, 0x08, 0x83, 0x04, 0xF8, 0x08, 0x83, 0x04, 0xFC, 0x08, 0x83, 0x04, 0x00, 0x09, 0x83, 0x04, + 0x04, 0x09, 0x83, 0x04, 0x08, 0x09, 0x83, 0x04, 0x0C, 0x09, 0x83, 0x04, 0x10, 0x09, 0x83, 0x04, + 0xF4, 0x37, 0x04, 0x00, 0x14, 0x09, 0x83, 0x04, 0x18, 0x09, 0x83, 0x04, 0x1C, 0x09, 0x83, 0x04, + 0x20, 0x09, 0x83, 0x04, 0x24, 0x09, 0x83, 0x04, 0x28, 0x09, 0x83, 0x04, 0x2C, 0x09, 0x83, 0x04, + 0x30, 0x09, 0x83, 0x04, 0x34, 0x09, 0x83, 0x04, 0x1D, 0x38, 0x04, 0x00, 0xF0, 0x0A, 0x83, 0x04, + 0x38, 0x0B, 0x83, 0x04, 0xF4, 0x0A, 0x83, 0x04, 0xF8, 0x0A, 0x83, 0x04, 0xFC, 0x0A, 0x83, 0x04, + 0x00, 0x0B, 0x83, 0x04, 0x04, 0x0B, 0x83, 0x04, 0x08, 0x0B, 0x83, 0x04, 0x0C, 0x0B, 0x83, 0x04, + 0x10, 0x0B, 0x83, 0x04, 0x46, 0x38, 0x04, 0x00, 0x14, 0x0B, 0x83, 0x04, 0x18, 0x0B, 0x83, 0x04, + 0x1C, 0x0B, 0x83, 0x04, 0x20, 0x0B, 0x83, 0x04, 0x24, 0x0B, 0x83, 0x04, 0x28, 0x0B, 0x83, 0x04, + 0x2C, 0x0B, 0x83, 0x04, 0x30, 0x0B, 0x83, 0x04, 0x34, 0x0B, 0x83, 0x04, 0x6F, 0x38, 0x04, 0x00, + 0x5C, 0x09, 0x83, 0x04, 0x80, 0x09, 0x83, 0x04, 0x5C, 0x0B, 0x83, 0x04, 0x80, 0x0B, 0x83, 0x04, + 0x0A, 0x4B, 0x0B, 0x49, 0x1A, 0x68, 0x42, 0xF0, 0x20, 0x02, 0x1A, 0x60, 0x0A, 0x68, 0xD2, 0x07, + 0xFC, 0xD5, 0x1A, 0x68, 0x22, 0xF0, 0x20, 0x02, 0x1A, 0x60, 0xFF, 0x23, 0x05, 0x4A, 0x13, 0x60, + 0x13, 0x64, 0xC2, 0xF8, 0x80, 0x30, 0xC2, 0xF8, 0xC0, 0x30, 0x70, 0x47, 0x50, 0x00, 0x83, 0x04, + 0xAC, 0x01, 0x83, 0x04, 0x94, 0x03, 0x83, 0x04, 0x03, 0x4A, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, + 0x18, 0x43, 0x10, 0x60, 0x70, 0x47, 0x00, 0xBF, 0x60, 0x00, 0x82, 0x04, 0x10, 0xB5, 0x00, 0x23, + 0x06, 0x4C, 0x01, 0x46, 0x18, 0x46, 0x23, 0x60, 0xFF, 0xF7, 0xEE, 0xFF, 0x04, 0x4A, 0x01, 0x23, + 0x23, 0x60, 0x13, 0x68, 0xDB, 0x07, 0xFC, 0xD5, 0x10, 0xBD, 0x00, 0xBF, 0x20, 0x03, 0x82, 0x04, + 0x24, 0x03, 0x82, 0x04, 0x01, 0x46, 0x08, 0xB5, 0x01, 0x20, 0xFF, 0xF7, 0xDD, 0xFF, 0x06, 0x4B, + 0x00, 0x22, 0x06, 0x49, 0x1A, 0x60, 0x0A, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x0A, 0x60, 0x1A, 0x68, + 0x42, 0xF0, 0x20, 0x02, 0x1A, 0x60, 0x08, 0xBD, 0x30, 0x00, 0x82, 0x04, 0xB0, 0x01, 0x82, 0x04, + 0x83, 0x6F, 0x9B, 0x00, 0x41, 0xBF, 0x03, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x04, 0x03, 0x13, 0x60, + 0x70, 0x47, 0x00, 0xBF, 0xC0, 0x01, 0x82, 0x04, 0x0E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, + 0x13, 0x60, 0x52, 0xF8, 0x20, 0x3C, 0x43, 0xF0, 0x40, 0x43, 0x42, 0xF8, 0x20, 0x3C, 0x02, 0xF5, + 0xFF, 0x52, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, 0x13, 0x60, 0x02, 0xF5, 0x80, 0x52, 0x13, 0x68, + 0x43, 0xF0, 0x40, 0x43, 0x13, 0x60, 0x02, 0xF5, 0x80, 0x52, 0x13, 0x68, 0x43, 0xF0, 0x40, 0x43, + 0x13, 0x60, 0x70, 0x47, 0xA0, 0x01, 0x82, 0x04, 0x43, 0x68, 0x18, 0x21, 0x2D, 0xE9, 0xF0, 0x4F, + 0xA3, 0xB0, 0x08, 0x26, 0x4F, 0xF0, 0x0E, 0x0A, 0x03, 0x27, 0x83, 0x46, 0x00, 0x93, 0x3D, 0x46, + 0xBB, 0x4B, 0xB8, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x1B, 0x68, 0x12, 0x97, 0xCD, 0xF8, 0x28, 0x90, + 0x01, 0x97, 0x1B, 0x0A, 0xCD, 0xF8, 0x24, 0x90, 0x01, 0x33, 0xDB, 0xB2, 0x4B, 0x43, 0x1B, 0x93, + 0x9B, 0x08, 0x21, 0x93, 0x04, 0x23, 0x05, 0x93, 0xCD, 0xE9, 0x1E, 0x33, 0x08, 0x23, 0x1D, 0x93, + 0x20, 0x93, 0x01, 0x23, 0x0D, 0x93, 0x02, 0x23, 0x1A, 0x93, 0x04, 0x23, 0x02, 0x93, 0x04, 0x93, + 0x0C, 0x93, 0x1B, 0x23, 0xCD, 0xE9, 0x18, 0x36, 0x0C, 0x23, 0x11, 0x93, 0x80, 0x23, 0x17, 0x93, + 0x62, 0x23, 0x10, 0x93, 0x0A, 0x23, 0x0B, 0x93, 0x10, 0x23, 0xCD, 0xE9, 0x15, 0x3A, 0x14, 0x23, + 0x14, 0x93, 0x00, 0x23, 0x02, 0x26, 0x08, 0x93, 0x01, 0x23, 0x13, 0x96, 0x0F, 0x96, 0x03, 0x97, + 0x0E, 0x97, 0xCD, 0xE9, 0x06, 0x33, 0x7B, 0x1C, 0x02, 0xD1, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0xDB, 0xF8, 0x78, 0x30, 0x1C, 0x93, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, 0x02, 0x03, 0x1B, 0x05, + 0x1B, 0x0D, 0x05, 0x2B, 0x1C, 0x9B, 0x18, 0xBF, 0x00, 0x27, 0x13, 0xF0, 0x04, 0x0A, 0x68, 0xD0, + 0xDB, 0xF8, 0x60, 0x10, 0x00, 0x2F, 0x50, 0xD1, 0x01, 0xF0, 0x1F, 0x01, 0x1B, 0x98, 0x01, 0x31, + 0xBA, 0x46, 0x01, 0xF0, 0x26, 0xEB, 0x04, 0x46, 0x00, 0x9B, 0x03, 0x2B, 0x5D, 0xD1, 0x21, 0x46, + 0x32, 0x20, 0xFE, 0xF7, 0x3D, 0xF8, 0xC3, 0xB2, 0x21, 0x46, 0x0A, 0x20, 0x15, 0x93, 0xFE, 0xF7, + 0x37, 0xF8, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x01, 0x90, 0x0F, 0x20, + 0xFE, 0xF7, 0x2E, 0xF8, 0xC3, 0xB2, 0x21, 0x46, 0x35, 0x20, 0x0A, 0x93, 0xFE, 0xF7, 0x28, 0xF8, + 0xC3, 0xB2, 0x21, 0x46, 0x08, 0x20, 0x14, 0x93, 0xFE, 0xF7, 0x22, 0xF8, 0xC5, 0xB2, 0x21, 0x46, + 0x26, 0x20, 0x02, 0x2D, 0x38, 0xBF, 0x02, 0x25, 0xFE, 0xF7, 0x1A, 0xF8, 0xC3, 0xB2, 0x21, 0x46, + 0x41, 0xF6, 0x78, 0x60, 0x16, 0x93, 0xA8, 0x46, 0xFE, 0xF7, 0x12, 0xF8, 0x21, 0x46, 0xC0, 0xF3, + 0x4F, 0x13, 0x4F, 0xF4, 0xAF, 0x70, 0x10, 0x93, 0xFE, 0xF7, 0x0A, 0xF8, 0x83, 0xB2, 0x21, 0x46, + 0x4F, 0xF4, 0xB4, 0x70, 0x17, 0x93, 0xFE, 0xF7, 0x03, 0xF8, 0xDD, 0xF8, 0x28, 0x90, 0xC0, 0xF3, + 0x47, 0x13, 0x1F, 0x93, 0x0B, 0x95, 0x02, 0x23, 0x74, 0xE0, 0x01, 0x2F, 0x0A, 0xD1, 0xC1, 0xF3, + 0x04, 0x21, 0x01, 0x31, 0x1B, 0x98, 0x01, 0xF0, 0xD4, 0xEA, 0x04, 0x46, 0x7B, 0x1C, 0x4F, 0xEA, + 0x03, 0x3A, 0xA9, 0xE7, 0x02, 0x2F, 0x0C, 0xBF, 0xC1, 0xF3, 0x04, 0x41, 0xC1, 0xF3, 0x04, 0x61, + 0xEF, 0xE7, 0x21, 0x9C, 0x00, 0x2F, 0x9F, 0xD0, 0xF0, 0xE7, 0x00, 0x9B, 0x04, 0x2B, 0x67, 0xD1, + 0x21, 0x46, 0x23, 0x20, 0xFD, 0xF7, 0xDC, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x08, 0x20, 0x15, 0x93, + 0xFD, 0xF7, 0xD6, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x01, 0x90, + 0x06, 0x20, 0xFD, 0xF7, 0xCD, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, + 0x0B, 0x90, 0x0A, 0x20, 0xFD, 0xF7, 0xC4, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x08, 0x28, 0x38, 0xBF, + 0x08, 0x20, 0x1D, 0x90, 0x0F, 0x20, 0xFD, 0xF7, 0xBB, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x31, 0x20, + 0x0A, 0x93, 0xFD, 0xF7, 0xB5, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x03, 0x20, 0x14, 0x93, 0xFD, 0xF7, + 0xAF, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x22, 0x20, 0x00, 0x2B, 0x08, 0xBF, 0x01, 0x23, 0x0D, 0x93, + 0xFD, 0xF7, 0xA6, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x41, 0xF6, 0x78, 0x60, 0x16, 0x93, 0xFD, 0xF7, + 0x9F, 0xFF, 0x21, 0x46, 0xC0, 0xF3, 0x4F, 0x13, 0x4F, 0xF4, 0xAF, 0x70, 0x10, 0x93, 0xFD, 0xF7, + 0x97, 0xFF, 0x83, 0xB2, 0x21, 0x46, 0x4F, 0xF4, 0xB4, 0x70, 0x17, 0x93, 0xFD, 0xF7, 0x90, 0xFF, + 0xC0, 0xF3, 0x47, 0x13, 0xDD, 0xF8, 0x04, 0x80, 0x1F, 0x93, 0x0B, 0x9B, 0xDD, 0xF8, 0x28, 0x90, + 0x1A, 0x93, 0x03, 0x23, 0x13, 0x93, 0x00, 0x9B, 0xD9, 0x1E, 0x05, 0x29, 0x00, 0xF2, 0x15, 0x81, + 0xDF, 0xE8, 0x11, 0xF0, 0x9A, 0x01, 0xBA, 0x00, 0x13, 0x01, 0x13, 0x01, 0xD9, 0x01, 0xFC, 0x01, + 0x00, 0x9B, 0x07, 0x2B, 0x4E, 0xD1, 0x21, 0x46, 0x32, 0x20, 0xFD, 0xF7, 0x71, 0xFF, 0xC0, 0xB2, + 0x21, 0x46, 0x04, 0x28, 0x38, 0xBF, 0x04, 0x20, 0x15, 0x90, 0x0A, 0x20, 0xFD, 0xF7, 0x68, 0xFF, + 0xC3, 0xB2, 0x21, 0x46, 0x18, 0x20, 0x00, 0x2B, 0x08, 0xBF, 0x01, 0x23, 0x01, 0x93, 0xFD, 0xF7, + 0x5F, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x0A, 0x90, 0x46, 0x20, + 0xFD, 0xF7, 0x56, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x08, 0x20, 0x14, 0x93, 0xFD, 0xF7, 0x50, 0xFF, + 0xC5, 0xB2, 0x21, 0x46, 0x1B, 0x20, 0x02, 0x2D, 0x38, 0xBF, 0x02, 0x25, 0xFD, 0xF7, 0x48, 0xFF, + 0x21, 0x46, 0x5F, 0xFA, 0x80, 0xF9, 0x2A, 0x20, 0xFD, 0xF7, 0x42, 0xFF, 0xC3, 0xB2, 0x21, 0x46, + 0x40, 0xF6, 0x3C, 0x70, 0x16, 0x93, 0xA8, 0x46, 0xFD, 0xF7, 0x3A, 0xFF, 0x21, 0x46, 0xC0, 0xF3, + 0x4F, 0x13, 0xD2, 0x20, 0x10, 0x93, 0xFD, 0xF7, 0x33, 0xFF, 0x83, 0xB2, 0x21, 0x46, 0xDC, 0x20, + 0x17, 0x93, 0xFD, 0xF7, 0x2D, 0xFF, 0xC3, 0xB2, 0x0B, 0x95, 0x1E, 0x93, 0x2B, 0xE7, 0x00, 0xBF, + 0x10, 0x10, 0x00, 0x03, 0x00, 0x9B, 0x08, 0x2B, 0x9D, 0xD1, 0x21, 0x46, 0x28, 0x20, 0xFD, 0xF7, + 0x1F, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x0A, 0x20, 0x15, 0x93, 0xFD, 0xF7, 0x19, 0xFF, 0x5F, 0xFA, + 0x80, 0xF8, 0x21, 0x46, 0x12, 0x20, 0x43, 0x46, 0x02, 0x2B, 0x38, 0xBF, 0x02, 0x23, 0x01, 0x93, + 0xFD, 0xF7, 0x0E, 0xFF, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, 0x0A, 0x90, + 0x41, 0x20, 0xFD, 0xF7, 0x05, 0xFF, 0xC3, 0xB2, 0x21, 0x46, 0x00, 0x98, 0x14, 0x93, 0xFD, 0xF7, + 0xFF, 0xFE, 0xC5, 0xB2, 0x02, 0x2D, 0x2B, 0x46, 0x38, 0xBF, 0x02, 0x23, 0x0B, 0x93, 0x1C, 0x9B, + 0xD8, 0x00, 0x05, 0xD5, 0x21, 0x46, 0x0C, 0x20, 0xFD, 0xF7, 0xF2, 0xFE, 0x5F, 0xFA, 0x80, 0xF8, + 0xB8, 0xF1, 0x04, 0x0F, 0x21, 0x46, 0x38, 0xBF, 0x4F, 0xF0, 0x04, 0x08, 0x15, 0x20, 0x04, 0x2D, + 0x38, 0xBF, 0x04, 0x25, 0xFD, 0xF7, 0xE4, 0xFE, 0x21, 0x46, 0x5F, 0xFA, 0x80, 0xF9, 0x2A, 0x20, + 0xFD, 0xF7, 0xDE, 0xFE, 0xC3, 0xB2, 0x21, 0x46, 0x4F, 0xF4, 0x74, 0x60, 0x16, 0x93, 0xFD, 0xF7, + 0xD7, 0xFE, 0x21, 0x46, 0xC0, 0xF3, 0x4F, 0x13, 0x4F, 0xF4, 0x8C, 0x70, 0x10, 0x93, 0xFD, 0xF7, + 0xCF, 0xFE, 0x83, 0xB2, 0x21, 0x46, 0x4F, 0xF4, 0x91, 0x70, 0x17, 0x93, 0xFD, 0xF7, 0xC8, 0xFE, + 0xC3, 0xB2, 0x1E, 0x93, 0x04, 0x23, 0x3D, 0xE7, 0x21, 0x46, 0x0F, 0x20, 0xFD, 0xF7, 0xC0, 0xFE, + 0xC0, 0xB2, 0x21, 0x46, 0x0C, 0x28, 0x38, 0xBF, 0x0C, 0x20, 0x09, 0x90, 0x05, 0x20, 0xFD, 0xF7, + 0xB7, 0xFE, 0xC6, 0xB2, 0x21, 0x46, 0x0A, 0x20, 0x02, 0x2E, 0x38, 0xBF, 0x02, 0x26, 0xFD, 0xF7, + 0xAF, 0xFE, 0xC0, 0xB2, 0x71, 0x1C, 0xCB, 0xB2, 0x21, 0x46, 0x03, 0x28, 0x38, 0xBF, 0x03, 0x20, + 0x12, 0x93, 0x04, 0x90, 0xAA, 0x20, 0xFD, 0xF7, 0xA3, 0xFE, 0x21, 0x46, 0xC0, 0xF3, 0x47, 0x13, + 0xBC, 0x48, 0x05, 0x93, 0xFD, 0xF7, 0x9C, 0xFE, 0xDB, 0xF8, 0x28, 0x10, 0xC0, 0xF3, 0x87, 0x23, + 0x18, 0x93, 0xB9, 0xF1, 0x04, 0x0F, 0x94, 0xBF, 0xC9, 0xF1, 0x09, 0x05, 0x04, 0x25, 0x21, 0xF0, + 0x38, 0x01, 0x98, 0xBF, 0xED, 0xB2, 0x41, 0xF0, 0x08, 0x01, 0xCB, 0xF8, 0x28, 0x10, 0x08, 0xF1, + 0x07, 0x01, 0xCB, 0xB2, 0x4F, 0xF4, 0xA4, 0x60, 0xCB, 0xF8, 0x20, 0x00, 0x19, 0x93, 0x0D, 0x9B, + 0xD9, 0x1D, 0xCB, 0xB2, 0x20, 0x93, 0x04, 0x9B, 0x02, 0x93, 0x05, 0x23, 0x0C, 0x93, 0x0E, 0x23, + 0x11, 0x93, 0x04, 0x23, 0x0F, 0x93, 0x00, 0x23, 0x08, 0x93, 0x05, 0x23, 0x03, 0x93, 0x07, 0x23, + 0x0E, 0x93, 0x06, 0x23, 0x07, 0x93, 0x0A, 0x23, 0x06, 0x93, 0xDD, 0xE9, 0x15, 0x23, 0xA2, 0x48, + 0x43, 0xEA, 0x02, 0x41, 0x11, 0x9B, 0x0B, 0x9A, 0x41, 0xEA, 0x03, 0x61, 0x18, 0x9B, 0x41, 0xEA, + 0x03, 0x21, 0x9E, 0x4B, 0x4A, 0xF8, 0x03, 0x10, 0x14, 0x9B, 0x43, 0xEA, 0x02, 0x41, 0x9C, 0x4B, + 0x41, 0xEA, 0x05, 0x21, 0x4A, 0xF8, 0x03, 0x10, 0x0E, 0x9B, 0x19, 0x04, 0x03, 0x9B, 0x41, 0xEA, + 0x03, 0x61, 0x19, 0x9B, 0x19, 0x43, 0x0C, 0x9B, 0x41, 0xEA, 0x03, 0x21, 0x95, 0x4B, 0x4A, 0xF8, + 0x03, 0x10, 0x0F, 0x9B, 0x19, 0x03, 0x08, 0x9B, 0x41, 0xEA, 0x03, 0x51, 0x09, 0x9B, 0x19, 0x43, + 0x91, 0x4B, 0x4A, 0xF8, 0x03, 0x10, 0x13, 0x9B, 0x19, 0x04, 0x0A, 0x9B, 0x41, 0xEA, 0x03, 0x61, + 0x01, 0x9B, 0x41, 0xEA, 0x09, 0x01, 0x41, 0xEA, 0x03, 0x21, 0x8C, 0x4B, 0x4A, 0xF8, 0x03, 0x10, + 0x02, 0x9B, 0x19, 0x04, 0x04, 0x9B, 0x41, 0xEA, 0x03, 0x61, 0x12, 0x9B, 0x31, 0x43, 0x41, 0xEA, + 0x03, 0x21, 0x87, 0x4B, 0x4A, 0xF8, 0x03, 0x10, 0x91, 0x1C, 0x86, 0x4B, 0x41, 0xF0, 0x00, 0x71, + 0x41, 0xF4, 0x00, 0x31, 0x1A, 0x9A, 0x4A, 0xF8, 0x03, 0x10, 0x1F, 0x9B, 0x43, 0xF4, 0x80, 0x51, + 0x05, 0x9B, 0x41, 0xEA, 0x03, 0x61, 0x41, 0xEA, 0x03, 0x41, 0x20, 0x9B, 0x4A, 0xF8, 0x00, 0x10, + 0x04, 0x30, 0x43, 0xEA, 0x02, 0x21, 0x41, 0xF4, 0x00, 0x31, 0x4A, 0xF8, 0x00, 0x10, 0x7A, 0x49, + 0x7A, 0x48, 0x4A, 0xF8, 0x01, 0x00, 0x04, 0x31, 0x79, 0x48, 0x1D, 0x9B, 0x4A, 0xF8, 0x01, 0x00, + 0x04, 0x31, 0x78, 0x48, 0x4A, 0xF8, 0x01, 0x30, 0x04, 0x31, 0x1E, 0x9B, 0x4A, 0xF8, 0x01, 0x00, + 0x04, 0x31, 0x4A, 0xF8, 0x01, 0x30, 0x74, 0x4B, 0x18, 0x68, 0x00, 0x9B, 0x07, 0x2B, 0x40, 0xF0, + 0xE7, 0x80, 0x20, 0xF0, 0x43, 0x40, 0x20, 0xF4, 0x7F, 0x00, 0x40, 0xF4, 0x9E, 0x00, 0x6F, 0x49, + 0x01, 0x40, 0x41, 0xF4, 0x89, 0x71, 0xE2, 0xE0, 0x21, 0x46, 0x08, 0x20, 0xFD, 0xF7, 0xE0, 0xFD, + 0x21, 0x46, 0x06, 0x46, 0x0A, 0x20, 0xFD, 0xF7, 0xDB, 0xFD, 0xC3, 0xB2, 0x02, 0x2B, 0x04, 0x93, + 0x2F, 0xD9, 0xF6, 0xB2, 0x02, 0x2E, 0x38, 0xBF, 0x02, 0x26, 0x71, 0x1C, 0x20, 0x46, 0xCB, 0xB2, + 0x0F, 0x21, 0x12, 0x93, 0x01, 0xF0, 0x36, 0xE9, 0xDB, 0xF8, 0x28, 0x10, 0xC3, 0xB2, 0x41, 0xF6, + 0x14, 0x70, 0x18, 0x93, 0x21, 0xF0, 0x38, 0x01, 0xCB, 0xF8, 0x20, 0x00, 0x41, 0xF0, 0x20, 0x01, + 0xCB, 0xF8, 0x28, 0x10, 0x00, 0x21, 0xCB, 0xF8, 0x2C, 0x10, 0x05, 0xEB, 0x09, 0x01, 0x08, 0x29, + 0x08, 0xF1, 0x07, 0x01, 0xCB, 0xB2, 0xDC, 0xBF, 0xC9, 0xF1, 0x09, 0x05, 0xED, 0xB2, 0x19, 0x93, + 0x04, 0x9B, 0x02, 0x93, 0x05, 0x23, 0x0C, 0x93, 0x0E, 0x23, 0x11, 0x93, 0x0C, 0x23, 0x09, 0x93, + 0x2F, 0xE7, 0x06, 0x26, 0xD1, 0xE7, 0x83, 0x23, 0x1C, 0x21, 0xCB, 0xE9, 0x09, 0x31, 0x00, 0x21, + 0xCB, 0xF8, 0x20, 0x10, 0x08, 0xF1, 0x09, 0x01, 0xCB, 0xB2, 0x03, 0x26, 0x19, 0x93, 0x05, 0x23, + 0x02, 0x93, 0x04, 0x93, 0x12, 0x93, 0x0D, 0x23, 0x0C, 0x93, 0x18, 0x23, 0x18, 0x93, 0x10, 0x23, + 0x11, 0x93, 0x0C, 0x23, 0x09, 0x93, 0x05, 0x23, 0x0F, 0x93, 0x08, 0x93, 0x04, 0x23, 0x03, 0x93, + 0x07, 0x23, 0x0E, 0x93, 0x06, 0x23, 0x07, 0x93, 0x0C, 0x23, 0x15, 0xE7, 0x21, 0x46, 0x0E, 0x20, + 0xFD, 0xF7, 0x7E, 0xFD, 0xC0, 0xB2, 0x21, 0x46, 0x05, 0x28, 0x38, 0xBF, 0x05, 0x20, 0x08, 0x90, + 0x0F, 0x20, 0xFD, 0xF7, 0x75, 0xFD, 0xC6, 0xB2, 0x21, 0x46, 0x02, 0x20, 0x02, 0x2E, 0x38, 0xBF, + 0x02, 0x26, 0xFD, 0xF7, 0x6D, 0xFD, 0xC0, 0xB2, 0x21, 0x46, 0x02, 0x28, 0x38, 0xBF, 0x02, 0x20, + 0x04, 0x90, 0x05, 0x20, 0xFD, 0xF7, 0x64, 0xFD, 0x10, 0x9B, 0xC0, 0xB2, 0x02, 0x28, 0x38, 0xBF, + 0x02, 0x20, 0x03, 0xEB, 0xC3, 0x01, 0x02, 0x90, 0x04, 0x20, 0xC1, 0xF3, 0x47, 0x13, 0x21, 0x46, + 0x18, 0x93, 0xFD, 0xF7, 0x55, 0xFD, 0x05, 0x46, 0x21, 0x46, 0x01, 0x20, 0x11, 0x35, 0xFD, 0xF7, + 0x4F, 0xFD, 0x2D, 0x1A, 0x1B, 0x21, 0xEB, 0xB2, 0x34, 0x24, 0xCB, 0xE9, 0x09, 0x41, 0x08, 0xF1, + 0x0E, 0x01, 0x0C, 0x93, 0xCB, 0xB2, 0x12, 0x96, 0x04, 0x25, 0x19, 0x93, 0x1C, 0x9B, 0x13, 0xF0, + 0x80, 0x5F, 0x08, 0x9B, 0x0F, 0x93, 0x4F, 0xF0, 0x18, 0x03, 0x11, 0x93, 0x4F, 0xF0, 0x0C, 0x03, + 0x09, 0x93, 0x4F, 0xF0, 0x05, 0x03, 0x03, 0x93, 0x05, 0xD1, 0x0A, 0x23, 0x0E, 0x93, 0x05, 0x23, + 0x07, 0x93, 0x11, 0x23, 0xC0, 0xE6, 0x0B, 0x23, 0x0E, 0x93, 0x05, 0x23, 0x07, 0x93, 0x13, 0x23, + 0xBA, 0xE6, 0x00, 0xBF, 0x38, 0x12, 0x01, 0x00, 0x20, 0x01, 0x82, 0x04, 0x00, 0x01, 0x82, 0x04, + 0x04, 0x01, 0x82, 0x04, 0x08, 0x01, 0x82, 0x04, 0x0C, 0x01, 0x82, 0x04, 0x10, 0x01, 0x82, 0x04, + 0x14, 0x01, 0x82, 0x04, 0x18, 0x01, 0x82, 0x04, 0x28, 0x01, 0x82, 0x04, 0x05, 0x0C, 0x0E, 0x00, + 0x1C, 0x02, 0x0C, 0x44, 0x02, 0x00, 0x10, 0x0A, 0xD0, 0x00, 0x82, 0x04, 0x00, 0xF0, 0xFF, 0x3F, + 0x00, 0x9B, 0x08, 0x2B, 0x5C, 0xD1, 0x4A, 0x49, 0x01, 0x40, 0x41, 0xF4, 0x7C, 0x71, 0x49, 0x4B, + 0x00, 0x9A, 0x49, 0x4C, 0x19, 0x60, 0xDB, 0xF8, 0x78, 0x10, 0x48, 0x4B, 0x11, 0xF0, 0x08, 0x0F, + 0x47, 0x49, 0x14, 0xBF, 0x4F, 0xF4, 0x84, 0x00, 0x4F, 0xF0, 0xF9, 0x70, 0x08, 0x60, 0x45, 0x48, + 0x01, 0x68, 0x21, 0xF4, 0x7F, 0x41, 0x21, 0xF0, 0x0F, 0x01, 0x41, 0xF4, 0x50, 0x61, 0x41, 0xF0, + 0x05, 0x01, 0x01, 0x60, 0x00, 0x20, 0x40, 0x49, 0x08, 0x60, 0x91, 0x1F, 0x02, 0x29, 0xDB, 0xF8, + 0x24, 0x20, 0x38, 0xD8, 0xDB, 0xF8, 0x28, 0x10, 0x41, 0xEA, 0x02, 0x41, 0x4A, 0xF8, 0x03, 0x10, + 0xDB, 0xF8, 0x2C, 0x10, 0x00, 0x9B, 0x09, 0x04, 0x08, 0x2B, 0x4A, 0xF8, 0x04, 0x10, 0x46, 0xD0, + 0x36, 0x48, 0x5A, 0xF8, 0x00, 0x10, 0x21, 0xF4, 0x7F, 0x61, 0x41, 0xF4, 0xCC, 0x61, 0x4A, 0xF8, + 0x00, 0x10, 0xDB, 0xF8, 0x78, 0x10, 0x11, 0xF0, 0x20, 0x0F, 0x31, 0x49, 0x48, 0xD1, 0x06, 0x9B, + 0x58, 0x1E, 0x07, 0x9B, 0x5C, 0x1E, 0x44, 0xF0, 0x00, 0x74, 0x44, 0xEA, 0x00, 0x40, 0x01, 0x43, + 0x2C, 0x48, 0x17, 0x9B, 0x01, 0x3F, 0x10, 0x9A, 0x4A, 0xF8, 0x00, 0x10, 0x2A, 0x49, 0x2B, 0x48, + 0x4A, 0xF8, 0x01, 0x00, 0x43, 0xEA, 0x02, 0x41, 0x29, 0x48, 0x4A, 0xF8, 0x00, 0x10, 0x42, 0xE4, + 0x20, 0xF0, 0x40, 0x40, 0xBB, 0xE6, 0xDB, 0xF8, 0x20, 0x00, 0x42, 0xEA, 0x00, 0x40, 0x4A, 0xF8, + 0x03, 0x00, 0xDB, 0xE9, 0x0A, 0x01, 0x00, 0x9B, 0x41, 0xEA, 0x00, 0x41, 0x04, 0x2B, 0x4A, 0xF8, + 0x04, 0x10, 0xC5, 0xD1, 0xDB, 0xE9, 0x0C, 0x01, 0x41, 0xEA, 0x00, 0x41, 0x1D, 0x48, 0x4A, 0xF8, + 0x00, 0x10, 0x1D, 0x49, 0xDB, 0xF8, 0x38, 0x00, 0x4A, 0xF8, 0x01, 0x00, 0xB8, 0xE7, 0xDB, 0xE9, + 0x0F, 0x01, 0x41, 0xEA, 0x00, 0x41, 0x17, 0x48, 0x4A, 0xF8, 0x00, 0x10, 0xDB, 0xF8, 0x54, 0x00, + 0xDB, 0xF8, 0x48, 0x10, 0x41, 0xEA, 0x00, 0x41, 0x13, 0x48, 0x4A, 0xF8, 0x00, 0x10, 0xA7, 0xE7, + 0x07, 0x9B, 0x43, 0xF0, 0x00, 0x70, 0x06, 0x9B, 0x40, 0xEA, 0x03, 0x40, 0xB7, 0xE7, 0x00, 0xBF, + 0x00, 0xF0, 0xFF, 0x3F, 0xD0, 0x00, 0x82, 0x04, 0xE0, 0x00, 0x82, 0x04, 0xDC, 0x00, 0x82, 0x04, + 0xD4, 0x00, 0x82, 0x04, 0xD8, 0x00, 0x82, 0x04, 0xB0, 0x01, 0x82, 0x04, 0xF4, 0x00, 0x82, 0x04, + 0x00, 0x80, 0x80, 0x00, 0x90, 0x01, 0x82, 0x04, 0x94, 0x01, 0x82, 0x04, 0x02, 0x02, 0x10, 0x00, + 0x64, 0x00, 0x82, 0x04, 0xE8, 0x00, 0x82, 0x04, 0xEC, 0x00, 0x82, 0x04, 0x83, 0x69, 0xC2, 0x69, + 0x2D, 0xE9, 0xF0, 0x47, 0xC3, 0xF3, 0x01, 0x31, 0x03, 0xF0, 0x0F, 0x04, 0xC3, 0xF3, 0x07, 0x16, + 0xC3, 0xF3, 0x81, 0x33, 0x15, 0x07, 0x4F, 0xEA, 0x03, 0x49, 0x4F, 0xEA, 0x03, 0x25, 0x64, 0x4F, + 0x4F, 0xEA, 0x03, 0x62, 0x18, 0xBF, 0x04, 0xF1, 0xFF, 0x34, 0x45, 0xEA, 0x09, 0x0E, 0x4E, 0xEA, + 0x02, 0x0C, 0xA4, 0xF1, 0x08, 0x08, 0xC7, 0xF8, 0x00, 0xC0, 0x08, 0x37, 0xDF, 0xF8, 0x88, 0xC1, + 0xB8, 0xF1, 0x03, 0x0F, 0x53, 0xD8, 0xDF, 0xE8, 0x08, 0xF0, 0x02, 0x3D, 0x44, 0x4A, 0x43, 0xF0, + 0xF8, 0x5E, 0x4E, 0xF4, 0xF8, 0x1E, 0x4E, 0xEA, 0x05, 0x05, 0xCC, 0xF8, 0x00, 0x50, 0x41, 0xF6, + 0x1F, 0x72, 0x3A, 0x60, 0x02, 0x2B, 0x4A, 0xD0, 0x43, 0xF6, 0x3F, 0x72, 0x43, 0xF6, 0x01, 0x75, + 0x01, 0x2B, 0x08, 0xBF, 0x2A, 0x46, 0x4F, 0x4D, 0x03, 0x29, 0x4F, 0x4F, 0x2A, 0x60, 0xA3, 0xF1, + 0x02, 0x02, 0x22, 0x44, 0x0B, 0x44, 0x4F, 0xEA, 0x02, 0x25, 0x18, 0xBF, 0x42, 0xF4, 0x7C, 0x12, + 0x23, 0x44, 0x4A, 0x49, 0x08, 0xBF, 0x45, 0xEA, 0x02, 0x45, 0x2A, 0x43, 0x04, 0x31, 0x3A, 0x60, + 0x9A, 0x1F, 0x42, 0xEA, 0x02, 0x2C, 0xA6, 0xF1, 0x0E, 0x07, 0x45, 0x4D, 0x4C, 0xEA, 0x02, 0x48, + 0x48, 0xEA, 0x02, 0x6E, 0x41, 0xF8, 0x04, 0xEC, 0x03, 0x2F, 0x6F, 0xD8, 0xDF, 0xE8, 0x07, 0xF0, + 0x22, 0x3A, 0x54, 0x69, 0x43, 0xF0, 0xF8, 0x5E, 0x4E, 0xEA, 0x05, 0x05, 0x45, 0xEA, 0x09, 0x05, + 0xC3, 0xE7, 0x1A, 0x43, 0x42, 0xEA, 0x0E, 0x02, 0xCC, 0xF8, 0x00, 0x20, 0xBF, 0xE7, 0x1A, 0x43, + 0x42, 0xEA, 0x0E, 0x02, 0xCC, 0xF8, 0x00, 0x20, 0x43, 0xF4, 0xF8, 0x52, 0xB9, 0xE7, 0x1D, 0x43, + 0x49, 0xEA, 0x02, 0x02, 0x2A, 0x43, 0xCC, 0xF8, 0x00, 0x20, 0x3D, 0x60, 0xB2, 0xE7, 0x40, 0xF2, + 0x01, 0x12, 0xB8, 0xE7, 0x4C, 0xF0, 0x70, 0x62, 0x42, 0xF4, 0x70, 0x22, 0x0A, 0x60, 0x40, 0xF6, + 0x0F, 0x72, 0x2A, 0x60, 0xC2, 0x69, 0xD2, 0x04, 0x45, 0xD5, 0xB0, 0xF8, 0x7A, 0x20, 0x02, 0xF0, + 0x07, 0x02, 0x01, 0x3A, 0x02, 0x2A, 0x03, 0xD9, 0x06, 0x3E, 0x1E, 0x44, 0x25, 0x4B, 0x1E, 0x60, + 0xBD, 0xE8, 0xF0, 0x87, 0xB0, 0xF8, 0x7A, 0x70, 0x07, 0xF0, 0x07, 0x07, 0x01, 0x2F, 0x0C, 0xD1, + 0x0B, 0x2C, 0x0E, 0xD1, 0x5C, 0x1F, 0x42, 0xF0, 0x70, 0x62, 0x42, 0xEA, 0x04, 0x22, 0x42, 0xEA, + 0x04, 0x42, 0x0A, 0x60, 0xDA, 0x1D, 0x1B, 0x49, 0xD8, 0xE7, 0x02, 0x2F, 0x01, 0xD1, 0x0A, 0x2C, + 0xEF, 0xE7, 0x48, 0xF0, 0x70, 0x62, 0xD1, 0xE7, 0xB0, 0xF8, 0x7A, 0x70, 0x07, 0xF0, 0x07, 0x07, + 0x01, 0x2F, 0x0B, 0xD1, 0x0A, 0x2C, 0x09, 0xD1, 0x5C, 0x1F, 0x22, 0x06, 0x42, 0xEA, 0x04, 0x42, + 0x42, 0xEA, 0x0C, 0x02, 0x0A, 0x60, 0x03, 0xF1, 0x08, 0x02, 0xE4, 0xE7, 0xC1, 0xF8, 0x00, 0xE0, + 0xBD, 0xE7, 0xC1, 0xF8, 0x00, 0xE0, 0x42, 0xF4, 0x70, 0x62, 0xBA, 0xE7, 0xC1, 0xF8, 0x00, 0xE0, + 0xC5, 0xF8, 0x00, 0xC0, 0xB6, 0xE7, 0x07, 0x4B, 0x1F, 0x22, 0x1A, 0x60, 0xC0, 0xE7, 0x00, 0xBF, + 0x08, 0x02, 0x82, 0x04, 0x20, 0x02, 0x82, 0x04, 0x04, 0x02, 0x82, 0x04, 0x14, 0x02, 0x82, 0x04, + 0x1C, 0x02, 0x82, 0x04, 0x00, 0x02, 0x82, 0x04, 0x0C, 0x02, 0x82, 0x04, 0xC3, 0x69, 0x40, 0xF2, + 0x01, 0x22, 0x30, 0xB5, 0x13, 0xF4, 0x80, 0x5F, 0x40, 0xF2, 0x03, 0x33, 0x08, 0xBF, 0x13, 0x46, + 0x1D, 0x4A, 0x13, 0x60, 0x43, 0x68, 0x03, 0xF0, 0x07, 0x03, 0x04, 0x2B, 0x12, 0xD0, 0x07, 0x2B, + 0x1C, 0xD0, 0x03, 0x2B, 0x19, 0x4B, 0x18, 0xBF, 0x4F, 0xF0, 0x04, 0x23, 0x18, 0x4A, 0x13, 0x60, + 0x02, 0xF5, 0x00, 0x52, 0x13, 0x60, 0x02, 0xF5, 0x80, 0x52, 0x13, 0x60, 0x02, 0xF5, 0x80, 0x52, + 0x13, 0x60, 0x30, 0xBD, 0x02, 0x6B, 0xC2, 0xF3, 0x00, 0x33, 0x99, 0x1D, 0x93, 0x02, 0x03, 0xF4, + 0xE0, 0x23, 0x43, 0xF4, 0x80, 0x63, 0x43, 0xEA, 0x01, 0x63, 0xE7, 0xE7, 0x01, 0x68, 0x0D, 0x4C, + 0xB1, 0xF5, 0xC8, 0x7F, 0xC1, 0xEB, 0xC1, 0x02, 0x34, 0xBF, 0x03, 0x21, 0x04, 0x21, 0x82, 0xFB, + 0x04, 0x45, 0xD2, 0x17, 0xC2, 0xEB, 0xE5, 0x12, 0xD3, 0x1D, 0x8A, 0x1A, 0x1B, 0x06, 0x43, 0xF4, + 0x80, 0x63, 0x43, 0xEA, 0x02, 0x43, 0xD1, 0xE7, 0x44, 0x02, 0x82, 0x04, 0x00, 0x04, 0x00, 0x06, + 0x40, 0x02, 0x82, 0x04, 0xD3, 0x4D, 0x62, 0x10, 0x06, 0x4A, 0x13, 0x68, 0x19, 0x05, 0x03, 0xD5, + 0x23, 0xF4, 0x80, 0x63, 0x13, 0x60, 0x70, 0x47, 0x81, 0x6F, 0x89, 0x06, 0xF8, 0xD4, 0x43, 0xF4, + 0x80, 0x63, 0xF7, 0xE7, 0x00, 0x00, 0x82, 0x04, 0x03, 0x4A, 0x83, 0x6F, 0x11, 0x68, 0xC3, 0xF3, + 0x80, 0x73, 0x0B, 0x43, 0x13, 0x60, 0x70, 0x47, 0x00, 0x00, 0x82, 0x04, 0x43, 0x68, 0x03, 0xF0, + 0x0F, 0x03, 0x04, 0x3B, 0x04, 0x2B, 0x97, 0xBF, 0x0A, 0x4A, 0x0B, 0x49, 0x02, 0xEB, 0x83, 0x03, + 0xD3, 0xF8, 0xA8, 0x13, 0xC3, 0x69, 0xDA, 0x0A, 0x1B, 0x03, 0x02, 0xF0, 0x06, 0x02, 0x03, 0xF4, + 0x80, 0x53, 0x01, 0x32, 0x43, 0xF0, 0x40, 0x43, 0x43, 0xEA, 0x02, 0x63, 0x03, 0x4A, 0x0B, 0x43, + 0x13, 0x60, 0x70, 0x47, 0x5C, 0x30, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x82, 0x04, + 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0xDA, 0xFF, 0x43, 0x68, 0x04, 0x2B, 0x01, 0xD1, 0xFF, 0xF7, + 0xCB, 0xFF, 0x63, 0x68, 0x03, 0x3B, 0x01, 0x2B, 0x02, 0xD8, 0x20, 0x46, 0xFF, 0xF7, 0xB4, 0xFF, + 0x20, 0x46, 0xFF, 0xF7, 0x63, 0xFF, 0xFF, 0xF7, 0x79, 0xFE, 0xFF, 0xF7, 0x1D, 0xFA, 0x09, 0x4B, + 0x00, 0x22, 0x20, 0x46, 0x1A, 0x60, 0xFF, 0xF7, 0xF7, 0xF9, 0x63, 0x68, 0x04, 0x2B, 0x01, 0xD0, + 0x08, 0x2B, 0x02, 0xD1, 0x20, 0x46, 0xFF, 0xF7, 0xE3, 0xF9, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, + 0xFF, 0xF7, 0xC8, 0xB9, 0x30, 0x00, 0x82, 0x04, 0x43, 0x68, 0x08, 0x2B, 0x01, 0xBF, 0x0D, 0x4A, + 0x13, 0x68, 0x43, 0xF0, 0x01, 0x03, 0x13, 0x60, 0x0B, 0x4B, 0x1A, 0x68, 0x22, 0xF4, 0x7F, 0x42, + 0x42, 0xF4, 0x40, 0x52, 0x1A, 0x60, 0x82, 0x6F, 0xD2, 0x00, 0x09, 0xD5, 0x1A, 0x68, 0x07, 0x48, + 0x22, 0xF0, 0x0F, 0x02, 0x42, 0xF0, 0x01, 0x02, 0x1A, 0x60, 0x19, 0x68, 0xFC, 0xF7, 0xD4, 0xBE, + 0x70, 0x47, 0x00, 0xBF, 0xA8, 0x2E, 0x10, 0x03, 0x50, 0x02, 0x82, 0x04, 0x98, 0x38, 0x04, 0x00, + 0x2D, 0xE9, 0xF0, 0x41, 0x80, 0x46, 0x27, 0x4D, 0x05, 0x20, 0x27, 0x4E, 0x2B, 0x68, 0x27, 0x4F, + 0x27, 0x4C, 0x23, 0xF0, 0x00, 0x43, 0x2B, 0x60, 0x2B, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x2B, 0x60, + 0x33, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x33, 0x60, 0x33, 0x68, 0x23, 0xF4, 0x80, 0x33, 0x33, 0x60, + 0x3B, 0x68, 0x23, 0xF0, 0x00, 0x43, 0x3B, 0x60, 0x23, 0x68, 0x23, 0xF0, 0x80, 0x43, 0x23, 0x60, + 0xFC, 0xF7, 0xDE, 0xFE, 0xD8, 0xF8, 0x00, 0x00, 0x42, 0x46, 0x39, 0x46, 0x40, 0x00, 0xFD, 0xF7, + 0x71, 0xFC, 0x23, 0x68, 0x05, 0x20, 0x23, 0xF0, 0x40, 0x73, 0x23, 0x60, 0x23, 0x68, 0x23, 0xF0, + 0x1F, 0x03, 0x43, 0xF0, 0x03, 0x02, 0x43, 0xF0, 0x00, 0x63, 0x43, 0xF0, 0x03, 0x03, 0x22, 0x60, + 0x23, 0x60, 0x33, 0x68, 0x43, 0xF4, 0x80, 0x33, 0x33, 0x60, 0x33, 0x68, 0x43, 0xF0, 0x01, 0x03, + 0x33, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x2B, 0x60, 0x2B, 0x68, 0x43, 0xF0, 0x00, 0x43, + 0x2B, 0x60, 0x23, 0x68, 0x43, 0xF0, 0x80, 0x43, 0x23, 0x60, 0xBD, 0xE8, 0xF0, 0x41, 0xFC, 0xF7, + 0xAF, 0xBE, 0x00, 0xBF, 0x40, 0x15, 0x00, 0x03, 0x0C, 0x18, 0x00, 0x03, 0x10, 0x10, 0x00, 0x03, + 0x00, 0x18, 0x00, 0x03, 0x10, 0xB5, 0x04, 0x46, 0xFF, 0xF7, 0xA2, 0xFF, 0x20, 0x46, 0x00, 0xF0, + 0x01, 0xFC, 0x63, 0x68, 0x04, 0x2B, 0x04, 0xBF, 0x4F, 0xF0, 0x80, 0x43, 0x1B, 0x68, 0x10, 0xBD, + 0x2D, 0xE9, 0xF8, 0x4F, 0x04, 0x46, 0x69, 0x4D, 0xD0, 0xF8, 0x00, 0xA0, 0xD0, 0xE9, 0x1C, 0x67, + 0xFD, 0xF7, 0x94, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xE5, 0xFF, 0xE0, 0xB1, 0x23, 0x46, 0x01, 0x22, + 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, 0xE9, 0xFA, 0xA0, 0xB9, 0xDF, 0xF8, 0xA8, 0xB1, + 0x4F, 0xF0, 0x05, 0x08, 0x21, 0x68, 0x5E, 0x48, 0xFC, 0xF7, 0x46, 0xFE, 0x23, 0x68, 0x53, 0x45, + 0x1A, 0xD9, 0xA3, 0x6F, 0x01, 0x25, 0xC4, 0xF8, 0x00, 0xA0, 0x1A, 0x02, 0x5C, 0xBF, 0x23, 0xF4, + 0x00, 0x63, 0xA3, 0x67, 0x0D, 0xE0, 0x21, 0x68, 0x28, 0x46, 0xFC, 0xF7, 0x35, 0xFE, 0x23, 0x68, + 0x60, 0x3B, 0xB3, 0xF5, 0xB4, 0x7F, 0x23, 0x60, 0xD4, 0xD2, 0x52, 0x48, 0x00, 0x25, 0xFC, 0xF7, + 0x2B, 0xFE, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x8F, 0xB8, 0xF1, 0x01, 0x08, 0x01, 0xD1, 0x4E, 0x48, + 0xF4, 0xE7, 0x20, 0x46, 0xFE, 0xF7, 0x36, 0xF8, 0x00, 0x28, 0x35, 0xD0, 0x4F, 0xF0, 0x04, 0x09, + 0x21, 0x68, 0x4A, 0x48, 0xFC, 0xF7, 0x18, 0xFE, 0xB9, 0xF1, 0x01, 0x09, 0x05, 0xD1, 0x48, 0x48, + 0xE4, 0xE7, 0x23, 0x68, 0x60, 0x3B, 0x23, 0x60, 0xF6, 0xE7, 0xC4, 0xE9, 0x1C, 0x67, 0x20, 0x46, + 0xFF, 0xF7, 0x98, 0xFF, 0x05, 0x46, 0x00, 0x28, 0xDB, 0xD0, 0x20, 0x46, 0xFE, 0xF7, 0x1A, 0xF8, + 0x00, 0x28, 0xEE, 0xD1, 0xD4, 0xE9, 0x1C, 0x12, 0x3E, 0x48, 0xFC, 0xF7, 0xFD, 0xFD, 0x23, 0x68, + 0x60, 0x33, 0x53, 0x45, 0x23, 0x60, 0xB1, 0xD8, 0x20, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0x00, 0x28, + 0x3B, 0xD0, 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, 0x86, 0xFA, + 0x98, 0xBB, 0xD4, 0xE9, 0x1C, 0x67, 0xA1, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x73, 0xFF, 0x50, 0xB1, + 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, 0xFD, 0xF7, 0x77, 0xFA, 0x10, 0xB9, + 0xD4, 0xE9, 0x1C, 0x67, 0xD6, 0xE7, 0x22, 0x68, 0x03, 0x25, 0x58, 0x46, 0xA2, 0xF1, 0x60, 0x01, + 0xFC, 0xF7, 0xD2, 0xFD, 0xC4, 0xE9, 0x1C, 0x67, 0x23, 0x68, 0x01, 0x3D, 0xA3, 0xF1, 0x60, 0x03, + 0x23, 0x60, 0x03, 0xD1, 0x24, 0x48, 0xFC, 0xF7, 0xC7, 0xFD, 0x9A, 0xE7, 0x20, 0x46, 0xFF, 0xF7, + 0x51, 0xFF, 0x00, 0x28, 0xF0, 0xD0, 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, 0x80, 0x50, + 0xFD, 0xF7, 0x54, 0xFA, 0x00, 0x28, 0xE7, 0xD1, 0xB4, 0xE7, 0xA1, 0x6F, 0x03, 0x25, 0x1B, 0x48, + 0xFC, 0xF7, 0xB2, 0xFD, 0x22, 0x68, 0x58, 0x46, 0xA2, 0xF1, 0x60, 0x01, 0xFC, 0xF7, 0xAC, 0xFD, + 0xD4, 0xE9, 0x1C, 0x12, 0x16, 0x48, 0xFC, 0xF7, 0xA7, 0xFD, 0xC4, 0xE9, 0x1C, 0x67, 0x23, 0x68, + 0x01, 0x3D, 0xA3, 0xF1, 0x60, 0x03, 0x23, 0x60, 0x01, 0xD1, 0x12, 0x48, 0xD3, 0xE7, 0x20, 0x46, + 0xFF, 0xF7, 0x28, 0xFF, 0x00, 0x28, 0xF2, 0xD0, 0x23, 0x46, 0x01, 0x22, 0x08, 0x21, 0x4F, 0xF4, + 0x80, 0x50, 0xFD, 0xF7, 0x2B, 0xFA, 0x00, 0x28, 0xE9, 0xD1, 0x47, 0xE7, 0xE8, 0x38, 0x04, 0x00, + 0xB4, 0x38, 0x04, 0x00, 0x1C, 0x39, 0x04, 0x00, 0x54, 0x39, 0x04, 0x00, 0x75, 0x39, 0x04, 0x00, + 0x9B, 0x39, 0x04, 0x00, 0x1E, 0x3A, 0x04, 0x00, 0xFC, 0x39, 0x04, 0x00, 0x58, 0x3A, 0x04, 0x00, + 0x70, 0x3A, 0x04, 0x00, 0x9E, 0x3A, 0x04, 0x00, 0xB8, 0x39, 0x04, 0x00, 0x2D, 0xE9, 0xF8, 0x4F, + 0x04, 0x46, 0xC6, 0x6E, 0x85, 0x69, 0x46, 0xF0, 0x80, 0x53, 0xC3, 0x66, 0x43, 0x68, 0x04, 0x2B, + 0x0C, 0xBF, 0x4B, 0xF2, 0xEB, 0x03, 0x43, 0xF2, 0xEB, 0x03, 0x83, 0x61, 0xD0, 0xE9, 0x06, 0x73, + 0x13, 0xF0, 0x0F, 0x0F, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x09, 0x4F, 0xF0, 0x02, 0x09, 0xFF, 0xF7, + 0xE9, 0xFE, 0x10, 0xB9, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x4F, 0xF0, 0x80, 0x42, 0x00, 0x23, + 0xD9, 0x07, 0x54, 0xBF, 0xD1, 0x43, 0x11, 0x46, 0x42, 0xF8, 0x04, 0x1B, 0xBF, 0xF3, 0x4F, 0x8F, + 0x01, 0x33, 0x10, 0x2B, 0xF4, 0xD1, 0x4F, 0xF0, 0x80, 0x43, 0x00, 0x21, 0xC8, 0x07, 0x40, 0xF1, + 0x89, 0x80, 0x1A, 0x46, 0x18, 0x6C, 0x82, 0x42, 0x40, 0xF0, 0x86, 0x80, 0x01, 0x31, 0x04, 0x33, + 0x10, 0x29, 0xF3, 0xD1, 0x4F, 0xF0, 0x01, 0x08, 0xC7, 0xF3, 0x81, 0x32, 0x4F, 0xF0, 0x01, 0x0E, + 0x4A, 0x44, 0x07, 0x27, 0xD0, 0x19, 0x4F, 0xF0, 0x80, 0x43, 0x0E, 0xFA, 0x00, 0xF0, 0x00, 0x21, + 0x50, 0xF8, 0x03, 0x90, 0x11, 0xF0, 0x01, 0x0F, 0x0C, 0xBF, 0x6F, 0xEA, 0x03, 0x0C, 0x9C, 0x46, + 0xE1, 0x45, 0x40, 0xF0, 0x84, 0x80, 0x01, 0x31, 0x04, 0x33, 0x10, 0x29, 0xF0, 0xD1, 0x01, 0x23, + 0x0D, 0x32, 0x03, 0xFA, 0x02, 0xF2, 0x4F, 0xF0, 0x80, 0x41, 0x00, 0x23, 0x52, 0xF8, 0x01, 0xC0, + 0xD8, 0x07, 0x54, 0xBF, 0xC8, 0x43, 0x08, 0x46, 0x84, 0x45, 0x6D, 0xD1, 0x01, 0x33, 0x04, 0x31, + 0x10, 0x2B, 0xF3, 0xD1, 0x4F, 0xF0, 0x02, 0x0A, 0x63, 0x68, 0x20, 0x46, 0x04, 0x2B, 0x0C, 0xBF, + 0x46, 0xF2, 0x18, 0x13, 0x42, 0xF2, 0x18, 0x13, 0xA3, 0x61, 0xD4, 0xE9, 0x06, 0x93, 0x13, 0xF0, + 0x0F, 0x0F, 0x14, 0xBF, 0x4F, 0xF0, 0x01, 0x0B, 0x4F, 0xF0, 0x02, 0x0B, 0xFF, 0xF7, 0x82, 0xFE, + 0x00, 0x28, 0x97, 0xD0, 0x4F, 0xF0, 0x80, 0x42, 0x00, 0x23, 0xD9, 0x07, 0x54, 0xBF, 0xD1, 0x43, + 0x11, 0x46, 0x42, 0xF8, 0x04, 0x1B, 0xBF, 0xF3, 0x4F, 0x8F, 0x01, 0x33, 0x10, 0x2B, 0xF4, 0xD1, + 0xC9, 0xF3, 0x81, 0x39, 0x0C, 0x21, 0x09, 0xF1, 0x0A, 0x09, 0x4F, 0xF0, 0x01, 0x0E, 0xD9, 0x44, + 0x09, 0xEB, 0x01, 0x00, 0x4F, 0xF0, 0x80, 0x42, 0x0E, 0xFA, 0x00, 0xF0, 0x00, 0x23, 0x50, 0xF8, + 0x02, 0xB0, 0x13, 0xF0, 0x01, 0x0F, 0x0C, 0xBF, 0x6F, 0xEA, 0x02, 0x0C, 0x94, 0x46, 0xE3, 0x45, + 0x32, 0xD1, 0x01, 0x33, 0x04, 0x32, 0x10, 0x2B, 0xF1, 0xD1, 0x2B, 0x0C, 0xE6, 0x66, 0x01, 0x20, + 0x1B, 0x04, 0x43, 0xEA, 0x88, 0x33, 0x3B, 0x43, 0x43, 0xEA, 0x0A, 0x33, 0x43, 0xEA, 0x01, 0x13, + 0xA3, 0x61, 0x60, 0xE7, 0xDA, 0x43, 0x75, 0xE7, 0x4F, 0xF0, 0x80, 0x43, 0x00, 0x21, 0xCA, 0x07, + 0x10, 0xD5, 0x1A, 0x46, 0xD3, 0xF8, 0x80, 0x00, 0x82, 0x42, 0x03, 0xD1, 0x01, 0x31, 0x04, 0x33, + 0x10, 0x29, 0xF4, 0xD1, 0x63, 0x68, 0x04, 0x2B, 0x14, 0xBF, 0x4F, 0xF0, 0x00, 0x08, 0x4F, 0xF0, + 0x02, 0x08, 0x69, 0xE7, 0xDA, 0x43, 0xED, 0xE7, 0x4F, 0xF0, 0x03, 0x0A, 0x94, 0xE7, 0x01, 0x37, + 0x0B, 0x2F, 0x7F, 0xF4, 0x67, 0xAF, 0x7A, 0xE7, 0x01, 0x31, 0x11, 0x29, 0xB8, 0xD1, 0xCC, 0xE7, + 0x2D, 0xE9, 0xF0, 0x47, 0x04, 0x46, 0xC7, 0x6E, 0xD0, 0xF8, 0x78, 0x80, 0x47, 0xF0, 0x80, 0x53, + 0xD0, 0xE9, 0x06, 0x96, 0xC3, 0x66, 0x48, 0xF0, 0x01, 0x03, 0x83, 0x67, 0x43, 0x68, 0x04, 0x2B, + 0x0C, 0xBF, 0x46, 0xF2, 0xB7, 0x03, 0x42, 0xF2, 0xB7, 0x03, 0x83, 0x61, 0x4F, 0xF4, 0x80, 0x53, + 0xC3, 0x61, 0xFF, 0xF7, 0x07, 0xFE, 0x05, 0x46, 0x88, 0xB1, 0x34, 0x48, 0xFC, 0xF7, 0x74, 0xFC, + 0x33, 0x0C, 0xE2, 0x69, 0x4F, 0xF0, 0x01, 0x0A, 0xC4, 0xF8, 0x78, 0x80, 0x1B, 0x04, 0xC4, 0xF8, + 0x18, 0x90, 0xE7, 0x66, 0x13, 0x43, 0xE3, 0x61, 0x50, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xA3, 0x6F, + 0x98, 0x07, 0x0A, 0xD5, 0x20, 0x46, 0xFE, 0xF7, 0x1F, 0xFA, 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, + 0x01, 0x35, 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xDF, 0xD1, 0x00, 0x23, 0x20, 0x46, 0xE3, 0x61, + 0xFF, 0xF7, 0xE0, 0xFD, 0x05, 0x46, 0x08, 0xB1, 0x21, 0x48, 0xD7, 0xE7, 0xA3, 0x6F, 0x99, 0x07, + 0x0A, 0xD5, 0x20, 0x46, 0xFE, 0xF7, 0x08, 0xFA, 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, + 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xEF, 0xD1, 0x41, 0xF2, 0x01, 0x03, 0x20, 0x46, 0xE3, 0x61, + 0xFF, 0xF7, 0xC8, 0xFD, 0x05, 0x46, 0x08, 0xB1, 0x16, 0x48, 0xBF, 0xE7, 0xA3, 0x6F, 0x9A, 0x07, + 0x0A, 0xD5, 0x20, 0x46, 0xFE, 0xF7, 0xF0, 0xF9, 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, + 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xEF, 0xD1, 0x01, 0x23, 0x20, 0x46, 0xE3, 0x61, 0xFF, 0xF7, + 0xB1, 0xFD, 0x82, 0x46, 0x08, 0xB1, 0x0C, 0x48, 0xA8, 0xE7, 0xA3, 0x6F, 0x9B, 0x07, 0xB3, 0xD5, + 0x05, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0xD8, 0xF9, 0x01, 0x28, 0x08, 0xBF, 0x0A, 0x25, 0x01, 0x35, + 0x09, 0x2D, 0xF6, 0xD9, 0x00, 0x28, 0xA7, 0xD0, 0xED, 0xE7, 0x00, 0xBF, 0xBF, 0x3A, 0x04, 0x00, + 0xEC, 0x3A, 0x04, 0x00, 0x19, 0x3B, 0x04, 0x00, 0x47, 0x3B, 0x04, 0x00, 0x83, 0x6F, 0x2D, 0xE9, + 0xF0, 0x47, 0x04, 0x46, 0x06, 0x68, 0xDD, 0x04, 0x05, 0xD5, 0xB6, 0xF5, 0xB4, 0x7F, 0x84, 0xBF, + 0x4F, 0xF4, 0xB4, 0x72, 0x02, 0x60, 0x13, 0xF0, 0x00, 0x75, 0x14, 0xD0, 0x44, 0x4A, 0x65, 0x69, + 0x44, 0x48, 0x62, 0x61, 0x44, 0x4A, 0xD4, 0xE9, 0x1C, 0x98, 0xE7, 0x6F, 0xC4, 0xE9, 0x1C, 0x02, + 0x42, 0x4A, 0xE2, 0x67, 0x5B, 0x04, 0x0A, 0xD5, 0x20, 0x46, 0xFF, 0xF7, 0x6F, 0xFE, 0x60, 0xB9, + 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x87, 0x2F, 0x46, 0xA8, 0x46, 0xA9, 0x46, 0xF2, 0xE7, 0x20, 0x46, + 0xFF, 0xF7, 0x46, 0xFF, 0x00, 0x28, 0xEF, 0xD1, 0xF2, 0xE7, 0xA3, 0x6F, 0x18, 0x04, 0x5E, 0xBF, + 0x43, 0xF4, 0xC0, 0x43, 0x43, 0xF0, 0x01, 0x03, 0xA3, 0x67, 0xA3, 0x6F, 0x19, 0x03, 0x1F, 0xD5, + 0x20, 0x46, 0xFF, 0xF7, 0x57, 0xFD, 0x00, 0x28, 0xE2, 0xD0, 0x20, 0x46, 0xFC, 0xF7, 0xD8, 0xFF, + 0xA3, 0x6F, 0xB0, 0xF5, 0x80, 0x5F, 0x23, 0xF4, 0x00, 0x23, 0xA3, 0x67, 0x1D, 0xD1, 0x4F, 0xF0, + 0x20, 0x43, 0x4F, 0xF0, 0xA0, 0x32, 0x1A, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x1B, 0x68, 0x93, 0x42, + 0x06, 0xD0, 0xA1, 0x6F, 0x26, 0x48, 0x41, 0xF4, 0x80, 0x31, 0xA1, 0x67, 0xFC, 0xF7, 0xAC, 0xFB, + 0xA3, 0x6F, 0x9A, 0x01, 0x06, 0xD5, 0xE3, 0x69, 0xDB, 0x04, 0x30, 0xD5, 0x65, 0x61, 0xC4, 0xE9, + 0x1C, 0x98, 0xE7, 0x67, 0x26, 0x60, 0x01, 0x20, 0xBB, 0xE7, 0xB0, 0xF5, 0x00, 0x6F, 0xEF, 0xD1, + 0x4F, 0xF0, 0xE0, 0x43, 0x4F, 0xF0, 0x70, 0x32, 0x1A, 0x60, 0xBF, 0xF3, 0x4F, 0x8F, 0x1B, 0x68, + 0x93, 0x42, 0x05, 0xD0, 0xA1, 0x6F, 0x41, 0xF4, 0x00, 0x31, 0xA1, 0x67, 0x15, 0x48, 0xDD, 0xE7, + 0x4F, 0xF0, 0x20, 0x4A, 0x4F, 0xF0, 0xA0, 0x33, 0xCA, 0xF8, 0x00, 0x30, 0x4F, 0xF0, 0x80, 0x32, + 0x4F, 0xF0, 0x00, 0x43, 0x01, 0x20, 0x1A, 0x60, 0xFC, 0xF7, 0xB2, 0xFB, 0xDA, 0xF8, 0x00, 0x30, + 0xB3, 0xF1, 0xA0, 0x3F, 0xCC, 0xD0, 0xA1, 0x6F, 0x41, 0xF4, 0xA0, 0x21, 0xE5, 0xE7, 0x23, 0x6D, + 0x63, 0x61, 0xE3, 0x6D, 0x23, 0x67, 0x23, 0x6E, 0x63, 0x67, 0x63, 0x6D, 0xE3, 0x67, 0xC9, 0xE7, + 0x1C, 0x1A, 0x15, 0x14, 0x19, 0x16, 0x13, 0x0E, 0x17, 0x18, 0x17, 0x18, 0x2B, 0x28, 0x28, 0x2A, + 0x75, 0x3B, 0x04, 0x00, 0xA6, 0x3B, 0x04, 0x00, 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0x6D, 0x4E, + 0x00, 0x27, 0x01, 0x24, 0xFD, 0xF7, 0xD2, 0xFF, 0x28, 0x46, 0xFD, 0xF7, 0x45, 0xF9, 0x37, 0x60, + 0x29, 0x46, 0x38, 0x46, 0xFE, 0xF7, 0x08, 0xFE, 0x34, 0x60, 0xEB, 0x6E, 0x13, 0xF4, 0x80, 0x16, + 0x11, 0xD0, 0x18, 0x03, 0x71, 0xD5, 0x28, 0x46, 0xFE, 0xF7, 0x80, 0xF8, 0x01, 0x28, 0x04, 0x46, + 0x08, 0xBF, 0x05, 0x27, 0x01, 0x37, 0x04, 0x2F, 0xF5, 0xD9, 0x00, 0x2C, 0x6A, 0xD1, 0x01, 0x26, + 0x5D, 0x48, 0xFC, 0xF7, 0x39, 0xFB, 0xEB, 0x6E, 0x13, 0xF4, 0x00, 0x17, 0x0F, 0xD0, 0x19, 0x03, + 0x62, 0xD5, 0x00, 0x27, 0x28, 0x46, 0xFE, 0xF7, 0xEF, 0xF8, 0x01, 0x28, 0x04, 0x46, 0x08, 0xBF, + 0x05, 0x27, 0x01, 0x37, 0x04, 0x2F, 0xF5, 0xD9, 0xB4, 0xFA, 0x84, 0xF7, 0x7F, 0x09, 0xEB, 0x6E, + 0x13, 0xF4, 0x80, 0x09, 0x18, 0xD0, 0x01, 0x2F, 0x58, 0xD0, 0x1A, 0x03, 0x51, 0xD5, 0xB8, 0x46, + 0x28, 0x46, 0xFE, 0xF7, 0x4B, 0xFA, 0x01, 0x28, 0x04, 0x46, 0x08, 0xBF, 0x4F, 0xF0, 0x05, 0x08, + 0x08, 0xF1, 0x01, 0x08, 0xB8, 0xF1, 0x04, 0x0F, 0xF2, 0xD9, 0x00, 0x2C, 0x49, 0xD1, 0x4F, 0xF0, + 0x01, 0x09, 0x46, 0x48, 0xFC, 0xF7, 0x08, 0xFB, 0xEA, 0x6E, 0x12, 0xF4, 0x00, 0x03, 0x16, 0xD0, + 0x01, 0x2F, 0x45, 0xD0, 0x13, 0x03, 0x3E, 0xD5, 0xB8, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0xF2, 0xFB, + 0x01, 0x28, 0x04, 0x46, 0x08, 0xBF, 0x4F, 0xF0, 0x05, 0x08, 0x08, 0xF1, 0x01, 0x08, 0xB8, 0xF1, + 0x04, 0x0F, 0xF2, 0xD9, 0xB4, 0xBB, 0x3A, 0x48, 0xFC, 0xF7, 0xEE, 0xFA, 0x01, 0x23, 0xE8, 0x6E, + 0x3E, 0x43, 0x46, 0xEA, 0x09, 0x06, 0x1E, 0x43, 0x10, 0xF4, 0x00, 0x20, 0x5F, 0xD0, 0x86, 0xB3, + 0x34, 0x4F, 0x00, 0x26, 0x3B, 0x68, 0x01, 0x33, 0x0A, 0x2B, 0x3B, 0x60, 0x24, 0xD1, 0x32, 0x48, + 0xFC, 0xF7, 0xDA, 0xFA, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x28, 0x46, 0xFE, 0xF7, 0x0E, 0xF8, + 0x04, 0x46, 0x92, 0xE7, 0x00, 0x26, 0x96, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0x8D, 0xF8, 0x04, 0x46, + 0xA2, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xFA, 0xF9, 0x04, 0x46, 0xB6, 0xE7, 0x4F, 0xF0, 0x00, 0x09, + 0xBA, 0xE7, 0xB9, 0x46, 0xB8, 0xE7, 0x28, 0x46, 0xFE, 0xF7, 0xB4, 0xFB, 0x04, 0x46, 0xC9, 0xE7, + 0x00, 0x23, 0xCC, 0xE7, 0x3B, 0x46, 0xCA, 0xE7, 0x28, 0x46, 0xFF, 0xF7, 0x43, 0xFC, 0x04, 0x46, + 0x3E, 0x60, 0x28, 0x46, 0xFD, 0xF7, 0xB6, 0xFB, 0xAB, 0x6F, 0x23, 0xF4, 0xFF, 0x63, 0x23, 0xF0, + 0x02, 0x03, 0x1B, 0x05, 0x1B, 0x0D, 0x05, 0x2B, 0x14, 0xD1, 0x01, 0x21, 0x28, 0x46, 0xFE, 0xF7, + 0xCD, 0xF8, 0x02, 0x21, 0x06, 0x46, 0x28, 0x46, 0xFE, 0xF7, 0xC8, 0xF8, 0x30, 0x40, 0x03, 0x21, + 0x04, 0x40, 0x28, 0x46, 0xFE, 0xF7, 0xC2, 0xF8, 0x00, 0x21, 0x04, 0x40, 0x28, 0x46, 0xFE, 0xF7, + 0xBD, 0xF8, 0x04, 0x40, 0x0D, 0x4A, 0x20, 0x46, 0x13, 0x68, 0x23, 0xF0, 0x01, 0x03, 0x13, 0x60, + 0x52, 0xF8, 0x0C, 0x3C, 0x23, 0xF0, 0x07, 0x03, 0x42, 0xF8, 0x0C, 0x3C, 0xAB, 0xE7, 0x00, 0x2E, + 0xCF, 0xD0, 0xA8, 0xE7, 0x20, 0x03, 0x82, 0x04, 0xD9, 0x3B, 0x04, 0x00, 0xF0, 0x3B, 0x04, 0x00, + 0x06, 0x3C, 0x04, 0x00, 0xE8, 0x3D, 0x04, 0x00, 0x1D, 0x3C, 0x04, 0x00, 0x60, 0x00, 0x83, 0x04, + 0x10, 0xB5, 0x04, 0x46, 0xFD, 0xF7, 0xD8, 0xFE, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0xFF, 0xF7, + 0x0B, 0xBF, 0x00, 0x00, 0x0E, 0x4A, 0x38, 0xB5, 0x04, 0x46, 0x13, 0x68, 0x23, 0xF0, 0x80, 0x73, + 0x43, 0xF0, 0x02, 0x23, 0x13, 0x60, 0x93, 0x69, 0x43, 0xF4, 0x00, 0x43, 0x93, 0x61, 0xFF, 0xF7, + 0x6B, 0xFB, 0x08, 0x4B, 0x00, 0x22, 0x20, 0x46, 0x1A, 0x60, 0xFF, 0xF7, 0x39, 0xFB, 0x20, 0x46, + 0xFF, 0xF7, 0xDE, 0xFF, 0x05, 0x46, 0x20, 0x46, 0xFE, 0xF7, 0x10, 0xFD, 0x28, 0x46, 0x38, 0xBD, + 0x08, 0x00, 0x81, 0x04, 0x38, 0x00, 0x82, 0x04, 0x2D, 0xE9, 0xF3, 0x41, 0x0C, 0x46, 0x8F, 0x6F, + 0x48, 0x48, 0x17, 0xF4, 0x00, 0x07, 0x14, 0xBF, 0xD1, 0xE9, 0x1C, 0x78, 0xB8, 0x46, 0x46, 0x49, + 0xFC, 0xF7, 0x3A, 0xFA, 0x45, 0x4A, 0x13, 0x68, 0x43, 0xF4, 0x80, 0x73, 0x13, 0x60, 0x93, 0x68, + 0x23, 0xF0, 0x3F, 0x03, 0x93, 0x60, 0x00, 0xF0, 0xAF, 0xF8, 0x18, 0xB9, 0x40, 0x48, 0xFC, 0xF7, + 0x2B, 0xFA, 0x06, 0xE0, 0x3F, 0x48, 0xFC, 0xF7, 0x27, 0xFA, 0x20, 0x46, 0xFC, 0xF7, 0x88, 0xFF, + 0x18, 0xB9, 0x00, 0x20, 0x02, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xA3, 0x6F, 0xDD, 0x07, 0x10, 0xD5, + 0xA3, 0x6F, 0x18, 0x05, 0x13, 0xD4, 0x21, 0x68, 0x37, 0x48, 0xFC, 0xF7, 0x15, 0xFA, 0x61, 0x68, + 0x36, 0x48, 0xFC, 0xF7, 0x11, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0x9C, 0xFB, 0x68, 0xB9, 0x34, 0x48, + 0xDD, 0xE7, 0x20, 0x46, 0xFF, 0xF7, 0x02, 0xFE, 0x00, 0x28, 0xE9, 0xD1, 0xE1, 0xE7, 0x20, 0x46, + 0xFF, 0xF7, 0x9E, 0xFB, 0x00, 0x28, 0xE6, 0xD1, 0xDB, 0xE7, 0xE6, 0x69, 0xB3, 0x0F, 0x03, 0x2B, + 0x0C, 0xD1, 0x20, 0x46, 0xFC, 0xF7, 0x0C, 0xFE, 0xC6, 0xF3, 0x0D, 0x42, 0x05, 0x46, 0x82, 0x42, + 0x08, 0xD0, 0x01, 0x46, 0x27, 0x48, 0xFC, 0xF7, 0xEF, 0xF9, 0xCA, 0xE7, 0x02, 0x2B, 0x20, 0xD1, + 0xC6, 0xF3, 0x0D, 0x45, 0x24, 0x4B, 0x29, 0x46, 0x24, 0x48, 0x1B, 0x68, 0xA3, 0x6F, 0x00, 0x93, + 0xD4, 0xE9, 0x06, 0x23, 0xFC, 0xF7, 0xE0, 0xF9, 0xA3, 0x6F, 0x28, 0x46, 0xD9, 0x01, 0x4F, 0xF4, + 0x80, 0x51, 0x41, 0xBF, 0x1E, 0x4A, 0x13, 0x68, 0x43, 0xF0, 0x09, 0x03, 0x13, 0x60, 0xA3, 0x6F, + 0x1A, 0x02, 0x48, 0xBF, 0xC4, 0xE9, 0x1C, 0x78, 0xFC, 0xF7, 0xA6, 0xFD, 0x50, 0xB9, 0x28, 0x46, + 0xA8, 0xE7, 0xB6, 0xB2, 0x20, 0x46, 0xFC, 0xF7, 0xDB, 0xFD, 0x46, 0xEA, 0x00, 0x46, 0x05, 0x46, + 0xE6, 0x61, 0xD7, 0xE7, 0xA3, 0x6F, 0x5B, 0x06, 0x9B, 0xD4, 0x20, 0x46, 0xFF, 0xF7, 0x4A, 0xFB, + 0x00, 0x28, 0xAC, 0xD0, 0x4F, 0xF4, 0x80, 0x51, 0x28, 0x46, 0xFC, 0xF7, 0x8D, 0xFD, 0x00, 0x28, + 0xE5, 0xD0, 0x8E, 0xE7, 0x3A, 0x3C, 0x04, 0x00, 0x33, 0x3C, 0x04, 0x00, 0x60, 0x01, 0x00, 0x03, + 0x54, 0x3C, 0x04, 0x00, 0x78, 0x3C, 0x04, 0x00, 0x8A, 0x3C, 0x04, 0x00, 0x9C, 0x3C, 0x04, 0x00, + 0xCD, 0x3C, 0x04, 0x00, 0xE7, 0x3C, 0x04, 0x00, 0x00, 0x62, 0x00, 0x03, 0x27, 0x3D, 0x04, 0x00, + 0x30, 0x00, 0x82, 0x04, 0x80, 0xEA, 0x01, 0x20, 0x08, 0x23, 0x48, 0xF2, 0x05, 0x01, 0x42, 0x00, + 0x01, 0x3B, 0x9B, 0xB2, 0x00, 0x04, 0x92, 0xB2, 0x4C, 0xBF, 0x82, 0xEA, 0x01, 0x00, 0x10, 0x46, + 0x00, 0x2B, 0xF4, 0xD1, 0x70, 0x47, 0x38, 0xB5, 0x0D, 0x46, 0x04, 0x46, 0x2C, 0x44, 0xFF, 0xF7, + 0xE9, 0xFF, 0x44, 0xEA, 0x00, 0x40, 0x38, 0xBD, 0x70, 0xB5, 0x00, 0x20, 0xFC, 0xF7, 0x0E, 0xFD, + 0x01, 0x25, 0x04, 0x46, 0x29, 0x46, 0x00, 0x20, 0xFF, 0xF7, 0xED, 0xFF, 0x84, 0x42, 0x05, 0xD0, + 0x01, 0x35, 0xED, 0xB2, 0x11, 0x2D, 0xF5, 0xD1, 0x00, 0x20, 0x0F, 0xE0, 0x01, 0x24, 0x20, 0x46, + 0xFC, 0xF7, 0xFC, 0xFC, 0x29, 0x46, 0x06, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0xDC, 0xFF, 0x86, 0x42, + 0xF2, 0xD1, 0x01, 0x34, 0xA4, 0xB2, 0x05, 0x2C, 0xF1, 0xD1, 0x01, 0x20, 0x70, 0xBD, 0x00, 0x00, + 0x01, 0x20, 0x51, 0xE2, 0x1E, 0xFF, 0x2F, 0x01, 0x36, 0x00, 0x00, 0x3A, 0x01, 0x00, 0x50, 0xE1, + 0x22, 0x00, 0x00, 0x9A, 0x02, 0x00, 0x11, 0xE1, 0x23, 0x00, 0x00, 0x0A, 0x0E, 0x02, 0x11, 0xE3, + 0x81, 0x11, 0xA0, 0x01, 0x08, 0x30, 0xA0, 0x03, 0x01, 0x30, 0xA0, 0x13, 0x01, 0x02, 0x51, 0xE3, + 0x00, 0x00, 0x51, 0x31, 0x01, 0x12, 0xA0, 0x31, 0x03, 0x32, 0xA0, 0x31, 0xFA, 0xFF, 0xFF, 0x3A, + 0x02, 0x01, 0x51, 0xE3, 0x00, 0x00, 0x51, 0x31, 0x81, 0x10, 0xA0, 0x31, 0x83, 0x30, 0xA0, 0x31, + 0xFA, 0xFF, 0xFF, 0x3A, 0x00, 0x20, 0xA0, 0xE3, 0x01, 0x00, 0x50, 0xE1, 0x01, 0x00, 0x40, 0x20, + 0x03, 0x20, 0x82, 0x21, 0xA1, 0x00, 0x50, 0xE1, 0xA1, 0x00, 0x40, 0x20, 0xA3, 0x20, 0x82, 0x21, + 0x21, 0x01, 0x50, 0xE1, 0x21, 0x01, 0x40, 0x20, 0x23, 0x21, 0x82, 0x21, 0xA1, 0x01, 0x50, 0xE1, + 0xA1, 0x01, 0x40, 0x20, 0xA3, 0x21, 0x82, 0x21, 0x00, 0x00, 0x50, 0xE3, 0x23, 0x32, 0xB0, 0x11, + 0x21, 0x12, 0xA0, 0x11, 0xEF, 0xFF, 0xFF, 0x1A, 0x02, 0x00, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, + 0x01, 0x00, 0xA0, 0x03, 0x00, 0x00, 0xA0, 0x13, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x08, 0x51, 0xE3, + 0x21, 0x18, 0xA0, 0x21, 0x10, 0x20, 0xA0, 0x23, 0x00, 0x20, 0xA0, 0x33, 0x01, 0x0C, 0x51, 0xE3, + 0x21, 0x14, 0xA0, 0x21, 0x08, 0x20, 0x82, 0x22, 0x10, 0x00, 0x51, 0xE3, 0x21, 0x12, 0xA0, 0x21, + 0x04, 0x20, 0x82, 0x22, 0x04, 0x00, 0x51, 0xE3, 0x03, 0x20, 0x82, 0x82, 0xA1, 0x20, 0x82, 0x90, + 0x30, 0x02, 0xA0, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x50, 0xE3, 0x00, 0x00, 0xE0, 0x13, + 0x59, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x51, 0xE3, 0xFA, 0xFF, 0xFF, 0x0A, 0x03, 0x40, 0x2D, 0xE9, + 0xBE, 0xFF, 0xFF, 0xEB, 0x06, 0x40, 0xBD, 0xE8, 0x92, 0x00, 0x03, 0xE0, 0x03, 0x10, 0x41, 0xE0, + 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x51, 0xE3, 0x43, 0x00, 0x00, 0x0A, 0x01, 0xC0, 0x20, 0xE0, + 0x00, 0x10, 0x61, 0x42, 0x01, 0x20, 0x51, 0xE2, 0x27, 0x00, 0x00, 0x0A, 0x00, 0x30, 0xB0, 0xE1, + 0x00, 0x30, 0x60, 0x42, 0x01, 0x00, 0x53, 0xE1, 0x26, 0x00, 0x00, 0x9A, 0x02, 0x00, 0x11, 0xE1, + 0x28, 0x00, 0x00, 0x0A, 0x0E, 0x02, 0x11, 0xE3, 0x81, 0x11, 0xA0, 0x01, 0x08, 0x20, 0xA0, 0x03, + 0x01, 0x20, 0xA0, 0x13, 0x01, 0x02, 0x51, 0xE3, 0x03, 0x00, 0x51, 0x31, 0x01, 0x12, 0xA0, 0x31, + 0x02, 0x22, 0xA0, 0x31, 0xFA, 0xFF, 0xFF, 0x3A, 0x02, 0x01, 0x51, 0xE3, 0x03, 0x00, 0x51, 0x31, + 0x81, 0x10, 0xA0, 0x31, 0x82, 0x20, 0xA0, 0x31, 0xFA, 0xFF, 0xFF, 0x3A, 0x00, 0x00, 0xA0, 0xE3, + 0x01, 0x00, 0x53, 0xE1, 0x01, 0x30, 0x43, 0x20, 0x02, 0x00, 0x80, 0x21, 0xA1, 0x00, 0x53, 0xE1, + 0xA1, 0x30, 0x43, 0x20, 0xA2, 0x00, 0x80, 0x21, 0x21, 0x01, 0x53, 0xE1, 0x21, 0x31, 0x43, 0x20, + 0x22, 0x01, 0x80, 0x21, 0xA1, 0x01, 0x53, 0xE1, 0xA1, 0x31, 0x43, 0x20, 0xA2, 0x01, 0x80, 0x21, + 0x00, 0x00, 0x53, 0xE3, 0x22, 0x22, 0xB0, 0x11, 0x21, 0x12, 0xA0, 0x11, 0xEF, 0xFF, 0xFF, 0x1A, + 0x00, 0x00, 0x5C, 0xE3, 0x00, 0x00, 0x60, 0x42, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x3C, 0xE1, + 0x00, 0x00, 0x60, 0x42, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0xA0, 0x33, 0xCC, 0x0F, 0xA0, 0x01, + 0x01, 0x00, 0x80, 0x03, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x08, 0x51, 0xE3, 0x21, 0x18, 0xA0, 0x21, + 0x10, 0x20, 0xA0, 0x23, 0x00, 0x20, 0xA0, 0x33, 0x01, 0x0C, 0x51, 0xE3, 0x21, 0x14, 0xA0, 0x21, + 0x08, 0x20, 0x82, 0x22, 0x10, 0x00, 0x51, 0xE3, 0x21, 0x12, 0xA0, 0x21, 0x04, 0x20, 0x82, 0x22, + 0x04, 0x00, 0x51, 0xE3, 0x03, 0x20, 0x82, 0x82, 0xA1, 0x20, 0x82, 0x90, 0x00, 0x00, 0x5C, 0xE3, + 0x33, 0x02, 0xA0, 0xE1, 0x00, 0x00, 0x60, 0x42, 0x1E, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x50, 0xE3, + 0x02, 0x01, 0xE0, 0xC3, 0x02, 0x01, 0xA0, 0xB3, 0x07, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x51, 0xE3, + 0xF9, 0xFF, 0xFF, 0x0A, 0x03, 0x40, 0x2D, 0xE9, 0xB3, 0xFF, 0xFF, 0xEB, 0x06, 0x40, 0xBD, 0xE8, + 0x92, 0x00, 0x03, 0xE0, 0x03, 0x10, 0x41, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1, + 0x00, 0x00, 0x53, 0xE3, 0x00, 0x00, 0x52, 0x03, 0x04, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x51, 0xE3, + 0x00, 0x00, 0x50, 0x03, 0x00, 0x10, 0xE0, 0x13, 0x00, 0x00, 0xE0, 0x13, 0xF6, 0xFF, 0xFF, 0xEA, + 0x08, 0xD0, 0x4D, 0xE2, 0x00, 0x60, 0x2D, 0xE9, 0x03, 0x00, 0x00, 0xEB, 0x04, 0xE0, 0x9D, 0xE5, + 0x08, 0xD0, 0x8D, 0xE2, 0x0C, 0x00, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0xF0, 0x47, 0x2D, 0xE9, + 0x03, 0x60, 0xA0, 0xE1, 0x02, 0x00, 0x50, 0xE1, 0x06, 0x30, 0xD1, 0xE0, 0x00, 0x40, 0xA0, 0xE1, + 0x00, 0x00, 0xA0, 0x33, 0x01, 0x50, 0xA0, 0xE1, 0x20, 0x70, 0x9D, 0xE5, 0x00, 0x10, 0xA0, 0x31, + 0x3B, 0x00, 0x00, 0x3A, 0x06, 0x10, 0xA0, 0xE1, 0x02, 0x00, 0xA0, 0xE1, 0x02, 0x80, 0xA0, 0xE1, + 0x3B, 0x00, 0x00, 0xEB, 0x05, 0x10, 0xA0, 0xE1, 0x00, 0x90, 0xA0, 0xE1, 0x04, 0x00, 0xA0, 0xE1, + 0x37, 0x00, 0x00, 0xEB, 0x00, 0xC0, 0x49, 0xE0, 0x16, 0x3C, 0xA0, 0xE1, 0x20, 0x60, 0x4C, 0xE2, + 0x18, 0x36, 0x83, 0xE1, 0x20, 0xE0, 0x6C, 0xE2, 0x18, 0x2C, 0xA0, 0xE1, 0x38, 0x3E, 0x83, 0xE1, + 0x02, 0x00, 0x54, 0xE1, 0x03, 0x10, 0xD5, 0xE0, 0x00, 0x00, 0xA0, 0x33, 0x00, 0x10, 0xA0, 0x31, + 0x05, 0x00, 0x00, 0x3A, 0x01, 0x00, 0xA0, 0xE3, 0x02, 0x40, 0x54, 0xE0, 0x10, 0x16, 0xA0, 0xE1, + 0x30, 0x1E, 0x81, 0xE1, 0x03, 0x50, 0xC5, 0xE0, 0x10, 0x0C, 0xA0, 0xE1, 0x00, 0x00, 0x5C, 0xE3, + 0x1F, 0x00, 0x00, 0x0A, 0xA2, 0x20, 0xA0, 0xE1, 0x83, 0x2F, 0x82, 0xE1, 0x0C, 0x80, 0xA0, 0xE1, + 0xA3, 0x30, 0xA0, 0xE1, 0x07, 0x00, 0x00, 0xEA, 0x02, 0x40, 0x54, 0xE0, 0x03, 0x50, 0xC5, 0xE0, + 0x04, 0x40, 0x94, 0xE0, 0x05, 0x50, 0xA5, 0xE0, 0x01, 0x40, 0x94, 0xE2, 0x00, 0x50, 0xA5, 0xE2, + 0x01, 0x80, 0x58, 0xE2, 0x06, 0x00, 0x00, 0x0A, 0x02, 0x00, 0x54, 0xE1, 0x03, 0x90, 0xD5, 0xE0, + 0xF4, 0xFF, 0xFF, 0x2A, 0x04, 0x40, 0x94, 0xE0, 0x05, 0x50, 0xA5, 0xE0, 0x01, 0x80, 0x58, 0xE2, + 0xF8, 0xFF, 0xFF, 0x1A, 0x04, 0x00, 0x90, 0xE0, 0x34, 0x4C, 0xA0, 0xE1, 0x15, 0x4E, 0x84, 0xE1, + 0x35, 0x46, 0x84, 0xE1, 0x05, 0x10, 0xA1, 0xE0, 0x35, 0x5C, 0xA0, 0xE1, 0x15, 0x3C, 0xA0, 0xE1, + 0x14, 0x36, 0x83, 0xE1, 0x14, 0xCC, 0xA0, 0xE1, 0x34, 0x3E, 0x83, 0xE1, 0x0C, 0x00, 0x50, 0xE0, + 0x03, 0x10, 0xC1, 0xE0, 0x00, 0x00, 0x57, 0xE3, 0x30, 0x00, 0x87, 0x18, 0xF0, 0x47, 0xBD, 0xE8, + 0x1E, 0xFF, 0x2F, 0xE1, 0x10, 0x40, 0x2D, 0xE9, 0x00, 0x00, 0x51, 0xE3, 0x02, 0x00, 0x00, 0x1A, + 0x05, 0x00, 0x00, 0xEB, 0x20, 0x00, 0x80, 0xE2, 0x01, 0x00, 0x00, 0xEA, 0x01, 0x00, 0xA0, 0xE1, + 0x01, 0x00, 0x00, 0xEB, 0x10, 0x40, 0xBD, 0xE8, 0x1E, 0xFF, 0x2F, 0xE1, 0x1C, 0x10, 0xA0, 0xE3, + 0x01, 0x08, 0x50, 0xE3, 0x20, 0x08, 0xA0, 0x21, 0x10, 0x10, 0x41, 0x22, 0x01, 0x0C, 0x50, 0xE3, + 0x20, 0x04, 0xA0, 0x21, 0x08, 0x10, 0x41, 0x22, 0x10, 0x00, 0x50, 0xE3, 0x20, 0x02, 0xA0, 0x21, + 0x04, 0x10, 0x41, 0x22, 0x08, 0x20, 0x8F, 0xE2, 0x00, 0x00, 0xD2, 0xE7, 0x01, 0x00, 0x80, 0xE0, + 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0x03, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x68, 0xFE, 0xFF, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x00, 0x54, 0x72, 0x75, + 0x65, 0x00, 0x46, 0x61, 0x6C, 0x73, 0x65, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, + 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10, 0x04, 0x45, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, + 0x05, 0x35, 0x30, 0x00, 0x50, 0x60, 0x00, 0x00, 0x00, 0x20, 0x28, 0x38, 0x50, 0x50, 0x00, 0x00, + 0x00, 0x30, 0x30, 0x30, 0x50, 0x50, 0x00, 0x00, 0x08, 0x20, 0x20, 0x28, 0x20, 0x20, 0x20, 0x00, + 0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x70, 0x78, 0x78, 0x78, 0x70, 0x78, 0x00, + 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x07, 0x28, 0x6E, 0x75, 0x6C, 0x6C, 0x29, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x5A, 0x5A, 0x5A, 0x5A, + 0x55, 0x55, 0x55, 0x55, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, - 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, - 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, - 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, - 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, - 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08, 0x00, 0x04, 0x00, 0x20, 0x00, 0x08, 0x00, - 0x49, 0x6E, 0x69, 0x74, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x44, 0x6F, 0x6E, 0x65, 0x2C, 0x20, - 0x44, 0x52, 0x41, 0x4D, 0x20, 0x53, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x4D, 0x0A, - 0x00, 0x53, 0x65, 0x74, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x56, 0x6F, 0x6C, 0x74, 0x61, 0x67, - 0x65, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x6D, 0x76, 0x0A, 0x00, 0x53, 0x65, 0x74, 0x20, 0x44, - 0x44, 0x52, 0x34, 0x20, 0x32, 0x35, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x56, 0x6F, 0x6C, 0x74, - 0x61, 0x67, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x6D, 0x76, 0x0A, 0x00, 0x74, 0x68, 0x65, - 0x20, 0x63, 0x68, 0x69, 0x70, 0x20, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, 0x30, 0x78, 0x25, 0x78, - 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x73, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x74, 0x65, - 0x73, 0x74, 0x20, 0x46, 0x41, 0x49, 0x4C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x25, 0x78, 0x20, 0x21, - 0x3D, 0x20, 0x25, 0x78, 0x20, 0x61, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, - 0x25, 0x78, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x73, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x20, - 0x74, 0x65, 0x73, 0x74, 0x20, 0x4F, 0x4B, 0x2E, 0x0A, 0x00, 0x50, 0x4F, 0x57, 0x45, 0x52, 0x20, - 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x45, 0x52, 0x52, 0x4F, 0x52, 0x21, 0x0A, 0x00, - 0x44, 0x52, 0x41, 0x4D, 0x5F, 0x56, 0x43, 0x43, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x6F, 0x20, - 0x25, 0x64, 0x20, 0x6D, 0x76, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x64, 0x72, 0x61, - 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x78, 0x5F, 0x64, 0x71, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5B, - 0x25, 0x64, 0x5D, 0x20, 0x3C, 0x3D, 0x20, 0x25, 0x64, 0x20, 0x70, 0x73, 0x20, 0x0A, 0x00, 0x65, - 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x78, 0x5F, 0x64, - 0x71, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5B, 0x25, 0x64, 0x5D, 0x20, 0x3E, 0x20, 0x25, 0x64, - 0x70, 0x73, 0x20, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, + 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x04, 0x00, + 0x08, 0x00, 0x04, 0x00, 0x20, 0x00, 0x08, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x3A, 0x20, 0x67, 0x69, + 0x76, 0x65, 0x6E, 0x20, 0x64, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x6C, 0x6B, 0x20, 0x25, 0x64, 0x4D, + 0x48, 0x7A, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x2E, 0x20, + 0x75, 0x73, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, + 0x6D, 0x0A, 0x00, 0x49, 0x6E, 0x69, 0x74, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x44, 0x6F, 0x6E, + 0x65, 0x2C, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x53, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x25, + 0x64, 0x4D, 0x0A, 0x00, 0x53, 0x65, 0x74, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x56, 0x6F, 0x6C, + 0x74, 0x61, 0x67, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x6D, 0x76, 0x0A, 0x00, 0x53, 0x65, + 0x74, 0x20, 0x44, 0x44, 0x52, 0x34, 0x20, 0x32, 0x35, 0x20, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x56, + 0x6F, 0x6C, 0x74, 0x61, 0x67, 0x65, 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x6D, 0x76, 0x0A, 0x00, + 0x5B, 0x25, 0x35, 0x6C, 0x75, 0x2E, 0x25, 0x30, 0x36, 0x6C, 0x75, 0x5D, 0x5B, 0x49, 0x5D, 0x20, + 0x00, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x70, 0x20, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, + 0x30, 0x78, 0x25, 0x78, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x73, 0x69, 0x6D, 0x70, 0x6C, + 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x46, 0x41, 0x49, 0x4C, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, + 0x25, 0x78, 0x20, 0x21, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x61, 0x74, 0x20, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x73, 0x69, 0x6D, + 0x70, 0x6C, 0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x4F, 0x4B, 0x2E, 0x0A, 0x00, 0x50, 0x4F, + 0x57, 0x45, 0x52, 0x20, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4E, 0x47, 0x20, 0x45, 0x52, 0x52, 0x4F, + 0x52, 0x21, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x5F, 0x56, 0x43, 0x43, 0x20, 0x73, 0x65, 0x74, + 0x20, 0x74, 0x6F, 0x20, 0x25, 0x64, 0x20, 0x6D, 0x76, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, + 0x3A, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x78, 0x5F, 0x64, 0x71, 0x5F, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x5B, 0x25, 0x64, 0x5D, 0x20, 0x3C, 0x3D, 0x20, 0x25, 0x64, 0x20, 0x70, 0x73, + 0x20, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, + 0x72, 0x78, 0x5F, 0x64, 0x71, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5B, 0x25, 0x64, 0x5D, 0x20, + 0x3E, 0x20, 0x25, 0x64, 0x70, 0x73, 0x20, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, + 0x45, 0x42, 0x55, 0x47, 0x5D, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, + 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, + 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, + 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, - 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x25, 0x64, 0x2D, - 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, - 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, - 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, - 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, - 0x55, 0x47, 0x5D, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, - 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, - 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x25, 0x64, 0x2D, 0x25, - 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, - 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x70, 0x68, 0x79, 0x5F, 0x64, 0x66, - 0x73, 0x5F, 0x63, 0x6C, 0x6B, 0x25, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x4D, 0x0A, 0x00, 0x65, - 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x68, 0x79, 0x5F, 0x64, 0x66, 0x73, 0x5F, 0x63, 0x6C, - 0x6B, 0x25, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x4D, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x67, - 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, 0x64, 0x78, 0x5F, 0x6C, - 0x6F, 0x77, 0x20, 0x31, 0x36, 0x62, 0x69, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x72, - 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x20, 0x0A, 0x00, - 0x64, 0x78, 0x5F, 0x68, 0x69, 0x67, 0x68, 0x20, 0x31, 0x36, 0x62, 0x69, 0x74, 0x20, 0x72, 0x65, - 0x61, 0x64, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, - 0x72, 0x20, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x64, 0x78, 0x30, 0x5F, 0x64, 0x71, - 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, - 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, - 0x64, 0x20, 0x64, 0x78, 0x31, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, - 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, - 0x25, 0x78, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x64, 0x78, 0x32, 0x5F, 0x64, 0x71, - 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, - 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, - 0x64, 0x20, 0x64, 0x78, 0x33, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, - 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, - 0x25, 0x78, 0x20, 0x0A, 0x00, 0x64, 0x78, 0x5F, 0x6C, 0x6F, 0x77, 0x20, 0x31, 0x36, 0x62, 0x69, - 0x74, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x20, 0x0A, 0x00, 0x64, 0x78, 0x5F, 0x68, 0x69, 0x67, - 0x68, 0x20, 0x31, 0x36, 0x62, 0x69, 0x74, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x72, - 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x20, 0x0A, 0x00, - 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x64, 0x78, 0x30, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, + 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, + 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, + 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, + 0x25, 0x78, 0x0A, 0x0D, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, + 0x25, 0x64, 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x20, 0x25, 0x64, + 0x2D, 0x25, 0x64, 0x2C, 0x25, 0x64, 0x2C, 0x30, 0x78, 0x25, 0x78, 0x0A, 0x0D, 0x00, 0x70, 0x68, + 0x79, 0x5F, 0x64, 0x66, 0x73, 0x5F, 0x63, 0x6C, 0x6B, 0x25, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, + 0x4D, 0x0A, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3A, 0x20, 0x70, 0x68, 0x79, 0x5F, 0x64, 0x66, + 0x73, 0x5F, 0x63, 0x6C, 0x6B, 0x25, 0x64, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x4D, 0x20, 0x72, 0x65, + 0x61, 0x64, 0x20, 0x67, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, + 0x64, 0x78, 0x5F, 0x6C, 0x6F, 0x77, 0x20, 0x31, 0x36, 0x62, 0x69, 0x74, 0x20, 0x72, 0x65, 0x61, + 0x64, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, + 0x20, 0x20, 0x0A, 0x00, 0x64, 0x78, 0x5F, 0x68, 0x69, 0x67, 0x68, 0x20, 0x31, 0x36, 0x62, 0x69, + 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, + 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x64, 0x78, + 0x30, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, + 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x64, 0x78, 0x31, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, - 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x64, - 0x78, 0x31, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, - 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x64, 0x78, 0x32, 0x5F, 0x64, 0x71, 0x25, 0x64, - 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, - 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x20, 0x64, 0x78, 0x33, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, - 0x78, 0x20, 0x0A, 0x00, 0x4D, 0x58, 0x5F, 0x53, 0x43, 0x48, 0x45, 0x44, 0x28, 0x30, 0x78, 0x30, - 0x34, 0x38, 0x32, 0x30, 0x32, 0x35, 0x30, 0x29, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, - 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6C, 0x74, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, - 0x63, 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x2C, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x20, 0x70, 0x61, - 0x73, 0x73, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, + 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x64, 0x78, + 0x32, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, + 0x00, 0x72, 0x65, 0x61, 0x64, 0x20, 0x64, 0x78, 0x33, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, + 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, + 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x64, 0x78, 0x5F, 0x6C, 0x6F, 0x77, 0x20, + 0x31, 0x36, 0x62, 0x69, 0x74, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x72, 0x61, 0x69, + 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x20, 0x0A, 0x00, 0x64, 0x78, + 0x5F, 0x68, 0x69, 0x67, 0x68, 0x20, 0x31, 0x36, 0x62, 0x69, 0x74, 0x20, 0x77, 0x72, 0x69, 0x74, + 0x65, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, + 0x20, 0x20, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x64, 0x78, 0x30, 0x5F, 0x64, 0x71, + 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, + 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x20, 0x64, 0x78, 0x31, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, + 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, + 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x64, 0x78, 0x32, 0x5F, + 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x77, + 0x72, 0x69, 0x74, 0x65, 0x20, 0x64, 0x78, 0x33, 0x5F, 0x64, 0x71, 0x25, 0x64, 0x20, 0x64, 0x65, + 0x6C, 0x61, 0x79, 0x5F, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5F, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, + 0x3D, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x4D, 0x58, 0x5F, 0x53, 0x43, 0x48, 0x45, 0x44, + 0x28, 0x30, 0x78, 0x30, 0x34, 0x38, 0x32, 0x30, 0x32, 0x35, 0x30, 0x29, 0x20, 0x3D, 0x20, 0x25, + 0x78, 0x20, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x63, 0x6F, 0x6E, 0x66, 0x69, 0x67, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x2C, 0x6D, 0x74, 0x65, 0x73, - 0x74, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, - 0x42, 0x55, 0x47, 0x5D, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, 0x20, 0x6C, 0x65, 0x73, - 0x73, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x33, 0x36, 0x30, 0x4D, 0x2C, 0x6D, 0x74, 0x65, 0x73, - 0x74, 0x20, 0x73, 0x74, 0x69, 0x6C, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, - 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x6C, 0x6F, 0x6F, 0x70, - 0x20, 0x3D, 0x20, 0x30, 0x2C, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0A, - 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x64, 0x72, 0x61, - 0x6D, 0x5F, 0x63, 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x65, - 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, - 0x55, 0x47, 0x5D, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x20, 0x3E, 0x3D, - 0x20, 0x33, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, - 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, 0x3D, 0x25, - 0x64, 0x20, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, - 0x3D, 0x25, 0x64, 0x20, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x20, 0x73, 0x74, 0x69, 0x6C, 0x6C, 0x20, - 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, - 0x42, 0x55, 0x47, 0x5D, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0x5F, 0x66, - 0x6C, 0x61, 0x67, 0x20, 0x3E, 0x3D, 0x20, 0x33, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, - 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x65, 0x73, 0x63, 0x61, - 0x6E, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x31, 0x20, 0x3D, 0x20, 0x25, - 0x78, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x32, 0x20, 0x3D, 0x20, 0x25, - 0x78, 0x20, 0x0A, 0x00, 0x70, 0x61, 0x72, 0x61, 0x2D, 0x3E, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, - 0x70, 0x72, 0x31, 0x33, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, - 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, - 0x31, 0x31, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, - 0x31, 0x32, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, - 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x66, 0x61, 0x69, 0x6C, - 0x5F, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x3E, 0x20, 0x33, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, - 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x33, 0x32, 0x62, 0x69, 0x74, 0x2C, 0x32, 0x20, 0x72, - 0x61, 0x6E, 0x6B, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x75, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, - 0x42, 0x55, 0x47, 0x5D, 0x33, 0x32, 0x62, 0x69, 0x74, 0x2C, 0x31, 0x20, 0x72, 0x61, 0x6E, 0x6B, + 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, + 0x42, 0x55, 0x47, 0x5D, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x63, 0x6F, 0x6E, 0x66, + 0x69, 0x67, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x2C, + 0x6D, 0x74, 0x65, 0x73, 0x74, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, + 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, + 0x20, 0x6C, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x33, 0x36, 0x30, 0x4D, 0x2C, + 0x6D, 0x74, 0x65, 0x73, 0x74, 0x20, 0x73, 0x74, 0x69, 0x6C, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, + 0x72, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, + 0x6C, 0x6F, 0x6F, 0x70, 0x20, 0x3D, 0x20, 0x30, 0x2C, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x66, + 0x61, 0x69, 0x6C, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, + 0x5D, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x65, 0x73, 0x63, + 0x61, 0x6E, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, + 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x66, 0x61, 0x69, + 0x6C, 0x20, 0x3E, 0x3D, 0x20, 0x33, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, + 0x42, 0x55, 0x47, 0x5D, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x63, + 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x65, 0x73, 0x63, 0x61, 0x6E, 0x2C, 0x64, 0x72, 0x61, 0x6D, + 0x5F, 0x63, 0x6C, 0x6B, 0x3D, 0x25, 0x64, 0x20, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x20, 0x73, 0x74, + 0x69, 0x6C, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, + 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x5F, 0x66, 0x61, + 0x69, 0x6C, 0x5F, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x3E, 0x3D, 0x20, 0x33, 0x0A, 0x00, 0x5B, 0x41, + 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, + 0x65, 0x73, 0x63, 0x61, 0x6E, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x31, + 0x20, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x32, + 0x20, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x70, 0x61, 0x72, 0x61, 0x2D, 0x3E, 0x64, 0x72, + 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x33, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, + 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x64, 0x72, 0x61, 0x6D, + 0x5F, 0x74, 0x70, 0x72, 0x31, 0x31, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x64, 0x72, 0x61, 0x6D, + 0x5F, 0x74, 0x70, 0x72, 0x31, 0x32, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x5B, 0x41, + 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x6D, 0x74, 0x65, 0x73, 0x74, 0x5F, + 0x66, 0x61, 0x69, 0x6C, 0x5F, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x3E, 0x20, 0x33, 0x0A, 0x00, 0x5B, + 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x33, 0x32, 0x62, 0x69, 0x74, + 0x2C, 0x32, 0x20, 0x72, 0x61, 0x6E, 0x6B, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, + 0x67, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, + 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x33, 0x32, 0x62, 0x69, 0x74, 0x2C, 0x31, 0x20, + 0x72, 0x61, 0x6E, 0x6B, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, + 0x45, 0x42, 0x55, 0x47, 0x5D, 0x31, 0x36, 0x20, 0x62, 0x69, 0x74, 0x2C, 0x32, 0x20, 0x72, 0x61, + 0x6E, 0x6B, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, + 0x55, 0x47, 0x5D, 0x31, 0x36, 0x20, 0x62, 0x69, 0x74, 0x2C, 0x31, 0x20, 0x72, 0x61, 0x6E, 0x6B, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, - 0x5D, 0x31, 0x36, 0x20, 0x62, 0x69, 0x74, 0x2C, 0x32, 0x20, 0x72, 0x61, 0x6E, 0x6B, 0x73, 0x20, - 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x21, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x31, - 0x36, 0x20, 0x62, 0x69, 0x74, 0x2C, 0x31, 0x20, 0x72, 0x61, 0x6E, 0x6B, 0x73, 0x20, 0x74, 0x72, - 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x21, 0x0A, - 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x33, 0x47, 0x42, - 0x20, 0x61, 0x75, 0x74, 0x6F, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, - 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x33, 0x20, 0x3D, 0x20, 0x25, 0x78, - 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5D, 0x31, 0x2E, - 0x35, 0x47, 0x42, 0x20, 0x61, 0x75, 0x74, 0x6F, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x65, 0x6E, 0x61, - 0x62, 0x6C, 0x65, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x33, 0x20, 0x3D, - 0x20, 0x25, 0x78, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x6C, 0x65, 0x76, 0x65, 0x6C, - 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x0A, 0x00, 0x72, 0x65, 0x61, 0x64, - 0x5F, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, - 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, - 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x72, 0x65, - 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x65, 0x6E, 0x20, 0x0A, 0x00, 0x56, - 0x30, 0x2E, 0x36, 0x39, 0x36, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, - 0x44, 0x52, 0x49, 0x56, 0x45, 0x20, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0x20, 0x25, 0x73, 0x0A, 0x00, - 0x69, 0x63, 0x20, 0x63, 0x61, 0x6E, 0x74, 0x20, 0x6D, 0x61, 0x74, 0x63, 0x68, 0x20, 0x61, 0x78, - 0x70, 0x2C, 0x20, 0x70, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x2E, - 0x2E, 0x2E, 0x0A, 0x00, 0x63, 0x68, 0x69, 0x70, 0x20, 0x69, 0x64, 0x20, 0x63, 0x68, 0x65, 0x63, - 0x6B, 0x20, 0x4F, 0x4B, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x43, 0x4C, 0x4B, 0x20, 0x3D, - 0x25, 0x64, 0x20, 0x4D, 0x48, 0x5A, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x54, 0x79, 0x70, - 0x65, 0x20, 0x3D, 0x25, 0x64, 0x20, 0x28, 0x33, 0x3A, 0x44, 0x44, 0x52, 0x33, 0x2C, 0x34, 0x3A, - 0x44, 0x44, 0x52, 0x34, 0x2C, 0x37, 0x3A, 0x4C, 0x50, 0x44, 0x44, 0x52, 0x33, 0x2C, 0x38, 0x3A, - 0x4C, 0x50, 0x44, 0x44, 0x52, 0x34, 0x29, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x69, 0x6E, - 0x69, 0x74, 0x69, 0x61, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x3A, 0x20, 0x31, 0x20, - 0x21, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x53, 0x49, 0x5A, 0x45, 0x20, 0x65, 0x72, 0x72, - 0x6F, 0x72, 0x21, 0x61, 0x75, 0x74, 0x6F, 0x5F, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x64, 0x72, 0x61, - 0x6D, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x2C, 0x61, 0x63, 0x74, 0x75, - 0x61, 0x6C, 0x5F, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x25, - 0x64, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x53, 0x49, 0x5A, 0x45, 0x20, 0x3D, 0x25, 0x64, - 0x20, 0x4D, 0x42, 0x79, 0x74, 0x65, 0x73, 0x2C, 0x20, 0x70, 0x61, 0x72, 0x61, 0x31, 0x20, 0x3D, - 0x20, 0x25, 0x78, 0x2C, 0x20, 0x70, 0x61, 0x72, 0x61, 0x32, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x2C, - 0x20, 0x74, 0x70, 0x72, 0x31, 0x33, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x0A, 0x00 + 0x5D, 0x33, 0x47, 0x42, 0x20, 0x61, 0x75, 0x74, 0x6F, 0x73, 0x63, 0x61, 0x6E, 0x20, 0x65, 0x6E, + 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, 0x31, 0x33, 0x20, + 0x3D, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x5B, 0x41, 0x55, 0x54, 0x4F, 0x20, 0x44, 0x45, 0x42, 0x55, + 0x47, 0x5D, 0x31, 0x2E, 0x35, 0x47, 0x42, 0x20, 0x61, 0x75, 0x74, 0x6F, 0x73, 0x63, 0x61, 0x6E, + 0x20, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x2C, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x74, 0x70, 0x72, + 0x31, 0x33, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x6C, + 0x65, 0x76, 0x65, 0x6C, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x0A, 0x00, + 0x72, 0x65, 0x61, 0x64, 0x5F, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, + 0x72, 0x6F, 0x72, 0x20, 0x0A, 0x00, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x74, 0x72, 0x61, 0x69, + 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, 0x0A, 0x00, 0x44, 0x52, 0x41, + 0x4D, 0x20, 0x72, 0x65, 0x74, 0x72, 0x61, 0x69, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x65, 0x6E, + 0x20, 0x0A, 0x00, 0x56, 0x30, 0x2E, 0x36, 0x39, 0x36, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x42, + 0x4F, 0x4F, 0x54, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x20, 0x49, 0x4E, 0x46, 0x4F, 0x3A, 0x20, + 0x25, 0x73, 0x0A, 0x00, 0x69, 0x63, 0x20, 0x63, 0x61, 0x6E, 0x74, 0x20, 0x6D, 0x61, 0x74, 0x63, + 0x68, 0x20, 0x61, 0x78, 0x70, 0x2C, 0x20, 0x70, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x63, 0x68, + 0x65, 0x63, 0x6B, 0x2E, 0x2E, 0x2E, 0x0A, 0x00, 0x63, 0x68, 0x69, 0x70, 0x20, 0x69, 0x64, 0x20, + 0x63, 0x68, 0x65, 0x63, 0x6B, 0x20, 0x4F, 0x4B, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x43, + 0x4C, 0x4B, 0x20, 0x3D, 0x25, 0x64, 0x20, 0x4D, 0x48, 0x5A, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, + 0x20, 0x54, 0x79, 0x70, 0x65, 0x20, 0x3D, 0x25, 0x64, 0x20, 0x28, 0x33, 0x3A, 0x44, 0x44, 0x52, + 0x33, 0x2C, 0x34, 0x3A, 0x44, 0x44, 0x52, 0x34, 0x2C, 0x37, 0x3A, 0x4C, 0x50, 0x44, 0x44, 0x52, + 0x33, 0x2C, 0x38, 0x3A, 0x4C, 0x50, 0x44, 0x44, 0x52, 0x34, 0x29, 0x0A, 0x00, 0x44, 0x52, 0x41, + 0x4D, 0x20, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20, + 0x3A, 0x20, 0x31, 0x20, 0x21, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x53, 0x49, 0x5A, 0x45, + 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x61, 0x75, 0x74, 0x6F, 0x5F, 0x73, 0x63, 0x61, 0x6E, + 0x5F, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x73, 0x69, 0x7A, 0x65, 0x20, 0x3D, 0x20, 0x25, 0x64, 0x2C, + 0x61, 0x63, 0x74, 0x75, 0x61, 0x6C, 0x5F, 0x64, 0x72, 0x61, 0x6D, 0x5F, 0x73, 0x69, 0x7A, 0x65, + 0x20, 0x3D, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x44, 0x52, 0x41, 0x4D, 0x20, 0x53, 0x49, 0x5A, 0x45, + 0x20, 0x3D, 0x25, 0x64, 0x20, 0x4D, 0x42, 0x79, 0x74, 0x65, 0x73, 0x2C, 0x20, 0x70, 0x61, 0x72, + 0x61, 0x31, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x70, 0x61, 0x72, 0x61, 0x32, 0x20, 0x3D, + 0x20, 0x25, 0x78, 0x2C, 0x20, 0x74, 0x70, 0x72, 0x31, 0x33, 0x20, 0x3D, 0x20, 0x25, 0x78, 0x0A, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x00, 0x00, 0x0C, 0x05, 0x0A, 0x0D, 0xFA, 0x30, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, + 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x48, + 0x33, 0x33, 0x27, 0x00, 0x1F, 0x18, 0x1C, 0x20, 0x13, 0x15, 0x15, 0x13, 0x21, 0x75, 0x00, 0x00, + 0x1F, 0x21, 0x23, 0x20 }; -unsigned long long init_dram_bin_length = 19789; +unsigned long long init_dram_bin_length = 21732; \ No newline at end of file diff --git a/board/100ask-ros/smhc_test/main.c b/board/100ask-ros/smhc_test/main.c index 43c4f929..4eda750a 100644 --- a/board/100ask-ros/smhc_test/main.c +++ b/board/100ask-ros/smhc_test/main.c @@ -20,7 +20,7 @@ #include extern sunxi_serial_t uart_dbg; - +extern uint32_t dram_para[32]; extern sunxi_i2c_t i2c_pmu; static void set_pmu_fin_voltage(char *power_name, uint32_t voltage) { @@ -56,7 +56,7 @@ int main(void) { pmu_axp2202_dump(&i2c_pmu); - printk_info("DRAM: DRAM Size = %dMB\n", sunxi_dram_init(NULL)); + printk_info("DRAM: DRAM Size = %dMB\n", sunxi_dram_init(&dram_para)); sunxi_clk_dump(); diff --git a/board/100ask-ros/syter_boot/main.c b/board/100ask-ros/syter_boot/main.c index 9b4c3ea8..f089ec2c 100644 --- a/board/100ask-ros/syter_boot/main.c +++ b/board/100ask-ros/syter_boot/main.c @@ -50,10 +50,9 @@ #define CONFIG_HEAP_SIZE (16 * 1024 * 1024) extern sunxi_serial_t uart_dbg; - extern sunxi_i2c_t i2c_pmu; - extern sdhci_t sdhci0; +extern uint32_t dram_para[32]; extern int ar100s_gpu_fix(void); @@ -299,7 +298,7 @@ int main(void) { pmu_axp2202_dump(&i2c_pmu); /* Initialize the DRAM and enable memory management unit (MMU). */ - uint64_t dram_size = sunxi_dram_init(NULL); + uint64_t dram_size = sunxi_dram_init(&dram_para); arm32_mmu_enable(SDRAM_BASE, dram_size); diff --git a/include/drivers/sys-rtc.h b/include/drivers/sys-rtc.h index 455a6e75..f01cd842 100644 --- a/include/drivers/sys-rtc.h +++ b/include/drivers/sys-rtc.h @@ -18,6 +18,7 @@ extern "C" { #define EFEX_FLAG (0x5AA5A55A) #define RTC_FEL_INDEX 2 +#define RTC_DRAM_PARA_ADDR 3 #define RTC_BOOT_INDEX 6 /** @@ -48,6 +49,19 @@ void rtc_set_fel_flag(void); */ void rtc_set_start_time_ms(void); +/** + * @brief Sets the parameters for Dynamic Random Access Memory (DRAM). + * + * This function is used to set the parameters for DRAM and ensures the success of parameter setting through a loop. + * + * @param dram_para_addr Address for DRAM parameters to be set. + * + * @return None. + * + * @note This function continuously attempts to set DRAM parameters until it succeeds. + */ +void rtc_set_dram_para(uint32_t dram_para_addr); + /** * Probe the FEL (Fastboot External Loader) flag in the RTC register. * diff --git a/payloads b/payloads index d6155ba4..9773932c 160000 --- a/payloads +++ b/payloads @@ -1 +1 @@ -Subproject commit d6155ba41fa84c99d69c3906315fbda675ec797e +Subproject commit 9773932c3465b5189b7e4b333fc99127f07ffdd2 diff --git a/src/drivers/sun50iw10/sys-dram.c b/src/drivers/sun50iw10/sys-dram.c index 5f3700c7..1b70b31b 100644 --- a/src/drivers/sun50iw10/sys-dram.c +++ b/src/drivers/sun50iw10/sys-dram.c @@ -16,11 +16,6 @@ #define INIT_DRAM_BIN_BASE 0x3E900 -#define SUNXI_RTC_BASE (0x07000000) -#define SUNXI_RTC_DATA_BASE (SUNXI_RTC_BASE + 0x100) - -#define RTC_FEL_INDEX 2 - extern uint8_t __ddr_bin_start[]; extern uint8_t __ddr_bin_end[]; @@ -28,6 +23,17 @@ uint64_t sunxi_dram_init(void *para) { uint8_t *src = __ddr_bin_start; uint8_t *dst = (uint8_t *) INIT_DRAM_BIN_BASE; + if (para == NULL) { + printk_error("DRAM: please provide DRAM para\n"); + } + + uint32_t *para_data = (uint32_t *) para; + + /* Set DRAM driver clk and training data to */ + if (para_data[0] != 0x0) { + rtc_set_dram_para((uint32_t) para); + } + printk_debug("DRAM: load dram init from 0x%08x -> 0x%08x size: %08x\n", src, dst, __ddr_bin_end - __ddr_bin_start); memcpy(dst, src, __ddr_bin_end - __ddr_bin_start); diff --git a/src/drivers/sun55iw3/sys-dram.c b/src/drivers/sun55iw3/sys-dram.c index 69b32b84..8f4479c7 100644 --- a/src/drivers/sun55iw3/sys-dram.c +++ b/src/drivers/sun55iw3/sys-dram.c @@ -18,21 +18,9 @@ #define INIT_DRAM_BIN_BASE 0x07280000 -#define SUNXI_RTC_DATA_BASE (SUNXI_RTC_BASE + 0x100) - -#define RTC_FEL_INDEX 2 -#define DRAM_PARA_ADDR 3 - extern uint8_t __ddr_bin_start[]; extern uint8_t __ddr_bin_end[]; -void rtc_set_dram_para(uint32_t dram_para_addr) { - do { - rtc_write_data(DRAM_PARA_ADDR, dram_para_addr); - data_sync_barrier(); - } while (rtc_read_data(DRAM_PARA_ADDR) != dram_para_addr); -} - uint64_t sunxi_dram_init(void *para) { uint8_t *src = __ddr_bin_start; uint8_t *dst = (uint8_t *) INIT_DRAM_BIN_BASE; diff --git a/src/drivers/sys-rtc.c b/src/drivers/sys-rtc.c index f3cbcc41..1f7dbc52 100644 --- a/src/drivers/sys-rtc.c +++ b/src/drivers/sys-rtc.c @@ -14,14 +14,30 @@ #include +/** + * Write data to the RTC register at the specified index. + * + * @param index The index of the RTC register to write data to. + * @param val The value to write to the RTC register. + */ void rtc_write_data(int index, uint32_t val) { writel(val, SUNXI_RTC_DATA_BASE + index * 4); } +/** + * Read data from the RTC register at the specified index. + * + * @param index The index of the RTC register to read data from. + * @return The value read from the RTC register. + */ uint32_t rtc_read_data(int index) { return readl(SUNXI_RTC_DATA_BASE + index * 4); } +/** + * Set the FEL (Fastboot External Loader) flag in the RTC register. + * This flag indicates that the system should enter Fastboot mode. + */ void rtc_set_fel_flag(void) { do { rtc_write_data(RTC_FEL_INDEX, EFEX_FLAG); @@ -29,6 +45,10 @@ void rtc_set_fel_flag(void) { } while (rtc_read_data(RTC_FEL_INDEX) != EFEX_FLAG); } +/** + * Set the start time in milliseconds in the RTC register. + * This function sets the start time for a specific operation. + */ void rtc_set_start_time_ms(void) { uint32_t init_time_ms = get_init_timestamp(); do { @@ -37,10 +57,37 @@ void rtc_set_start_time_ms(void) { } while (rtc_read_data(RTC_FEL_INDEX) != init_time_ms); } +/** + * @brief Sets the parameters for Dynamic Random Access Memory (DRAM). + * + * This function is used to set the parameters for DRAM and ensures the success of parameter setting through a loop. + * + * @param dram_para_addr Address for DRAM parameters to be set. + * + * @return None. + * + * @note This function continuously attempts to set DRAM parameters until it succeeds. + */ +void rtc_set_dram_para(uint32_t dram_para_addr) { + do { + rtc_write_data(RTC_DRAM_PARA_ADDR, dram_para_addr); + data_sync_barrier(); + } while (rtc_read_data(RTC_DRAM_PARA_ADDR) != dram_para_addr); +} + +/** + * Probe the FEL (Fastboot External Loader) flag in the RTC register. + * + * @return The value of the FEL flag (0 or 1). + */ uint32_t rtc_probe_fel_flag(void) { return rtc_read_data(RTC_FEL_INDEX) == EFEX_FLAG ? 1 : 0; } +/** + * Clear the FEL (Fastboot External Loader) flag in the RTC register. + * This function clears the FEL flag after it has been processed. + */ void rtc_clear_fel_flag(void) { do { rtc_write_data(RTC_FEL_INDEX, 0); @@ -48,6 +95,12 @@ void rtc_clear_fel_flag(void) { } while (rtc_read_data(RTC_FEL_INDEX) != 0); } +/** + * Set the bootmode flag in the RTC register. + * + * @param flag The bootmode flag value to set. + * @return 0 if successful, or an error code if failed. + */ int rtc_set_bootmode_flag(uint8_t flag) { do { rtc_write_data(RTC_BOOT_INDEX, flag); @@ -57,6 +110,11 @@ int rtc_set_bootmode_flag(uint8_t flag) { return 0; } +/** + * Get the bootmode flag from the RTC register. + * + * @return The value of the bootmode flag. + */ int rtc_get_bootmode_flag(void) { uint32_t boot_flag; @@ -65,3 +123,4 @@ int rtc_get_bootmode_flag(void) { return boot_flag; } + From 8746b430a04aeede9814c704927d5278042a35a3 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sat, 15 Jun 2024 17:58:34 +0800 Subject: [PATCH 10/12] [driver] MMCv2 driver support TF Card and SMHC0 --- board/avaota-a1/board.c | 4 ++- board/avaota-a1/extlinux_boot/main.c | 15 ++-------- include/drivers/mmc/sys-mmc.h | 15 ++++++++++ include/drivers/mmc/sys-sdcard.h | 22 ++++++++++++-- include/drivers/mmc/sys-sdhci.h | 5 ++-- src/drivers/mmc/sys-mmc.c | 45 +++++++++++----------------- src/drivers/mmc/sys-sdcard.c | 14 +++++++-- src/drivers/mmc/sys-sdhci.c | 30 ++++++++++++------- 8 files changed, 91 insertions(+), 59 deletions(-) diff --git a/board/avaota-a1/board.c b/board/avaota-a1/board.c index fcfbe561..93c5a106 100644 --- a/board/avaota-a1/board.c +++ b/board/avaota-a1/board.c @@ -58,7 +58,9 @@ sunxi_sdhci_t sdhci0 = { .clk_ctrl_base = CCU_BASE + CCU_SMHC_BGR_REG, .clk_base = CCU_BASE + CCU_SMHC0_CLK_REG, .sdhci_mmc_type = MMC_TYPE_SD, - .max_clk = 75 * 1000 * 1000, + .max_clk = 200 * 1000 * 1000, + .width = SMHC_WIDTH_4BIT, + .dma_des_addr = SDRAM_BASE + 0x30080000, .pinctrl = { .gpio_clk = {GPIO_PIN(GPIO_PORTF, 2), GPIO_PERIPH_MUX2}, .gpio_cmd = {GPIO_PIN(GPIO_PORTF, 3), GPIO_PERIPH_MUX2}, diff --git a/board/avaota-a1/extlinux_boot/main.c b/board/avaota-a1/extlinux_boot/main.c index 07714bde..53a8c71c 100644 --- a/board/avaota-a1/extlinux_boot/main.c +++ b/board/avaota-a1/extlinux_boot/main.c @@ -196,17 +196,7 @@ static int load_sdcard(image_info_t *image) { FATFS fs; FRESULT fret; int ret; - uint32_t start; - - uint32_t test_time; - start = time_ms(); - sdmmc_blk_read(&card0, (uint8_t *) (SDRAM_BASE), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); - test_time = time_ms() - start; - printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n", - (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, - (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); - - start = time_ms(); + uint32_t start = time_ms(); fret = f_mount(&fs, "", 1); if (fret != FR_OK) { @@ -768,8 +758,6 @@ int main(void) { printk_info("SMHC: %s controller initialized\n", sdhci0.name); } - sunxi_mmc_init(&sdhci0); - /* Initialize the SD card and check if initialization is successful. */ if (sdmmc_init(&card0, &sdhci0) != 0) { printk_warning("SMHC: SDC0 init failed, init SDC2...\n"); @@ -831,6 +819,7 @@ int main(void) { jmp_to_fel(); _fail: + printk_error("SyterKit Boot Failed\n"); LCD_ShowString(0, 0, "SyterKit Boot Failed", SPI_LCD_COLOR_RED, SPI_LCD_COLOR_BLACK, 12); LCD_ShowString(0, 12, "Please Connect UART for Debug info", SPI_LCD_COLOR_RED, SPI_LCD_COLOR_BLACK, 12); LCD_ShowString(0, 24, "Error Info:", SPI_LCD_COLOR_RED, SPI_LCD_COLOR_BLACK, 12); diff --git a/include/drivers/mmc/sys-mmc.h b/include/drivers/mmc/sys-mmc.h index 977d2196..70bf7dab 100644 --- a/include/drivers/mmc/sys-mmc.h +++ b/include/drivers/mmc/sys-mmc.h @@ -377,6 +377,21 @@ typedef struct mmc { */ int sunxi_mmc_init(void *sdhci_hdl); +/** + * @brief Reads blocks from the SD/MMC card. + * + * This function reads blocks from the SD/MMC card starting from the specified block address. + * It supports reading multiple blocks and handles high capacity cards appropriately. + * + * @param sdhci Pointer to the SDHCI controller structure. + * @param dst Pointer to the destination buffer where the data will be stored. + * @param start Start block address from where to read the data. + * @param blkcnt Number of blocks to read. + * @return Number of blocks read on success, 0 otherwise. + */ +uint32_t sunxi_mmc_blk_read(void *sdhci, void *dst, uint32_t start, uint32_t blkcnt); + + #ifdef __cplusplus } #endif// __cplusplus diff --git a/include/drivers/mmc/sys-sdcard.h b/include/drivers/mmc/sys-sdcard.h index 9264eb1d..5e9a33d5 100644 --- a/include/drivers/mmc/sys-sdcard.h +++ b/include/drivers/mmc/sys-sdcard.h @@ -18,9 +18,7 @@ extern "C" { #endif// __cplusplus typedef struct { - mmc_t card; sunxi_sdhci_t *hci; - uint8_t buf[512]; bool online; } sdmmc_pdata_t; @@ -29,6 +27,26 @@ typedef struct { */ extern sdmmc_pdata_t card0; +/** + * Initialize the SDMMC controller with the specified platform data and SDHCI driver. + * + * @param data Pointer to the SDMMC platform data structure. + * @param hci Pointer to the SDHCI driver instance. + * @return 0 if successful, or an error code if failed. + */ +int sdmmc_init(sdmmc_pdata_t *data, sunxi_sdhci_t *hci); + +/** + * Read data from the SDMMC card into the provided buffer. + * + * @param data Pointer to the SDMMC platform data structure. + * @param buf Pointer to the destination buffer to store the read data. + * @param blkno The starting block number to read from. + * @param blkcnt The number of blocks to read. + * @return The total number of bytes read, or an error code if failed. + */ +uint32_t sdmmc_blk_read(sdmmc_pdata_t *data, uint8_t *buf, uint32_t blkno, uint32_t blkcnt); + #ifdef __cplusplus } #endif// __cplusplus diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index d89ed25c..4b0f7c9a 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -53,7 +53,7 @@ typedef struct sunxi_sdhci_desc { err_flag : 1, /* transfer error flag */ own : 1; /* des owner:1-idma owns it, 0-host owns it */ - uint32_t data_buf_sz : 16, data_buf_dummy : 16; + uint32_t data_buf_sz : SMHC_DES_NUM_SHIFT, data_buf_dummy : (32 - SMHC_DES_NUM_SHIFT); uint32_t buf_addr; uint32_t next_desc_addr; } sunxi_sdhci_desc_t __attribute__((aligned(8))); @@ -71,7 +71,7 @@ typedef struct sunxi_sdhci_host { uint32_t clock; /* DMA DESC */ - sunxi_sdhci_desc_t sdhci_desc[32]; + sunxi_sdhci_desc_t *sdhci_desc; } sunxi_sdhci_host_t; typedef struct sunxi_sdhci_pinctrl { @@ -105,6 +105,7 @@ typedef struct sunxi_sdhci { uint32_t clk_ctrl_base; uint32_t clk_base; uint32_t max_clk; + uint32_t dma_des_addr; sunxi_sdhci_type_t sdhci_mmc_type; /* Pinctrl info */ diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index aa870583..e9904bf6 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -242,15 +242,15 @@ static int sunxi_mmc_set_block_len(sunxi_sdhci_t *sdhci, uint32_t len) { * @param blkcnt Number of blocks to read. * @return Number of blocks read on success, 0 otherwise. */ -static uint64_t sunxi_mmc_read_blocks(sunxi_sdhci_t *sdhci, void *dst, uint64_t start, uint64_t blkcnt) { +static uint32_t sunxi_mmc_read_blocks(sunxi_sdhci_t *sdhci, void *dst, uint32_t start, uint32_t blkcnt) { mmc_t *mmc = sdhci->mmc; - mmc_cmd_t cmd; - mmc_data_t data; + mmc_cmd_t cmd = {0}; + mmc_data_t data = {0}; int timeout = 1000; - if (blkcnt > 1) + if (blkcnt > 1UL) cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; else cmd.cmdidx = MMC_CMD_READ_SINGLE_BLOCK; @@ -1667,22 +1667,23 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { } sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_8BIT); } - } - if (mmc->card_caps & MMC_MODE_HS400) { - mmc->tran_speed = sdhci->max_clk; - } else if (mmc->card_caps & MMC_MODE_DDR_52MHz) { - mmc->tran_speed = 52000000; - } else if (mmc->card_caps & MMC_MODE_HS) { - if (mmc->card_caps & MMC_MODE_HS_52MHz) { + if (mmc->card_caps & MMC_MODE_HS400) { + mmc->tran_speed = sdhci->max_clk; + } else if (mmc->card_caps & MMC_MODE_DDR_52MHz) { mmc->tran_speed = 52000000; + } else if (mmc->card_caps & MMC_MODE_HS) { + if (mmc->card_caps & MMC_MODE_HS_52MHz) { + mmc->tran_speed = 52000000; + } else { + mmc->tran_speed = 26000000; + } } else { mmc->tran_speed = 26000000; } - } else { - mmc->tran_speed = 26000000; } + printk_trace("SMHC: set clock to %u\n", mmc->tran_speed); sunxi_mmc_set_clock(sdhci, mmc->tran_speed); @@ -1767,19 +1768,9 @@ int sunxi_mmc_init(void *sdhci_hdl) { printk_error("SMHC%d: SD/MMC Probe failed, err %d\n", sdhci->id, err); } -#define CONFIG_SDMMC_SPEED_TEST_SIZE 4096 - - memset((void *) 0x40000000, 0xff, 0x20000); - - uint32_t start = time_ms(); - sunxi_mmc_read_blocks(sdhci, (uint8_t *) (0x40000000), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); - uint32_t test_time = time_ms() - start; - - printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n", - (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, - (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); - - dump_hex(0x40000000, 0x200); - return err; +} + +uint32_t sunxi_mmc_blk_read(void *sdhci, void *dst, uint32_t start, uint32_t blkcnt) { + return sunxi_mmc_read_blocks((sunxi_sdhci_t *) sdhci, dst, start, blkcnt); } \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdcard.c b/src/drivers/mmc/sys-sdcard.c index caced5f2..6cd0af20 100644 --- a/src/drivers/mmc/sys-sdcard.c +++ b/src/drivers/mmc/sys-sdcard.c @@ -19,9 +19,17 @@ sdmmc_pdata_t card0; int sdmmc_init(sdmmc_pdata_t *data, sunxi_sdhci_t *hci) { - return 0; + data->hci = hci; + data->online = false; + + if (sunxi_mmc_init(data->hci) == 0) { + printk_info("SHMC: %s card detected\n", data->hci->sdhci_mmc_type & MMC_TYPE_SD ? "SD" : "MMC"); + return 0; + } + + return -1; } -uint64_t sdmmc_blk_read(sdmmc_pdata_t *data, uint8_t *buf, uint64_t blkno, uint64_t blkcnt) { - return 0; +uint32_t sdmmc_blk_read(sdmmc_pdata_t *data, uint8_t *buf, uint32_t blkno, uint32_t blkcnt) { + return sunxi_mmc_blk_read(data->hci, buf, blkno, blkcnt); } \ No newline at end of file diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index 34a9fa1f..ce2b9d26 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -757,18 +757,22 @@ static int sunxi_sunxi_sdhci_trans_data_cpu(sunxi_sdhci_t *sdhci, mmc_data_t *da static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *data) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; sunxi_sdhci_desc_t *pdes = mmc_host->sdhci_desc; + uint32_t byte_cnt = data->blocksize * data->blocks; uint8_t *buff; uint32_t des_idx = 0, buff_frag_num = 0, remain = 0; uint32_t reg_val = 0; uint32_t timeout = time_us() + SMHC_TIMEOUT; + /* burst-16, rx/tx trigger level=15/240 */ + mmc_host->reg->ftrglevel = ((3 << 28) | (15 << 16) | 240); + buff = data->flags & MMC_DATA_READ ? (uint8_t *) data->b.dest : (uint8_t *) data->b.src; - buff_frag_num = (data->blocksize * data->blocks) >> SMHC_DES_NUM_SHIFT; - remain = (data->blocksize * data->blocks) & (SMHC_DES_BUFFER_MAX_LEN - 1); + buff_frag_num = byte_cnt >> SMHC_DES_NUM_SHIFT; + remain = byte_cnt & (SMHC_DES_BUFFER_MAX_LEN - 1); if (remain) { buff_frag_num++; } else { - remain = SMHC_DES_BUFFER_MAX_LEN; + remain = SMHC_DES_BUFFER_MAX_LEN - 1; } for (size_t i = 0; i < buff_frag_num; i++, des_idx++) { @@ -778,7 +782,7 @@ static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *da pdes[des_idx].dic = 1; if (buff_frag_num > 1 && i != buff_frag_num - 1) { - pdes[des_idx].data_buf_sz = SMHC_DES_BUFFER_MAX_LEN; + pdes[des_idx].data_buf_sz = SMHC_DES_BUFFER_MAX_LEN - 1; } else { pdes[des_idx].data_buf_sz = remain; } @@ -881,7 +885,8 @@ void sunxi_sdhci_set_ios(sunxi_sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = sdhci->mmc; - printk_trace("SMHC: ios setting bus:%u, speed %u\n", mmc->bus_width, mmc->clock); + printk_trace("SMHC: ios setting bus:%u, speed %u\n", + (0x1 << (mmc->bus_width + 1)), mmc->clock); // Configure clock and handle errors if (mmc->clock && sunxi_sdhci_config_clock(sdhci, mmc->clock)) { @@ -1061,7 +1066,8 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { * STATREG[3] : FIFO full */ if (data) { - printk_trace("SMHC: transfer data %lu bytes\n", data->blocksize * data->blocks); + printk_trace("SMHC: transfer data %lu bytes by %s\n", data->blocksize * data->blocks, + ((data->blocksize * data->blocks > 512) ? "DMA" : "CPU")); if (data->blocksize * data->blocks > 512) { use_dma_status = true; mmc_host->reg->gctrl &= ~SMHC_GCTRL_ACCESS_BY_AHB; @@ -1091,7 +1097,10 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { if (!error_code) { error_code = 0xffffffff; } - printk_error("SMHC: cmd 0x%08x timeout, error %08x\n", cmd->cmdidx, error_code); + if (time_us() > timeout) + printk_error("SMHC: stage 1 data timeout, error %08x\n", error_code); + else + printk_error("SMHC: stage 1 status get interrupt, error 0x%08x\n", error_code); goto out; } } while (!(status & SMHC_RINT_COMMAND_DONE)); @@ -1100,7 +1109,6 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { uint32_t done = false; timeout = time_us() + (use_dma_status ? SMHC_DMA_TIMEOUT : SMHC_TIMEOUT); do { - sunxi_sdhci_dump_reg(sdhci); status = mmc_host->reg->rint; if ((time_us() > timeout) || (status & SMHC_RINT_INTERRUPT_ERROR_BIT)) { error_code = status & SMHC_RINT_INTERRUPT_ERROR_BIT; @@ -1108,9 +1116,9 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { error_code = 0xffffffff; } if (time_us() > timeout) - printk_error("SMHC: data timeout, error %08x\n", error_code); + printk_error("SMHC: stage 2 data timeout, error %08x\n", error_code); else - printk_error("SMHC: status get interrupt, error 0x%08x\n", error_code); + printk_error("SMHC: stage 2 status get interrupt, error 0x%08x\n", error_code); goto out; } @@ -1186,7 +1194,6 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { } if (error_code) { - dump_hex(sdhci->reg_base, 0x200); mmc_host->reg->gctrl = SMHC_GCTRL_HARDWARE_RESET; timeout = time_us() + SMHC_TIMEOUT; while (mmc_host->reg->gctrl & SMHC_GCTRL_HARDWARE_RESET) { @@ -1288,6 +1295,7 @@ int sunxi_sdhci_init(sunxi_sdhci_t *sdhci) { mmc_host->hclkbase = sdhci->clk_ctrl_base; mmc_host->hclkrst = sdhci->clk_ctrl_base; mmc_host->mclkbase = sdhci->clk_base; + mmc_host->sdhci_desc = (sunxi_sdhci_desc_t *) sdhci->dma_des_addr; /* Configure pins and enable clocks */ sunxi_sdhci_pin_config(sdhci); From 1cf0332a91a84e2fd934906c72b3a66318fac79f Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sat, 15 Jun 2024 20:04:59 +0800 Subject: [PATCH 11/12] [board] add GPIO CD pin and fix hs400 mode --- board/avaota-a1/board.c | 6 +++- include/drivers/mmc/sys-sdhci.h | 2 ++ include/drivers/sys-gpio.h | 5 ++++ src/drivers/mmc/sys-mmc.c | 51 +++++++++++++++++++++++++-------- src/drivers/mmc/sys-sdcard.c | 2 +- src/drivers/mmc/sys-sdhci.c | 9 ++++-- 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/board/avaota-a1/board.c b/board/avaota-a1/board.c index 93c5a106..84a96b41 100644 --- a/board/avaota-a1/board.c +++ b/board/avaota-a1/board.c @@ -68,6 +68,8 @@ sunxi_sdhci_t sdhci0 = { .gpio_d1 = {GPIO_PIN(GPIO_PORTF, 0), GPIO_PERIPH_MUX2}, .gpio_d2 = {GPIO_PIN(GPIO_PORTF, 5), GPIO_PERIPH_MUX2}, .gpio_d3 = {GPIO_PIN(GPIO_PORTF, 4), GPIO_PERIPH_MUX2}, + .gpio_cd = {GPIO_PIN(GPIO_PORTF, 6), GPIO_INPUT}, + .cd_level = GPIO_LEVEL_LOW, }, .timing_data = { .freq_id = MMC_CLK_25M, @@ -85,7 +87,9 @@ sunxi_sdhci_t sdhci2 = { .clk_ctrl_base = CCU_BASE + CCU_SMHC_BGR_REG, .clk_base = CCU_BASE + CCU_SMHC2_CLK_REG, .sdhci_mmc_type = MMC_TYPE_EMMC, - .max_clk = 200 * 1000 * 1000, + .max_clk = 50 * 1000 * 1000, + .width = SMHC_WIDTH_8BIT, + .dma_des_addr = SDRAM_BASE + 0x30080000, .pinctrl = { .gpio_clk = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX3}, .gpio_cmd = {GPIO_PIN(GPIO_PORTC, 6), GPIO_PERIPH_MUX3}, diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index 4b0f7c9a..590f2969 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -87,6 +87,8 @@ typedef struct sunxi_sdhci_pinctrl { gpio_mux_t gpio_clk; gpio_mux_t gpio_ds; gpio_mux_t gpio_rst; + gpio_mux_t gpio_cd; + uint8_t cd_level; } sunxi_sdhci_pinctrl_t; typedef struct sunxi_sdhci_timing { diff --git a/include/drivers/sys-gpio.h b/include/drivers/sys-gpio.h index 77f09fe9..5c4a1ba8 100644 --- a/include/drivers/sys-gpio.h +++ b/include/drivers/sys-gpio.h @@ -30,6 +30,11 @@ enum { GPIO_DISABLED = 0xf, }; +enum { + GPIO_LEVEL_LOW = 0, + GPIO_LEVEL_HIGH, +}; + enum { GPIO_PORTA = 0, GPIO_PORTB, diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index e9904bf6..306552a4 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -1090,13 +1090,13 @@ static int sunxi_mmc_mmc_switch_speed_mode(sunxi_sdhci_t *sdhci, uint32_t spd_mo ret = sunxi_mmc_mmc_switch_ds(sdhci); break; case MMC_HSSDR52_SDR25: - ret = sunxi_mmc_mmc_switch_to_hs(sdhci); + ret = sunxi_mmc_mmc_switch_hs(sdhci); break; case MMC_HS200_SDR104: - ret = sunxi_mmc_mmc_switch_to_hs200(sdhci); + ret = sunxi_mmc_mmc_switch_hs200(sdhci); break; case MMC_HS400: - ret = sunxi_mmc_mmc_switch_to_hs400(sdhci); + ret = sunxi_mmc_mmc_switch_hs400(sdhci); break; default: ret = -1; @@ -1121,12 +1121,13 @@ static int sunxi_mmc_check_bus_width(sunxi_sdhci_t *sdhci, uint32_t emmc_hs_ddr, int ret = 0; if (bus_width == SMHC_WIDTH_1BIT) { - /* don't consider SD3.0. tSD/fSD is SD2.0, 1-bit can be support */ { - if ((emmc_hs_ddr && (!IS_SD(mmc)) && (mmc->speed_mode == MMC_HSSDR52_SDR25)) || - ((!IS_SD(mmc)) && (mmc->speed_mode == MMC_HSDDR52_DDR50)) || - ((!IS_SD(mmc)) && (mmc->speed_mode == MMC_HS200_SDR104)) || - ((!IS_SD(mmc)) && (mmc->speed_mode == MMC_HS400))) - ret = -1; + /* don't consider SD3.0. tSD/fSD is SD2.0, 1-bit can be support */ + + if ((emmc_hs_ddr && (!sunxi_mmc_device_is_sd(mmc)) && (mmc->speed_mode == MMC_HSSDR52_SDR25)) || + ((!sunxi_mmc_device_is_sd(mmc)) && (mmc->speed_mode == MMC_HSDDR52_DDR50)) || + ((!sunxi_mmc_device_is_sd(mmc)) && (mmc->speed_mode == MMC_HS200_SDR104)) || + ((!sunxi_mmc_device_is_sd(mmc)) && (mmc->speed_mode == MMC_HS400))) { + ret = -1; } } else if (bus_width == SMHC_WIDTH_1BIT) { if (!(mmc->card_caps & MMC_MODE_4BIT)) { @@ -1135,7 +1136,7 @@ static int sunxi_mmc_check_bus_width(sunxi_sdhci_t *sdhci, uint32_t emmc_hs_ddr, } else if (bus_width == SMHC_WIDTH_8BIT) { if (!(mmc->card_caps & MMC_MODE_8BIT)) ret = -1; - if (IS_SD(mmc)) + if (sunxi_mmc_device_is_sd(mmc)) ret = -1; } else { printk_debug("SMHC: bus width error %d\n", bus_width); @@ -1615,14 +1616,14 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { mmc->speed_mode = MMC_HS400; if ((mmc->card_caps & MMC_MODE_HS400)) { /* firstly, switch to HS-DDR 8 bit */ - err = sunxi_mmc_mmc_switch_bus_width(sdhci, MMC_HSDDR52_DDR50, 8); + err = sunxi_mmc_mmc_switch_bus_width(sdhci, MMC_HSDDR52_DDR50, SMHC_WIDTH_8BIT); if (err) { printk_error("SMHC: HS400 switch to DDR mode fail\n"); return err; } /* then, switch to HS400 */ - err = sunxi_mmc_mmc_switch_bus_mode(sdhci, MMC_HS400, 8); + err = sunxi_mmc_mmc_switch_bus_mode(sdhci, MMC_HS400, SMHC_WIDTH_8BIT); if (err) { printk_error("SMHC: switch to HS400 mode fail\n"); return err; @@ -1743,6 +1744,15 @@ int sunxi_mmc_init(void *sdhci_hdl) { mmc->part_num = 0; if (sdhci->sdhci_mmc_type == MMC_TYPE_SD) { + /* if is SDHCI0 in PF port try SD Card CD pin */ + if (sdhci->pinctrl.gpio_cd.pin != 0) { + if (sdhci->id == 0 && sunxi_gpio_read(sdhci->pinctrl.gpio_cd.pin) != GPIO_LEVEL_LOW) { + printk_error("SMHC: SD Card Get CD error %d\n", sunxi_gpio_read(sdhci->pinctrl.gpio_cd.pin)); + err = -1; + return err; + } + } + printk_debug("SMHC: Try to init SD Card\n"); err = sunxi_mmc_send_if_cond(sdhci); if (err) { @@ -1768,6 +1778,23 @@ int sunxi_mmc_init(void *sdhci_hdl) { printk_error("SMHC%d: SD/MMC Probe failed, err %d\n", sdhci->id, err); } +#define CONFIG_SDMMC_SPEED_TEST_SIZE 4096 + + memset((void *) 0x40000000, 0xff, 0x20000); + + uint32_t start = time_ms(); + sunxi_mmc_read_blocks(sdhci, (uint8_t *) (0x40000000), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); + uint32_t test_time = time_ms() - start; + + printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n", + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, + (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); + + while (1) { + /* code */ + } + + return err; } diff --git a/src/drivers/mmc/sys-sdcard.c b/src/drivers/mmc/sys-sdcard.c index 6cd0af20..558abda1 100644 --- a/src/drivers/mmc/sys-sdcard.c +++ b/src/drivers/mmc/sys-sdcard.c @@ -23,7 +23,7 @@ int sdmmc_init(sdmmc_pdata_t *data, sunxi_sdhci_t *hci) { data->online = false; if (sunxi_mmc_init(data->hci) == 0) { - printk_info("SHMC: %s card detected\n", data->hci->sdhci_mmc_type & MMC_TYPE_SD ? "SD" : "MMC"); + printk_info("SHMC: %s card detected\n", data->hci->sdhci_mmc_type == MMC_TYPE_SD ? "SD" : "MMC"); return 0; } diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index ce2b9d26..ea748905 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -706,6 +706,11 @@ static void sunxi_sdhci_pin_config(sunxi_sdhci_t *sdhci) { sunxi_gpio_init(sdhci_pins.gpio_rst.pin, sdhci_pins.gpio_rst.mux); sunxi_gpio_set_pull(sdhci_pins.gpio_rst.pin, GPIO_PULL_UP); } + + if (sdhci->pinctrl.gpio_cd.pin != 0) { + sunxi_gpio_init(sdhci_pins.gpio_cd.pin, sdhci_pins.gpio_cd.mux); + sunxi_gpio_set_pull(sdhci_pins.gpio_cd.pin, GPIO_PULL_UP); + } } /** @@ -885,8 +890,7 @@ void sunxi_sdhci_set_ios(sunxi_sdhci_t *sdhci) { sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; mmc_t *mmc = sdhci->mmc; - printk_trace("SMHC: ios setting bus:%u, speed %u\n", - (0x1 << (mmc->bus_width + 1)), mmc->clock); + printk_trace("SMHC: ios setting bus:%u, speed %u\n", mmc->bus_width, mmc->clock); // Configure clock and handle errors if (mmc->clock && sunxi_sdhci_config_clock(sdhci, mmc->clock)) { @@ -1091,6 +1095,7 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { timeout = time_us() + SMHC_TIMEOUT; do { + sunxi_sdhci_dump_reg(sdhci); status = mmc_host->reg->rint; if ((time_us() > timeout) || (status & SMHC_RINT_INTERRUPT_ERROR_BIT)) { error_code = status & SMHC_RINT_INTERRUPT_ERROR_BIT; From d3f4d7435e3922ed0ca7eea0c53f38b6de22b545 Mon Sep 17 00:00:00 2001 From: SamulKyull Date: Sat, 15 Jun 2024 23:10:52 +0800 Subject: [PATCH 12/12] [driver] MMCv2 driver WIP 4/4 --- board/avaota-a1/board.c | 9 +- include/drivers/mmc/sys-sdhci.h | 4 +- include/drivers/reg/reg-smhc.h | 9 +- src/drivers/mmc/sys-mmc.c | 45 ++------- src/drivers/mmc/sys-sdhci.c | 158 ++++++++++++++++---------------- 5 files changed, 96 insertions(+), 129 deletions(-) diff --git a/board/avaota-a1/board.c b/board/avaota-a1/board.c index 84a96b41..77477569 100644 --- a/board/avaota-a1/board.c +++ b/board/avaota-a1/board.c @@ -71,13 +71,6 @@ sunxi_sdhci_t sdhci0 = { .gpio_cd = {GPIO_PIN(GPIO_PORTF, 6), GPIO_INPUT}, .cd_level = GPIO_LEVEL_LOW, }, - .timing_data = { - .freq_id = MMC_CLK_25M, - .odly = 0, - .sdly = 0, - .spd_md_id = MMC_DS26_SDR12, - .auto_timing = TRUE, - }, }; sunxi_sdhci_t sdhci2 = { @@ -87,7 +80,7 @@ sunxi_sdhci_t sdhci2 = { .clk_ctrl_base = CCU_BASE + CCU_SMHC_BGR_REG, .clk_base = CCU_BASE + CCU_SMHC2_CLK_REG, .sdhci_mmc_type = MMC_TYPE_EMMC, - .max_clk = 50 * 1000 * 1000, + .max_clk = 25 * 1000 * 1000, .width = SMHC_WIDTH_8BIT, .dma_des_addr = SDRAM_BASE + 0x30080000, .pinctrl = { diff --git a/include/drivers/mmc/sys-sdhci.h b/include/drivers/mmc/sys-sdhci.h index 590f2969..c45c8ef5 100644 --- a/include/drivers/mmc/sys-sdhci.h +++ b/include/drivers/mmc/sys-sdhci.h @@ -94,8 +94,6 @@ typedef struct sunxi_sdhci_pinctrl { typedef struct sunxi_sdhci_timing { uint32_t odly; uint32_t sdly; - uint32_t spd_md_id; - uint32_t freq_id; uint8_t auto_timing; } sunxi_sdhci_timing_t; @@ -116,7 +114,7 @@ typedef struct sunxi_sdhci { /* Private data */ mmc_t *mmc; sunxi_sdhci_host_t *mmc_host; - sunxi_sdhci_timing_t timing_data; + sunxi_sdhci_timing_t *timing_data; } sunxi_sdhci_t; /** diff --git a/include/drivers/reg/reg-smhc.h b/include/drivers/reg/reg-smhc.h index badea770..7efdd591 100644 --- a/include/drivers/reg/reg-smhc.h +++ b/include/drivers/reg/reg-smhc.h @@ -79,14 +79,15 @@ #define SMHC_RINT_AUTO_COMMAND_DONE (0x1 << 14) #define SMHC_RINT_END_BIT_ERROR (0x1 << 15) #define SMHC_RINT_SDIO_INTERRUPT (0x1 << 16) +#define SMHC_RINT_R1B_BUSY_CLEAR (0x1 << 17) #define SMHC_RINT_CARD_INSERT (0x1 << 30) #define SMHC_RINT_CARD_REMOVE (0x1 << 31) #define SMHC_RINT_INTERRUPT_ERROR_BIT \ (SMHC_RINT_RESP_ERROR | SMHC_RINT_RESP_CRC_ERROR | \ SMHC_RINT_DATA_CRC_ERROR | SMHC_RINT_RESP_TIMEOUT | \ - SMHC_RINT_DATA_TIMEOUT | SMHC_RINT_VOLTAGE_CHANGE_DONE | \ - SMHC_RINT_FIFO_RUN_ERROR | SMHC_RINT_HARD_WARE_LOCKED | \ - SMHC_RINT_START_BIT_ERROR | SMHC_RINT_END_BIT_ERROR) /* 0xbfc2 */ + SMHC_RINT_DATA_TIMEOUT | SMHC_RINT_FIFO_RUN_ERROR | \ + SMHC_RINT_HARD_WARE_LOCKED | SMHC_RINT_START_BIT_ERROR | \ + SMHC_RINT_END_BIT_ERROR) /* 0xbbc2 */ #define SMHC_RINT_INTERRUPT_DONE_BIT \ (SMHC_RINT_AUTO_COMMAND_DONE | SMHC_RINT_DATA_OVER | \ SMHC_RINT_COMMAND_DONE | SMHC_RINT_VOLTAGE_CHANGE_DONE) @@ -261,4 +262,4 @@ typedef struct { volatile uint32_t vers; /* (0x300) SMHC Version Register */ } sdhci_reg_t; -#endif // __REG_SMHC_H__ \ No newline at end of file +#endif// __REG_SMHC_H__ \ No newline at end of file diff --git a/src/drivers/mmc/sys-mmc.c b/src/drivers/mmc/sys-mmc.c index 306552a4..8edf99a8 100644 --- a/src/drivers/mmc/sys-mmc.c +++ b/src/drivers/mmc/sys-mmc.c @@ -1612,28 +1612,18 @@ static int sunxi_mmc_probe(sunxi_sdhci_t *sdhci) { } else { /* EMMC */ if (mmc->card_caps & MMC_MODE_8BIT) { - mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_HS400; - mmc->speed_mode = MMC_HS400; - if ((mmc->card_caps & MMC_MODE_HS400)) { - /* firstly, switch to HS-DDR 8 bit */ - err = sunxi_mmc_mmc_switch_bus_width(sdhci, MMC_HSDDR52_DDR50, SMHC_WIDTH_8BIT); - if (err) { - printk_error("SMHC: HS400 switch to DDR mode fail\n"); - return err; - } - - /* then, switch to HS400 */ - err = sunxi_mmc_mmc_switch_bus_mode(sdhci, MMC_HS400, SMHC_WIDTH_8BIT); + /* Set the card to use 8 bit */ + if ((mmc->card_caps & MMC_MODE_DDR_52MHz)) { + /* Set the card to use 8 bit ddr */ + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_DDR_8); if (err) { - printk_error("SMHC: switch to HS400 mode fail\n"); + printk_error("SMHC: switch bus width failed\n"); return err; } - mmc->tran_speed = sdhci->max_clk; - + sunxi_mmc_set_bus_width(sdhci, SMHC_WIDTH_8BIT); + } else { /* Set the card to use 8 bit */ - } else if ((mmc->card_caps & MMC_MODE_DDR_52MHz)) { - /* Set the card to use 8 bit ddr */ - err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_DDR_8); + err = sunxi_mmc_switch(sdhci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8); if (err) { printk_error("SMHC: switch bus width failed\n"); return err; @@ -1752,7 +1742,7 @@ int sunxi_mmc_init(void *sdhci_hdl) { return err; } } - + printk_debug("SMHC: Try to init SD Card\n"); err = sunxi_mmc_send_if_cond(sdhci); if (err) { @@ -1778,23 +1768,6 @@ int sunxi_mmc_init(void *sdhci_hdl) { printk_error("SMHC%d: SD/MMC Probe failed, err %d\n", sdhci->id, err); } -#define CONFIG_SDMMC_SPEED_TEST_SIZE 4096 - - memset((void *) 0x40000000, 0xff, 0x20000); - - uint32_t start = time_ms(); - sunxi_mmc_read_blocks(sdhci, (uint8_t *) (0x40000000), 0, CONFIG_SDMMC_SPEED_TEST_SIZE); - uint32_t test_time = time_ms() - start; - - printk_debug("SDMMC: speedtest %uKB in %ums at %uKB/S\n", - (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / 1024, test_time, - (CONFIG_SDMMC_SPEED_TEST_SIZE * 512) / test_time); - - while (1) { - /* code */ - } - - return err; } diff --git a/src/drivers/mmc/sys-sdhci.c b/src/drivers/mmc/sys-sdhci.c index ea748905..380b188b 100644 --- a/src/drivers/mmc/sys-sdhci.c +++ b/src/drivers/mmc/sys-sdhci.c @@ -19,6 +19,7 @@ /* Global data*/ sunxi_sdhci_host_t g_mmc_host; +sunxi_sdhci_timing_t g_mmc_timing; mmc_t g_mmc; /** @@ -93,64 +94,65 @@ static int sunxi_sdhci_update_clk(sunxi_sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC structure. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_get_timing_config_timing_4(sunxi_sdhci_t *sdhci) { - sunxi_sdhci_timing_t timing_data = sdhci->timing_data; +static int sunxi_sdhci_get_timing_config_timing_4(sunxi_sdhci_t *sdhci, const uint32_t spd_md_id, const uint32_t freq_id) { + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; uint32_t spd_md_sdly = 0, dly = 0; int ret = 0; printk_trace("SMHC: sdhci timing config timing 4\n"); /* Check if the controller ID is MMC_CONTROLLER_2 and if timing mode and frequency ID are valid */ - if ((sdhci->id != MMC_CONTROLLER_2) || (timing_data.spd_md_id > MMC_TIMING_MODE_4) || (timing_data.freq_id > MMC_MAX_SPD_MD_NUM)) { + if ((sdhci->id != MMC_CONTROLLER_2) || (spd_md_id > MMC_HS400) || (freq_id > MMC_MAX_SPD_MD_NUM)) { printk_error("SMHC: timing 4 not supported for this configuration\n"); return -1; } /* Calculate delay based on speed mode and frequency */ - dly = ((spd_md_sdly >> ((timing_data.freq_id % 4) * 8)) & 0xff); + spd_md_sdly = sdhci->mmc->tune_sdly.tm4_smx_fx[spd_md_id * 2 + freq_id / 4]; + dly = ((spd_md_sdly >> ((freq_id % 4) * 8)) & 0xff); + if ((dly == 0xff) || (dly == 0)) { - if (timing_data.spd_md_id == MMC_DS26_SDR12) { - if (timing_data.freq_id <= MMC_CLK_25M) { + if (spd_md_id == MMC_DS26_SDR12) { + if (freq_id <= MMC_CLK_25M) { dly = 0; } else { - printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data.freq_id, timing_data.spd_md_id); + printk_error("SMHC: wrong frequency %d at speed mode %d\n", freq_id, spd_md_id); ret = -1; } - } else if (timing_data.spd_md_id == MMC_HSSDR52_SDR25) { - if (timing_data.freq_id <= MMC_CLK_25M) { + } else if (spd_md_id == MMC_HSSDR52_SDR25) { + if (freq_id <= MMC_CLK_25M) { dly = 0; - } else if (timing_data.freq_id == MMC_CLK_50M) { + } else if (freq_id == MMC_CLK_50M) { dly = 15; } else { - printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data.freq_id, timing_data.spd_md_id); + printk_error("SMHC: wrong frequency %d at speed mode %d\n", freq_id, spd_md_id); ret = -1; } - } else if (timing_data.spd_md_id == MMC_HSDDR52_DDR50) { - if (timing_data.freq_id <= MMC_CLK_25M) { + } else if (spd_md_id == MMC_HSDDR52_DDR50) { + if (freq_id <= MMC_CLK_25M) { dly = 0; } else { - printk_error("SMHC: wrong frequency %d at speed mode %d\n", timing_data.freq_id, timing_data.spd_md_id); + printk_error("SMHC: wrong frequency %d at speed mode %d\n", freq_id, spd_md_id); ret = -1; } } else { - printk_error("SMHC: wrong speed mode %d\n", timing_data.spd_md_id); + printk_error("SMHC: wrong speed mode %d\n", spd_md_id); ret = -1; } } /* Set output delay based on speed mode */ - if (timing_data.spd_md_id == MMC_HSDDR52_DDR50) { - timing_data.odly = 1; + if (spd_md_id == MMC_HSDDR52_DDR50) { + timing_data->odly = 1; } else { - timing_data.odly = 0; + timing_data->odly = 0; } /* Set the calculated delay */ - timing_data.sdly = dly; + timing_data->sdly = dly; printk_trace("SMHC: TM4 Timing odly = %u, sdly = %u, spd_md_id = %u, freq_id = %u\n", - timing_data.odly, timing_data.sdly, timing_data.spd_md_id, - timing_data.freq_id); + timing_data->odly, timing_data->sdly, spd_md_id, freq_id); return ret; } @@ -164,28 +166,28 @@ static int sunxi_sdhci_get_timing_config_timing_4(sunxi_sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC controller structure. * @return Returns 0 on success, -1 on failure. */ -static int sunxi_sdhci_get_timing_config(sunxi_sdhci_t *sdhci) { +static int sunxi_sdhci_get_timing_config(sunxi_sdhci_t *sdhci, uint32_t spd_md_id, uint32_t freq_id) { int ret = 0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - sunxi_sdhci_timing_t timing_data = sdhci->timing_data; + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; // Check for specific conditions based on the controller ID and timing mode if ((sdhci->id == 2) && mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { /* When using eMMC and SMHC2, config it as timing 4 */ - ret = sunxi_sdhci_get_timing_config_timing_4(sdhci); + ret = sunxi_sdhci_get_timing_config_timing_4(sdhci, spd_md_id, freq_id); if (ret) { printk_error("SMHC: Config timing TM4 fail\n"); } } else if ((sdhci->id == 0) && (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1)) { // Check timing data and adjust configuration if necessary - if ((timing_data.spd_md_id <= MMC_HSSDR52_SDR25) && (timing_data.freq_id <= MMC_CLK_50M)) { + if ((spd_md_id <= MMC_HSSDR52_SDR25) && (freq_id <= MMC_CLK_50M)) { /* if timing less than SDR25, use default odly */ - timing_data.odly = 0; - timing_data.sdly = 0; + timing_data->odly = 0; + timing_data->sdly = 0; ret = 0; } else { - printk_warning("SMHC: SMHC0 does not support input spd mode %d\n", timing_data.spd_md_id); + printk_warning("SMHC: SMHC0 does not support input spd mode %d\n", spd_md_id); ret = -1; } } else { @@ -304,105 +306,100 @@ static uint32_t sunxi_sdhci_get_mclk(sunxi_sdhci_t *sdhci) { * @param sdhci Pointer to the SDHC controller structure. * @return 0 on success, -1 on failure. */ -static int sunxi_sdhci_config_delay(sunxi_sdhci_t *sdhci) { +static int sunxi_sdhci_config_delay(sunxi_sdhci_t *sdhci, uint32_t spd_md_id, uint32_t freq_id) { int ret = 0; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - sunxi_sdhci_timing_t timing_data = sdhci->timing_data; + mmc_t *mmc = sdhci->mmc; + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_1) { - timing_data.odly = 0; - timing_data.sdly = 0; - printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_1, odly %d, sldy %d\n", timing_data.odly, timing_data.sdly); + timing_data->odly = 0; + timing_data->sdly = 0; + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_1, odly %d, sldy %d\n", timing_data->odly, timing_data->sdly); reg_val = mmc_host->reg->drv_dl; reg_val &= (~(0x3 << 16)); - reg_val |= (((timing_data.odly & 0x1) << 16) | ((timing_data.odly & 0x1) << 17)); + reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); mmc_host->reg->drv_dl = reg_val; writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); reg_val = mmc_host->reg->ntsr; reg_val &= (~(0x3 << 4)); - reg_val |= ((timing_data.sdly & 0x3) << 4); + reg_val |= ((timing_data->sdly & 0x3) << 4); mmc_host->reg->ntsr = reg_val; } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_3) { - timing_data.odly = 0; - timing_data.sdly = 0; - printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_3, odly %d, sldy %d\n", timing_data.odly, timing_data.sdly); + timing_data->odly = 0; + timing_data->sdly = 0; + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_3, odly %d, sldy %d\n", timing_data->odly, timing_data->sdly); reg_val = mmc_host->reg->drv_dl; reg_val &= (~(0x3 << 16)); - reg_val |= (((timing_data.odly & 0x1) << 16) | ((timing_data.odly & 0x1) << 17)); + reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); mmc_host->reg->drv_dl = reg_val; writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); reg_val = mmc_host->reg->samp_dl; reg_val &= (~SDXC_NTDC_CFG_DLY); - reg_val |= ((timing_data.sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); mmc_host->reg->samp_dl = reg_val; } else if (mmc_host->timing_mode == SUNXI_MMC_TIMING_MODE_4) { - uint32_t spd_md_orig = timing_data.spd_md_id; + uint32_t spd_md_orig = spd_md_id; - printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_4, setup\n"); + printk_trace("SMHC: SUNXI_MMC_TIMING_MODE_4, setup freq id: %d, spd_md_id: %d\n", freq_id, spd_md_id); - if (timing_data.spd_md_id == MMC_HS400) - timing_data.spd_md_id = MMC_HS200_SDR104; + if (spd_md_id == MMC_HS400) + spd_md_id = MMC_HS200_SDR104; - timing_data.odly = 0xff; - timing_data.sdly = 0xff; + timing_data->odly = 0xff; + timing_data->sdly = 0xff; - if ((ret = sunxi_sdhci_get_timing_config(sdhci)) != 0) { + if ((ret = sunxi_sdhci_get_timing_config(sdhci, spd_md_id, freq_id)) != 0) { printk_error("SMHC: getting timing param error %d\n", ret); return -1; } - timing_data = sdhci->timing_data; - - if ((timing_data.odly == 0xff) || (timing_data.sdly == 0xff)) { + if ((timing_data->odly == 0xff) || (timing_data->sdly == 0xff)) { printk_error("SMHC: getting timing config error\n"); return -1; } reg_val = mmc_host->reg->drv_dl; reg_val &= (~(0x3 << 16)); - reg_val |= (((timing_data.odly & 0x1) << 16) | ((timing_data.odly & 0x1) << 17)); + reg_val |= (((timing_data->odly & 0x1) << 16) | ((timing_data->odly & 0x1) << 17)); writel(readl(mmc_host->mclkbase) & (~(1 << 31)), mmc_host->mclkbase); mmc_host->reg->drv_dl = reg_val; writel(readl(mmc_host->mclkbase) | (1 << 31), mmc_host->mclkbase); reg_val = mmc_host->reg->samp_dl; reg_val &= (~SDXC_NTDC_CFG_DLY); - reg_val |= ((timing_data.sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); mmc_host->reg->samp_dl = reg_val; /* Reset to orig md id */ - timing_data.spd_md_id = spd_md_orig; - if (timing_data.spd_md_id = MMC_HS400) { - timing_data.odly = 0xff; - timing_data.sdly = 0xff; - if ((ret = sunxi_sdhci_get_timing_config(sdhci)) != 0) { + spd_md_id = spd_md_orig; + if (spd_md_id == MMC_HS400) { + timing_data->odly = 0xff; + timing_data->sdly = 0xff; + if ((ret = sunxi_sdhci_get_timing_config(sdhci, spd_md_id, freq_id)) != 0) { printk_error("SMHC: getting timing param error %d\n", ret); return -1; } - timing_data = sdhci->timing_data; - - if ((timing_data.odly == 0xff) || (timing_data.sdly == 0xff)) { + if ((timing_data->odly == 0xff) || (timing_data->sdly == 0xff)) { printk_error("SMHC: getting timing config error\n"); return -1; } reg_val = mmc_host->reg->ds_dl; reg_val &= (~SDXC_NTDC_CFG_DLY); - reg_val |= ((timing_data.sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); + reg_val |= ((timing_data->sdly & SDXC_NTDC_CFG_DLY) | SDXC_NTDC_ENABLE_DLY); mmc_host->reg->ds_dl = reg_val; } - printk_trace("SMHC: config delay freq = %d, odly = %d," - "sdly = %d, spd_md_id = %d\n", - timing_data.freq_id, timing_data.odly, - timing_data.sdly, timing_data.spd_md_id); + printk_trace("SMHC: config delay freq = %d, odly = %d, sdly = %d, spd_md_id = %d\n", + freq_id, timing_data->odly, timing_data->sdly, spd_md_id); } } @@ -419,7 +416,7 @@ static int sunxi_sdhci_clock_mode(sunxi_sdhci_t *sdhci, uint32_t clk) { int ret = 0; uint32_t reg_val = 0x0; sunxi_sdhci_host_t *mmc_host = sdhci->mmc_host; - sunxi_sdhci_timing_t timing_data = sdhci->timing_data; + sunxi_sdhci_timing_t *timing_data = sdhci->timing_data; mmc_t *mmc = sdhci->mmc; /* disable mclk */ @@ -493,31 +490,32 @@ static int sunxi_sdhci_clock_mode(sunxi_sdhci_t *sdhci, uint32_t clk) { } /* config delay for mmc device */ - timing_data.freq_id = MMC_CLK_25M; + uint32_t freq_id = MMC_CLK_25M; switch (clk) { case 0 ... 400000: - timing_data.freq_id = MMC_CLK_400K; + freq_id = MMC_CLK_400K; break; case 400001 ... 26000000: - timing_data.freq_id = MMC_CLK_25M; + freq_id = MMC_CLK_25M; break; case 26000001 ... 52000000: - timing_data.freq_id = MMC_CLK_50M; + freq_id = MMC_CLK_50M; break; case 52000001 ... 100000000: - timing_data.freq_id = MMC_CLK_100M; + freq_id = MMC_CLK_100M; break; case 100000001 ... 150000000: - timing_data.freq_id = MMC_CLK_150M; + freq_id = MMC_CLK_150M; break; case 150000001 ... 200000000: - timing_data.freq_id = MMC_CLK_200M; + freq_id = MMC_CLK_200M; break; default: - timing_data.freq_id = MMC_CLK_25M; + freq_id = MMC_CLK_25M; break; } - sunxi_sdhci_config_delay(sdhci); + + sunxi_sdhci_config_delay(sdhci, mmc->speed_mode, freq_id); return 0; } @@ -806,7 +804,7 @@ static int sunxi_sunxi_sdhci_trans_data_dma(sunxi_sdhci_t *sdhci, mmc_data_t *da pdes[des_idx].next_desc_addr = ((size_t) &pdes[des_idx + 1]) >> 2; } -#ifdef SMHC_DMA_TRACE +#ifndef SMHC_DMA_TRACE printk_trace("SMHC: frag %d, remain %d, des[%d] = 0x%08x:" " [0] = 0x%08x, [1] = 0x%08x, [2] = 0x%08x, [3] = 0x%08x\n", i, remain, des_idx, (uint32_t) (&pdes[des_idx]), @@ -906,7 +904,6 @@ void sunxi_sdhci_set_ios(sunxi_sdhci_t *sdhci) { if (mmc->speed_mode == MMC_HSDDR52_DDR50) { sunxi_sdhci_ddr_mode_set(sdhci, true); sunxi_sdhci_hs400_mode_set(sdhci, false); - } else if (mmc->speed_mode == MMC_HS400) { sunxi_sdhci_ddr_mode_set(sdhci, false); sunxi_sdhci_hs400_mode_set(sdhci, true); @@ -1095,7 +1092,6 @@ int sunxi_sdhci_xfer(sunxi_sdhci_t *sdhci, mmc_cmd_t *cmd, mmc_data_t *data) { timeout = time_us() + SMHC_TIMEOUT; do { - sunxi_sdhci_dump_reg(sdhci); status = mmc_host->reg->rint; if ((time_us() > timeout) || (status & SMHC_RINT_INTERRUPT_ERROR_BIT)) { error_code = status & SMHC_RINT_INTERRUPT_ERROR_BIT; @@ -1269,6 +1265,9 @@ int sunxi_sdhci_init(sunxi_sdhci_t *sdhci) { sdhci->mmc = &g_mmc; mmc_t *mmc = sdhci->mmc; + memset(&g_mmc_timing, 0, sizeof(sunxi_sdhci_timing_t)); + sdhci->timing_data = &g_mmc_timing; + /* Set timing mode based on controller ID */ if (sdhci->id == MMC_CONTROLLER_0) { mmc_host->timing_mode = SUNXI_MMC_TIMING_MODE_1; @@ -1344,5 +1343,8 @@ void sunxi_sdhci_dump_reg(sunxi_sdhci_t *sdhci) { printk_trace("dlba 0x%x\n", reg->dlba); printk_trace("idst 0x%x\n", reg->idst); printk_trace("idie 0x%x\n", reg->idie); + printk_trace("drv_dl 0x%x\n", reg->drv_dl); + printk_trace("samp_dl 0x%x\n", reg->samp_dl); + printk_trace("ds_dl 0x%x\n", reg->ds_dl); printk_trace("\n\n"); }