From ed6bcd64304ea875dddf343f00d371641c76a582 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 13 Jan 2020 23:50:55 -0400 Subject: [PATCH 001/100] [platform][vc4] initial port of little-kernel to vc4 some parts are copy/pasted from https://github.com/cleverca22/rpi-open-firmware which itself is a fork of https://github.com/christinaa/rpi-open-firmware what works: network booting lk.elf on an rpi4 (just rename to start4.elf and host over tftp) the full console with line editing and history serial over pl011 (but no serial init, relies on previous bootloader stage) reboot command irq handling for timer compare and uart one-shot timer reporting cpu exceptions such as divide by zero --- arch/vc4/arch.c | 18 ++ arch/vc4/include/arch/arch_ops.h | 55 ++++++ arch/vc4/include/arch/arch_thread.h | 7 + arch/vc4/include/arch/aspace.h | 19 ++ arch/vc4/include/arch/defines.h | 8 + arch/vc4/include/arch/spinlock.h | 70 +++++++ arch/vc4/include/arch/vc4_pcb.h | 54 +++++ arch/vc4/include/arch/vc4_traps.h | 21 ++ arch/vc4/intc.c | 207 ++++++++++++++++++++ arch/vc4/interrupt.S | 58 ++++++ arch/vc4/rules.mk | 27 +++ arch/vc4/start.S | 11 ++ arch/vc4/start.ld | 73 +++++++ arch/vc4/startup.c | 3 + arch/vc4/thread.c | 36 ++++ arch/vc4/thread_asm.S | 9 + arch/vc4/timer.c | 41 ++++ lib/cbuf/cbuf.c | 1 + lib/debugcommands/debugcommands.c | 2 + lib/libc/string/arch/vc4/rules.mk | 2 + platform/bcm28xx/include/platform/bcm28xx.h | 36 +++- platform/bcm28xx/intc.c | 10 +- platform/bcm28xx/platform.c | 25 +++ platform/bcm28xx/rules.mk | 19 +- platform/bcm28xx/uart.c | 3 + platform/bcm28xx/vc4_timer.c | 2 + project/rpi3-vpu-test.mk | 16 ++ target/rpi3-vpu/rules.mk | 9 + 28 files changed, 833 insertions(+), 9 deletions(-) create mode 100644 arch/vc4/arch.c create mode 100644 arch/vc4/include/arch/arch_ops.h create mode 100644 arch/vc4/include/arch/arch_thread.h create mode 100644 arch/vc4/include/arch/aspace.h create mode 100644 arch/vc4/include/arch/defines.h create mode 100644 arch/vc4/include/arch/spinlock.h create mode 100644 arch/vc4/include/arch/vc4_pcb.h create mode 100644 arch/vc4/include/arch/vc4_traps.h create mode 100644 arch/vc4/intc.c create mode 100644 arch/vc4/interrupt.S create mode 100644 arch/vc4/rules.mk create mode 100644 arch/vc4/start.S create mode 100644 arch/vc4/start.ld create mode 100644 arch/vc4/startup.c create mode 100644 arch/vc4/thread.c create mode 100644 arch/vc4/thread_asm.S create mode 100644 arch/vc4/timer.c create mode 100644 lib/libc/string/arch/vc4/rules.mk create mode 100644 platform/bcm28xx/vc4_timer.c create mode 100644 project/rpi3-vpu-test.mk create mode 100644 target/rpi3-vpu/rules.mk diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c new file mode 100644 index 0000000000..ea74a60122 --- /dev/null +++ b/arch/vc4/arch.c @@ -0,0 +1,18 @@ +#include +#include +#include + +void arch_early_init(void) { +} + +void arch_init(void) { +} + +void arch_idle(void) { + asm volatile("sleep"); +} + +void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3) { + PANIC_UNIMPLEMENTED; +} + diff --git a/arch/vc4/include/arch/arch_ops.h b/arch/vc4/include/arch/arch_ops.h new file mode 100644 index 0000000000..01c9ebb4ce --- /dev/null +++ b/arch/vc4/include/arch/arch_ops.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +static inline void arch_enable_ints(void) { + __asm__ volatile("ei"); +} + +static inline void arch_disable_ints(void) { + __asm__ volatile("di"); +} + +static inline bool arch_ints_disabled(void) { + uint32_t state; + + __asm__ volatile("mov %0, sr": "=r" (state)); + return !(state & 0x40000000); +} + +static inline int atomic_add(volatile int *ptr, int val) { + // TODO + *ptr += val; + return *ptr; +} + +static inline int atomic_or(volatile int *ptr, int val) { + return __atomic_fetch_or(ptr, val, __ATOMIC_RELAXED); +} + +static inline int atomic_and(volatile int *ptr, int val) { + return __atomic_fetch_and(ptr, val, __ATOMIC_RELAXED); +} + +static inline int atomic_swap(volatile int *ptr, int val) { + return __atomic_exchange_n(ptr, val, __ATOMIC_RELAXED); +} +static inline struct thread *get_current_thread(void) { + uint32_t thread_reg; + __asm__ volatile("mov %0, r29" : "=r"(thread_reg)); + return thread_reg; +} + +static inline void set_current_thread(struct thread *t) { + __asm__ volatile ("mov r29, %0" : : "r"(t)); +} + +static inline uint32_t arch_cycle_count(void) { return 0; } + +static inline uint arch_curr_cpu_num(void) { + uint32_t cpuid; + __asm__("version %0" : "=r"(cpuid)); + // TODO, one of the bits in the cpuid is the cpu#, dont remember which one + return 0; +} diff --git a/arch/vc4/include/arch/arch_thread.h b/arch/vc4/include/arch/arch_thread.h new file mode 100644 index 0000000000..5d790ce073 --- /dev/null +++ b/arch/vc4/include/arch/arch_thread.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +struct arch_thread { + uint32_t sp; +}; diff --git a/arch/vc4/include/arch/aspace.h b/arch/vc4/include/arch/aspace.h new file mode 100644 index 0000000000..e8d26ff0d2 --- /dev/null +++ b/arch/vc4/include/arch/aspace.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#pragma once + +#include + +__BEGIN_CDECLS + +struct arch_aspace { + // nothing for now, does not support address spaces other than the kernel +}; + +__END_CDECLS + diff --git a/arch/vc4/include/arch/defines.h b/arch/vc4/include/arch/defines.h new file mode 100644 index 0000000000..9db873d37c --- /dev/null +++ b/arch/vc4/include/arch/defines.h @@ -0,0 +1,8 @@ +#pragma once + +#define PAGE_SIZE 4096 +#define PAGE_SIZE_SHIFT 12 + +#define ARCH_DEFAULT_STACK_SIZE 4096 + +#define CACHE_LINE 32 // TODO, confirm diff --git a/arch/vc4/include/arch/spinlock.h b/arch/vc4/include/arch/spinlock.h new file mode 100644 index 0000000000..7cc8c923cb --- /dev/null +++ b/arch/vc4/include/arch/spinlock.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 Travis Geiselbrecht + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#pragma once + +#include +#include + +#if WITH_SMP +#error vc4 does not support SMP +#endif + +#define SPIN_LOCK_INITIAL_VALUE (0) + +typedef unsigned int spin_lock_t; + +typedef unsigned int spin_lock_saved_state_t; +typedef unsigned int spin_lock_save_flags_t; + +static inline void arch_spin_lock(spin_lock_t *lock) { + *lock = 1; +} + +static inline int arch_spin_trylock(spin_lock_t *lock) { + return 0; +} + +static inline void arch_spin_unlock(spin_lock_t *lock) { + *lock = 0; +} + +static inline void arch_spin_lock_init(spin_lock_t *lock) { + *lock = SPIN_LOCK_INITIAL_VALUE; +} + +static inline bool arch_spin_lock_held(spin_lock_t *lock) { + return *lock != 0; +} + +/* default arm flag is to just disable plain irqs */ +#define ARCH_DEFAULT_SPIN_LOCK_FLAG_INTERRUPTS 0 + +enum { + /* private */ + SPIN_LOCK_STATE_RESTORE_IRQ = 1, +}; + +static inline void +arch_interrupt_save(spin_lock_saved_state_t *statep, spin_lock_save_flags_t flags) { + spin_lock_saved_state_t state = 0; + if (!arch_ints_disabled()) { + state |= SPIN_LOCK_STATE_RESTORE_IRQ; + arch_disable_ints(); + } + *statep = state; +} + +static inline void +arch_interrupt_restore(spin_lock_saved_state_t old_state, spin_lock_save_flags_t flags) { + if (old_state & SPIN_LOCK_STATE_RESTORE_IRQ) + arch_enable_ints(); +} + + + + diff --git a/arch/vc4/include/arch/vc4_pcb.h b/arch/vc4/include/arch/vc4_pcb.h new file mode 100644 index 0000000000..a334adc331 --- /dev/null +++ b/arch/vc4/include/arch/vc4_pcb.h @@ -0,0 +1,54 @@ +/*============================================================================= +Copyright (C) 2016-2017 Authors of rpi-open-firmware +All rights reserved. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +FILE DESCRIPTION +Process control block. + +=============================================================================*/ + +#pragma once + +typedef struct { + uint32_t r23; + uint32_t r22; + uint32_t r21; + uint32_t r20; + uint32_t r19; + uint32_t r18; + uint32_t r17; + uint32_t r16; + uint32_t r15; + uint32_t r14; + uint32_t r13; + uint32_t r12; + uint32_t r11; + uint32_t r10; + uint32_t r9; + uint32_t r8; + uint32_t r7; + uint32_t r6; + + uint32_t r5; + uint32_t r4; + uint32_t r3; + uint32_t r2; + uint32_t r1; + uint32_t r0; + + uint32_t lr; + + uint32_t sr; + uint32_t pc; +} vc4_saved_state_t; + diff --git a/arch/vc4/include/arch/vc4_traps.h b/arch/vc4/include/arch/vc4_traps.h new file mode 100644 index 0000000000..1d30d36c2b --- /dev/null +++ b/arch/vc4/include/arch/vc4_traps.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +void fleh_zero(void); +void fleh_misaligned(void); +void fleh_dividebyzero(); +void fleh_undefinedinstruction(); +void fleh_forbiddeninstruction(); +void fleh_illegalmemory(); +void fleh_buserror(); +void fleh_floatingpoint(); +void fleh_isp(); +void fleh_dummy(); +void fleh_icache(); +void fleh_veccore(); +void fleh_badl2alias(); +void fleh_breakpoint(); +void fleh_unknown(); +void fleh_irq(); +void print_vpu_state(vc4_saved_state_t* pcb); diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c new file mode 100644 index 0000000000..57eb95d6f8 --- /dev/null +++ b/arch/vc4/intc.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +struct handlerArgPair { + int_handler h; + void *arg; +}; +typedef void (*irqType)(void); + +struct handlerArgPair irq_handlers[64]; +// when an exception or interrupt occurs, the cpu will make sp into an alias pointing to r28 +// it will then push pc and sr onto the new stack +// it will then read an entry from this vector table, and set the PC to that entry +// if the highest bit on this addr is set, the cpu will switch into supervisor mode +irqType __attribute__ ((aligned (512))) vectorTable[144]; // might only need to be 128 entries + +static const char* g_ExceptionNames[] = { + "Zero", + "Misaligned", + "Division by zero", + "Undefined instruction", + "Forbidden instruction", + "Illegal memory", + "Bus error", + "Floating point exception", + "ISP", + "Dummy", + "ICache", + "Vector core exception", + "Bad L2 alias", + "Breakpoint" +}; + +void set_interrupt(int intno, bool enable, int core) { + uint32_t base = (core == 0) ? IC0_BASE : IC1_BASE; + + int offset = 0x10 + ((intno >> 3) << 2); + uint32_t slot = 0xF << ((intno & 7) << 2); + + uint32_t v = *REG32(base + offset) & ~slot; + *REG32(base + offset) = enable ? v | slot : v; +} + + +void intc_init(void) { + // TODO + for (int i=0; i<64; i++) { + irq_handlers[0].h = 0; // is this needed? maybe .bss already took care of it? + set_interrupt(i, false, 0); + set_interrupt(i, false, 1); + } + // https://github.com/hermanhermitage/videocoreiv/wiki/VideoCore-IV-Programmers-Manual#interrupts + // processor internal exceptions + vectorTable[0] = fleh_zero; + vectorTable[1] = fleh_misaligned; + vectorTable[2] = fleh_dividebyzero; + vectorTable[3] = fleh_undefinedinstruction; + vectorTable[4] = fleh_forbiddeninstruction; + vectorTable[5] = fleh_illegalmemory; + vectorTable[6] = fleh_buserror; + vectorTable[7] = fleh_floatingpoint; + vectorTable[8] = fleh_isp; + vectorTable[9] = fleh_dummy; + vectorTable[10] = fleh_icache; + vectorTable[11] = fleh_veccore; + vectorTable[12] = fleh_badl2alias; + vectorTable[13] = fleh_breakpoint; + for (int i=14; i<=31; i++) { + vectorTable[i] = fleh_unknown; + } + // swi opcode handler + for (int i=32; i<=63; i++) { + vectorTable[i] = fleh_irq; + } + // external interrupts + for (int i=64; i<=127; i++) { + vectorTable[i] = fleh_irq; + } + + *REG32(IC0_VADDR) = vectorTable; + *REG32(IC1_VADDR) = vectorTable; + + if (*REG32(IC0_VADDR) != vectorTable) { + printf("vector table now at 0x%08lx 0x%08lx\n", *REG32(IC0_VADDR), (uint32_t)vectorTable); + panic("vector table failed to install"); + } +} + +#define REGISTER_FORMAT_STRING(prefix) \ + prefix " r0: 0x%08x r1: 0x%08x r2: 0x%08x r3: 0x%08x\n" \ + prefix " r4: 0x%08x r5: 0x%08x r6: 0x%08x r7: 0x%08x\n" \ + prefix " r8: 0x%08x r9: 0x%08x r10: 0x%08x r11: 0x%08x\n" \ + prefix " r12: 0x%08x r13: 0x%08x r14: 0x%08x r15: 0x%08x\n" \ + prefix " pc: 0x%08x lr: 0x%08x sr: 0x%08x\n" + +void print_vpu_state(vc4_saved_state_t* pcb) { + printf("VPU registers:\n"); + + printf( + REGISTER_FORMAT_STRING(" "), + pcb->r0, + pcb->r1, + pcb->r2, + pcb->r3, + pcb->r4, + pcb->r5, + pcb->r6, + pcb->r7, + pcb->r8, + pcb->r9, + pcb->r10, + pcb->r11, + pcb->r12, + pcb->r13, + pcb->r14, + pcb->r15, + pcb->pc, + pcb->lr, + pcb->sr + ); + + printf("Exception info (IC0):\n"); + + printf( + " src0: 0x%08x src1: 0x%08x vaddr: 0x%08x\n" + " C: 0x%08x S: 0x%08x\n", + *REG32(IC0_SRC0), + *REG32(IC0_SRC1), + *REG32(IC0_VADDR), + *REG32(IC0_C), + *REG32(IC0_S) + ); + + printf("Exception info (IC1):\n"); + + printf( + " src0: 0x%08x src1: 0x%08x vaddr: 0x%08x\n" + " C: 0x%08x S: 0x%08x\n", + *REG32(IC1_SRC0), + *REG32(IC1_SRC1), + *REG32(IC1_VADDR), + *REG32(IC1_C), + *REG32(IC1_S) + ); +} + +void register_int_handler(unsigned int vector, int_handler handler, void *arg) { + assert(vector < 64); + __asm__ volatile("di"); + irq_handlers[vector].h = handler; + irq_handlers[vector].arg = arg; + __asm__ volatile("ei"); +} + +status_t unmask_interrupt(unsigned int vector) { + assert(vector < 64); + set_interrupt(vector, true, 0); + return NO_ERROR; +} + +static const char* exception_name(uint32_t n) { + if (n >= (sizeof(g_ExceptionNames)/4)) return "unknown"; + return g_ExceptionNames[n]; +} + +// c mode handlers, called by interrupt.S + +void sleh_fatal(vc4_saved_state_t* pcb, uint32_t n) { + printf("Fatal VPU Exception: %s\n", exception_name(n)); + + print_vpu_state(pcb); + + printf("We are hanging here ...\n"); + + while(true) __asm__ volatile ("nop"); +} + +void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { + uint32_t status = *REG32(IC0_S); + uint32_t source = status & 0xFF; + uint32_t cs; + int ret; + + //dprintf(INFO, "VPU Received interrupt from source %d\n", source); + + switch (source) { + case 64: // timer0 + case 121: // uart + assert(irq_handlers[source - 64].h); + ret = irq_handlers[source - 64].h(irq_handlers[source - 64].arg); + if (ret == INT_RESCHEDULE) thread_preempt(); + break; + case INTERRUPT_ARM: + // fired when the arm cpu writes to the arm->vpu mailbox + break; + default: + print_vpu_state(pcb); + panic("unknown interrupt source!"); + } +} diff --git a/arch/vc4/interrupt.S b/arch/vc4/interrupt.S new file mode 100644 index 0000000000..33ce5f4a55 --- /dev/null +++ b/arch/vc4/interrupt.S @@ -0,0 +1,58 @@ +.macro SaveRegsLower + stm lr, (--sp) + stm r0-r5, (--sp) +.endm + +.macro SaveRegsUpper + stm r6-r15, (--sp) + stm r16-r23, (--sp) +.endm + +.macro SaveRegsAll + SaveRegsLower + SaveRegsUpper +.endm + +.macro ExceptionHandler label, exception_number +.global fleh_\label +fleh_\label: + SaveRegsLower + mov r1, \exception_number + b irq_fatal +.endm + +.text +irq_fatal: + SaveRegsUpper + mov r0, sp + b sleh_fatal + + ExceptionHandler zero, #0 + ExceptionHandler misaligned, #1 + ExceptionHandler dividebyzero, #2 + ExceptionHandler undefinedinstruction, #3 + ExceptionHandler forbiddeninstruction, #4 + ExceptionHandler illegalmemory, #5 + ExceptionHandler buserror, #6 + ExceptionHandler floatingpoint, #7 + ExceptionHandler isp, #8 + ExceptionHandler dummy, #9 + ExceptionHandler icache, #10 + ExceptionHandler veccore, #11 + ExceptionHandler badl2alias, #12 + ExceptionHandler breakpoint, #13 + ExceptionHandler unknown, #14 + +.global fleh_irq +fleh_irq: + SaveRegsAll + mov r0, sp + mov r1, r29 + di + bl sleh_irq +return_from_exception: + ldm r16-r23, (sp++) + ldm r6-r15, (sp++) + ldm r0-r5, (sp++) + ld lr, (sp++) + rti diff --git a/arch/vc4/rules.mk b/arch/vc4/rules.mk new file mode 100644 index 0000000000..d1b0d66c65 --- /dev/null +++ b/arch/vc4/rules.mk @@ -0,0 +1,27 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +TOOLCHAIN_PREFIX := vc4-elf- + +$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/start.ld + @echo generating $@ + @$(MKDIR) + echo TODO: properly template the linker script + cp $< $@ + +# TODO, fix the linker flags +ARCH_LDFLAGS += -L/nix/store/cwpy4q0qvdwdif1zfwnfg5gi50c6j9w8-vc4-elf-stage-final-gcc-debug-6.5.0/lib/gcc/vc4-elf/6.2.1/ + +MODULE_SRCS += \ + $(LOCAL_DIR)/timer.c \ + $(LOCAL_DIR)/arch.c \ + $(LOCAL_DIR)/thread.c \ + $(LOCAL_DIR)/intc.c \ + $(LOCAL_DIR)/start.S \ + $(LOCAL_DIR)/thread_asm.S \ + $(LOCAL_DIR)/interrupt.S \ + +GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1 + +include make/module.mk diff --git a/arch/vc4/start.S b/arch/vc4/start.S new file mode 100644 index 0000000000..949ee73a70 --- /dev/null +++ b/arch/vc4/start.S @@ -0,0 +1,11 @@ +#include + +.text +FUNCTION(_start) +.global _start +_start: + di + mov sp, _fstack + bl lk_main +loop: + b loop diff --git a/arch/vc4/start.ld b/arch/vc4/start.ld new file mode 100644 index 0000000000..b481f243fd --- /dev/null +++ b/arch/vc4/start.ld @@ -0,0 +1,73 @@ +/* + * based heavily on https://github.com/ptesarik/vc4boot + */ + +OUTPUT_FORMAT("elf32-vc4", "elf32-vc4", "elf32-vc4") +OUTPUT_ARCH(vc4) +ENTRY(_start) +GROUP(-lgloss -lc -lteststub -lgcc) + +MEMORY { + /* in the C alias, direct uncached + */ + ram (rwx) : ORIGIN = 0xc0000000 + 2M, LENGTH = 20M +} +SECTIONS { + .text : ALIGN(32) { + PROVIDE(_start = .); + . = ALIGN(4); + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + KEEP (*(.init)) + KEEP (*(.fini)) + KEEP (*(.jcr)) + _etext = .; + } >ram =0 + + .rodata : { + . = ALIGN(4); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + _erodata = .; + } >ram + + .init_array : { + PROVIDE (__init_array_start = .); + __ctor_list = .; + *(.init_array) + *(.init_array.*) + *(.ctors) + *(.ctors.*) + __init_array_end = .; + __ctor_end = .; + } >ram + + .data : { + . = ALIGN(4); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + SORT(CONSTRUCTORS) + *(.sdata .sdata.* .gnu.linkonce.s.*) + _edata = .; + } >ram + + .bss : { + . = ALIGN(4); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _end = .; + PROVIDE (end = .); + } >ram + + /* First location in stack is highest address in RAM */ + PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4); +} diff --git a/arch/vc4/startup.c b/arch/vc4/startup.c new file mode 100644 index 0000000000..52cef6d0d9 --- /dev/null +++ b/arch/vc4/startup.c @@ -0,0 +1,3 @@ +void vc4_start() { + lk_main(); +} diff --git a/arch/vc4/thread.c b/arch/vc4/thread.c new file mode 100644 index 0000000000..c11beac702 --- /dev/null +++ b/arch/vc4/thread.c @@ -0,0 +1,36 @@ +#include +#include + +void vc4_context_switch(uint32_t *oldsp, uint32_t newsp); + +void arch_context_switch(thread_t *oldthread, thread_t *newthread) { + vc4_context_switch(&oldthread->arch.sp, newthread->arch.sp); +} + +static inline void push(thread_t *t, uint32_t val) { + // SP always points to the last valid value in the stack + t->arch.sp -= 4; + volatile uint32_t *ram32 = 0; + ram32[t->arch.sp/4] = val; +} + +static void initial_thread_func(void) __NO_RETURN; +static void initial_thread_func(void) { + thread_t *ct = get_current_thread(); + + int ret = ct->entry(ct->arg); + + thread_exit(ret); +} + +void arch_thread_initialize(thread_t *t) { + t->arch.sp = (t->stack + t->stack_size) - 4; + push(t, &initial_thread_func); + push(t, 0); // the initial frame-pointer +} + +void arch_dump_thread(thread_t *t) { + if (t->state != THREAD_RUNNING) { + dprintf(INFO, "\tarch: sp 0x%x\n", t->arch.sp); + } +} diff --git a/arch/vc4/thread_asm.S b/arch/vc4/thread_asm.S new file mode 100644 index 0000000000..b61bbcb95a --- /dev/null +++ b/arch/vc4/thread_asm.S @@ -0,0 +1,9 @@ +.text +.global vc4_context_switch +// r0 is address to save the sp to +// r1 is the new sp to load +vc4_context_switch: + stm r6,lr,(--sp) + st sp, (r0) + mov sp, r1 + ldm r6,pc,(sp++) diff --git a/arch/vc4/timer.c b/arch/vc4/timer.c new file mode 100644 index 0000000000..572f090832 --- /dev/null +++ b/arch/vc4/timer.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include + +static enum handler_return timer0_irq(void *arg); + +lk_bigtime_t current_time_hires(void) { + //TODO, deal with rollover + return ( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO); +} + +lk_time_t current_time(void) { + return *REG32(ST_CLO); +} + +static platform_timer_callback timer_cb = 0;; +static void *timer_arg = 0;; + +status_t platform_set_oneshot_timer (platform_timer_callback callback, void *arg, lk_time_t interval) { + timer_cb = callback; + timer_arg = arg; + *REG32(ST_C0) = *REG32(ST_CLO) + (interval * 1000); + register_int_handler(0, timer0_irq, NULL); + unmask_interrupt(0); + + return NO_ERROR; +} + +static enum handler_return timer0_irq(void *arg) { + uint32_t cs = *REG32(ST_CS); + *REG32(ST_CS) = cs; // ack the event so the irq signal clears + assert(timer_cb); + return timer_cb(timer_arg, current_time()); +} + +void platform_stop_timer(void) { +} diff --git a/lib/cbuf/cbuf.c b/lib/cbuf/cbuf.c index 50fb963c16..7e2f523bbb 100644 --- a/lib/cbuf/cbuf.c +++ b/lib/cbuf/cbuf.c @@ -219,6 +219,7 @@ size_t cbuf_read_char(cbuf_t *cbuf, char *c, bool block) { DEBUG_ASSERT(c); retry: + DEBUG_ASSERT(cbuf->event.magic == EVENT_MAGIC); if (block) event_wait(&cbuf->event); diff --git a/lib/debugcommands/debugcommands.c b/lib/debugcommands/debugcommands.c index a23a66ab12..17b9581055 100644 --- a/lib/debugcommands/debugcommands.c +++ b/lib/debugcommands/debugcommands.c @@ -310,6 +310,8 @@ static int cmd_crash(int argc, const cmd_args *argv) { volatile uint32_t *ptr = (void *)1; *ptr = 1; + volatile int a = 1 / 0; + /* if it didn't, panic the system */ panic("crash"); diff --git a/lib/libc/string/arch/vc4/rules.mk b/lib/libc/string/arch/vc4/rules.mk new file mode 100644 index 0000000000..7a97451a6d --- /dev/null +++ b/lib/libc/string/arch/vc4/rules.mk @@ -0,0 +1,2 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index f4b06f06e9..2198d55ed4 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -8,15 +8,21 @@ #pragma once #define SDRAM_BASE 0 +#ifdef BCM2XXX_VPU +#define BCM_PERIPH_BASE_PHYS (0x7e000000U) +#else /* Note: BCM2836/BCM2837 use different peripheral base than BCM2835 */ #define BCM_PERIPH_BASE_PHYS (0x3f000000U) +#endif #define BCM_PERIPH_SIZE (0x01100000U) #if BCM2836 -#define BCM_PERIPH_BASE_VIRT (0xe0000000U) + #define BCM_PERIPH_BASE_VIRT (0xe0000000U) #elif BCM2837 -#define BCM_PERIPH_BASE_VIRT (0xffffffffc0000000ULL) -#define MEMORY_APERTURE_SIZE (1024 * 1024 * 1024) + #define BCM_PERIPH_BASE_VIRT (0xffffffffc0000000ULL) + #define MEMORY_APERTURE_SIZE (1024 * 1024 * 1024) +#elif BCM2XXX_VPU + #define BCM_PERIPH_BASE_VIRT (0x7e000000U) #else #error Unknown BCM28XX Variant #endif @@ -28,6 +34,7 @@ #define BCM_LOCAL_PERIPH_BASE_VIRT (BCM_PERIPH_BASE_VIRT + 0x01000000) #define IC0_BASE (BCM_PERIPH_BASE_VIRT + 0x2000) +#define IC1_BASE (BCM_PERIPH_BASE_VIRT + 0x2800) #define ST_BASE (BCM_PERIPH_BASE_VIRT + 0x3000) #define MPHI_BASE (BCM_PERIPH_BASE_VIRT + 0x6000) #define DMA_BASE (BCM_PERIPH_BASE_VIRT + 0x7000) @@ -49,6 +56,29 @@ #define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) #define MCORE_BASE (BCM_PERIPH_BASE_VIRT + 0x0000) +#define ST_CS (ST_BASE + 0x0) +#define ST_CLO (ST_BASE + 0x4) +#define ST_CHI (ST_BASE + 0x8) +#define ST_C0 (ST_BASE + 0xc) + +#define IC0_C (IC0_BASE + 0x0) +#define IC0_S (IC0_BASE + 0x4) +#define IC0_SRC0 (IC0_BASE + 0x8) +#define IC0_SRC1 (IC0_BASE + 0xc) +#define IC0_VADDR (IC0_BASE + 0x30) + +#define IC1_C (IC1_BASE + 0x0) +#define IC1_S (IC1_BASE + 0x4) +#define IC1_SRC0 (IC1_BASE + 0x8) +#define IC1_SRC1 (IC1_BASE + 0xc) +#define IC1_VADDR (IC1_BASE + 0x30) + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC (PM_BASE + 0x1c) +#define PM_RSTC_WRCFG_CLR 0xffffffcf // mask to keep everything but the watchdog config +#define PM_WDOG (PM_BASE + 0x24) +#define PM_WDOG_MASK 0x00000fff + #define ARMCTRL_BASE (ARM_BASE + 0x000) #define ARMCTRL_INTC_BASE (ARM_BASE + 0x200) #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) diff --git a/platform/bcm28xx/intc.c b/platform/bcm28xx/intc.c index cf85322a45..3f944cbcbb 100644 --- a/platform/bcm28xx/intc.c +++ b/platform/bcm28xx/intc.c @@ -14,13 +14,15 @@ #include #include #include +#include #if defined (BCM2836) -#include -typedef struct arm_iframe arm_platform_iframe_t; + #include + typedef struct arm_iframe arm_platform_iframe_t; #elif defined (BCM2837) -#include -typedef struct arm64_iframe_long arm_platform_iframe_t; + #include + typedef struct arm64_iframe_long arm_platform_iframe_t; +#elif defined BCM2XXX_VPU #else #error Unknown BCM28XX Variant #endif diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index e2c62efb57..76c2782237 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -15,7 +15,11 @@ #include #include #include + +#ifndef BCM2XXX_VPU #include +#endif + #include #include #include @@ -89,6 +93,8 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { #define DEBUG_UART 1 +#elif BCM2XXX_VPU + #define DEBUG_UART 0 #else #error Unknown BCM28XX Variant #endif @@ -159,12 +165,15 @@ void platform_early_init(void) { #elif BCM2836 arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 1000000); +#elif BCM2XXX_VPU #else #error Unknown BCM28XX Variant #endif +#ifdef WITH_KERNEL_VM /* add the main memory arena */ pmm_add_arena(&arena); +#endif #if BCM2837 /* reserve the first 64k of ram, which should be holding the fdt */ @@ -215,3 +224,19 @@ int platform_dgetc(char *c, bool wait) { return 0; } +void platform_halt(platform_halt_action suggested_action, + platform_halt_reason reason) { + if (suggested_action == HALT_ACTION_REBOOT) { + *REG32(PM_WDOG) = PM_PASSWORD | (1 & PM_WDOG_MASK); + uint32_t t = *REG32(PM_RSTC); + t &= PM_RSTC_WRCFG_CLR; + t |= 0x20; + *REG32(PM_RSTC) = PM_PASSWORD | t; + dprintf(ALWAYS, "waiting for watchdog\n"); + arch_disable_ints(); + for (;;); + } + dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); + arch_disable_ints(); + for (;;); +} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 8f29103603..2a0ed86c9b 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -5,9 +5,14 @@ MODULE := $(LOCAL_DIR) WITH_SMP := 1 #LK_HEAP_IMPLEMENTATION ?= dlmalloc +ifeq ($(ARCJ),arm) MODULE_DEPS := \ dev/timer/arm_generic \ lib/cbuf +MODULE_SRCS += + $(LOCAL_DIR)/mailbox.c \ + +endif #lib/bio \ @@ -18,9 +23,8 @@ MODULE_DEPS := \ MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ - $(LOCAL_DIR)/intc.c \ $(LOCAL_DIR)/platform.c \ - $(LOCAL_DIR)/mailbox.c \ + #$(LOCAL_DIR)/intc.c \ MEMBASE := 0x00000000 @@ -65,6 +69,17 @@ MODULE_DEPS += \ app/shell \ app/tests \ lib/fdt +else ifeq ($(TARGET),rpi3-vpu) +ARCH ?= vc4 +MEMSIZE ?= 0x1400000 # 20MB +MEMBASE ?= 0 +GLOBAL_DEFINES += \ + BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ + MEMSIZE=$(MEMSIZE) \ + MEMBASE=$(MEMBASE) \ + +MODULE_SRCS += \ + $(LOCAL_DIR)/uart.c endif diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 914a529775..4f070e97d3 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -13,6 +13,7 @@ #include #include #include +#include /* TODO: extract this into a generic PL011 driver */ @@ -75,6 +76,7 @@ void uart_init(void) { for (size_t i = 0; i < NUM_UART; i++) { // create circular buffer to hold received data cbuf_initialize(&uart_rx_buf[i], RXBUF_SIZE); + DEBUG_ASSERT(uart_rx_buf[i].event.magic == EVENT_MAGIC); // assumes interrupts are contiguous register_int_handler(INTERRUPT_VC_UART + i, &uart_irq, (void *)i); @@ -117,6 +119,7 @@ int uart_getc(int port, bool wait) { cbuf_t *rxbuf = &uart_rx_buf[port]; char c; + assert(port < NUM_UART); if (cbuf_read_char(rxbuf, &c, wait) == 1) return c; diff --git a/platform/bcm28xx/vc4_timer.c b/platform/bcm28xx/vc4_timer.c new file mode 100644 index 0000000000..626b51a4d6 --- /dev/null +++ b/platform/bcm28xx/vc4_timer.c @@ -0,0 +1,2 @@ +lk_bigtime_t current_time_hires(void) { +} diff --git a/project/rpi3-vpu-test.mk b/project/rpi3-vpu-test.mk new file mode 100644 index 0000000000..065b739836 --- /dev/null +++ b/project/rpi3-vpu-test.mk @@ -0,0 +1,16 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi3-vpu +ARCH := vc4 + +MODULES += \ + app/shell \ + app/stringtests \ + app/tests \ + lib/cksum \ + lib/debugcommands \ + + + + + diff --git a/target/rpi3-vpu/rules.mk b/target/rpi3-vpu/rules.mk new file mode 100644 index 0000000000..fe10d50d72 --- /dev/null +++ b/target/rpi3-vpu/rules.mk @@ -0,0 +1,9 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +GLOBAL_INCLUDES += \ + $(LOCAL_DIR)/include + +PLATFORM := bcm28xx + +#include make/module.mk + From 6177b6048acfd59607cccd16270f35fafe48f1e3 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 14 Jan 2020 07:13:09 -0400 Subject: [PATCH 002/100] [platform][vc4] implement setting the baud rate, currently hard-coded to 115200 --- platform/bcm28xx/include/platform/bcm28xx.h | 4 + .../include/platform/bcm28xx/pll_read.h | 18 ++++ platform/bcm28xx/platform.c | 4 + platform/bcm28xx/pll_read.c | 87 +++++++++++++++++++ platform/bcm28xx/rules.mk | 6 +- platform/bcm28xx/uart.c | 52 ++++++++++- .../{rpi3-vpu-test.mk => rpi4-vpu-test.mk} | 2 +- target/{rpi3-vpu => rpi4-vpu}/rules.mk | 0 8 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 platform/bcm28xx/include/platform/bcm28xx/pll_read.h create mode 100644 platform/bcm28xx/pll_read.c rename project/{rpi3-vpu-test.mk => rpi4-vpu-test.mk} (88%) rename target/{rpi3-vpu => rpi4-vpu}/rules.mk (100%) diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 2198d55ed4..f5a3a60826 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -40,6 +40,7 @@ #define DMA_BASE (BCM_PERIPH_BASE_VIRT + 0x7000) #define ARM_BASE (BCM_PERIPH_BASE_VIRT + 0xB000) #define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) +#define CM_BASE (BCM_PERIPH_BASE_VIRT + 0x101000) #define PCM_CLOCK_BASE (BCM_PERIPH_BASE_VIRT + 0x101098) #define RNG_BASE (BCM_PERIPH_BASE_VIRT + 0x104000) #define GPIO_BASE (BCM_PERIPH_BASE_VIRT + 0x200000) @@ -61,6 +62,9 @@ #define ST_CHI (ST_BASE + 0x8) #define ST_C0 (ST_BASE + 0xc) +#define CM_UARTCTL (CM_BASE + 0xf0) +#define CM_UARTDIV (CM_BASE + 0xf4) + #define IC0_C (IC0_BASE + 0x0) #define IC0_S (IC0_BASE + 0x4) #define IC0_SRC0 (IC0_BASE + 0x8) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h new file mode 100644 index 0000000000..f7f95c9dc0 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif +uint32_t clk_get_input_freq(volatile uint32_t *ctlreg); +uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg); +uint32_t get_vpu_per_freq(); +uint32_t get_uart_base_freq(); +uint32_t plla(); +uint32_t pllb(); +uint32_t pllc(); +uint32_t plld(); +uint32_t pllh(); +extern uint32_t xtal_freq; +#ifdef __cplusplus +} +#endif diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 76c2782237..33590d71b4 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -23,6 +23,7 @@ #include #include #include +#include #if BCM2836 #include @@ -114,6 +115,9 @@ void platform_init_mmu_mappings(void) { } void platform_early_init(void) { + // 19.2mhz for most models + // 54mhz for rpi4 + xtal_freq = CRYSTAL; uart_init_early(); intc_init(); diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c new file mode 100644 index 0000000000..795a107ba6 --- /dev/null +++ b/platform/bcm28xx/pll_read.c @@ -0,0 +1,87 @@ +#include +#include +#include + +uint32_t xtal_freq; + +uint32_t get_vpu_per_freq() { + return clk_get_freq(&CM_VPUDIV, &CM_VPUCTL); +} + +uint32_t get_uart_base_freq() { + return clk_get_freq(&CM_UARTDIV, &CM_UARTCTL); +} + +uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { + uint32_t ndiv = A2W_PLLC_CTRL & A2W_PLLC_CTRL_NDIV_SET; + uint32_t pdiv = (A2W_PLLC_CTRL & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; + uint64_t mult1 = (ndiv << 20) | frac; + mult1 *= pdiv; + // TODO, the optional /2 phase + uint32_t freq = (xtal_freq * mult1) >> 20; + return freq; +} + +uint32_t plla() { + return compute_pll_freq(A2W_PLLA_CTRL, A2W_PLLA_FRAC & A2W_PLLA_FRAC_MASK); +} + +uint32_t pllb() { + return compute_pll_freq(A2W_PLLB_CTRL, A2W_PLLB_FRAC & A2W_PLLB_FRAC_MASK); +} + +uint32_t pllc() { + //uint32_t ana1 = A2W_PLLC_ANA1; + uint32_t ctrl = A2W_PLLC_CTRL; + uint32_t frac = A2W_PLLC_FRAC & A2W_PLLC_FRAC_MASK; + return compute_pll_freq(ctrl, frac); +} + +uint32_t plld() { + return compute_pll_freq(A2W_PLLD_CTRL, A2W_PLLD_FRAC & A2W_PLLD_FRAC_MASK); +} + +uint32_t pllh() { + return compute_pll_freq(A2W_PLLH_CTRL, A2W_PLLH_FRAC & A2W_PLLH_FRAC_MASK); +} + +uint32_t pllc_core0() { + uint32_t ctrl = A2W_PLLC_CORE0; + uint32_t div = ctrl & A2W_PLLC_CORE0_DIV_SET; + uint32_t pllc_freq = pllc(); + return pllc_freq / div; +} + +uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg) { + uint32_t div = *divreg; + if (div == 0) return 0; + uint64_t input_freq = clk_get_input_freq(ctlreg); + return ((input_freq << 12) / *divreg); +} + +uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) { + uint32_t ctl = *ctlreg; + switch (ctl & 0xf) { + case 0: // GND clock source + return 0; + case 1: // crystal oscilator + return xtal_freq; + case 2: // test debug 0 + case 3: // test debug 1 + return 0; + case 4: // plla + return 0; + case 5: // pllc_core0 + return pllc_core0(); + case 6: // plld_per + return 0; + case 7: // pllh_aux + return 0; + case 8: // pllc_core1? + return 0; + case 9: // pllc_core2? + return 0; + default: + return 0; + } +} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 2a0ed86c9b..8fd2216f58 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -69,7 +69,7 @@ MODULE_DEPS += \ app/shell \ app/tests \ lib/fdt -else ifeq ($(TARGET),rpi3-vpu) +else ifeq ($(TARGET),rpi4-vpu) ARCH ?= vc4 MEMSIZE ?= 0x1400000 # 20MB MEMBASE ?= 0 @@ -77,9 +77,11 @@ GLOBAL_DEFINES += \ BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ MEMSIZE=$(MEMSIZE) \ MEMBASE=$(MEMBASE) \ + CRYSTAL=54000000 \ MODULE_SRCS += \ - $(LOCAL_DIR)/uart.c + $(LOCAL_DIR)/uart.c \ + $(LOCAL_DIR)/pll_read.c \ endif diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 4f070e97d3..9ff209fb36 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -8,11 +8,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include /* TODO: extract this into a generic PL011 driver */ @@ -40,6 +42,12 @@ static cbuf_t uart_rx_buf[NUM_UART]; +static int cmd_uart_dump(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dump_uart_state", "print uart state relating to baud", &cmd_uart_dump) +STATIC_COMMAND_END(uart); + static inline uintptr_t uart_to_ptr(unsigned int n) { switch (n) { default: @@ -48,6 +56,12 @@ static inline uintptr_t uart_to_ptr(unsigned int n) { } } +static uint32_t calculate_baud_divisor(uint32_t baud) { + uint32_t uart_freq = get_uart_base_freq(); + uint32_t divisor = (uart_freq << 6) / baud / 16; + return divisor; +} + static enum handler_return uart_irq(void *arg) { bool resched = false; uint port = (uint)arg; @@ -72,18 +86,38 @@ static enum handler_return uart_irq(void *arg) { return resched ? INT_RESCHEDULE : INT_NO_RESCHEDULE; } +static void uart_flush(int port) { + uintptr_t base = uart_to_ptr(port); + while (UARTREG(base, UART_TFR) & 0x20); +} + void uart_init(void) { for (size_t i = 0; i < NUM_UART; i++) { + uintptr_t base = uart_to_ptr(i); + // create circular buffer to hold received data cbuf_initialize(&uart_rx_buf[i], RXBUF_SIZE); DEBUG_ASSERT(uart_rx_buf[i].event.magic == EVENT_MAGIC); // assumes interrupts are contiguous register_int_handler(INTERRUPT_VC_UART + i, &uart_irq, (void *)i); + uint32_t divisor = calculate_baud_divisor(115200); + dprintf(INFO, "changing divisor to %d\n", divisor); + + uart_flush(i); + + UARTREG(base, UART_CR) = 0; // shutdown the entire uart // clear all irqs UARTREG(uart_to_ptr(i), UART_ICR) = 0x3ff; + UARTREG(base, UART_LCRH) = 0x70; // fifo enable, 8bit mode + + if (divisor > 0) { + UARTREG(base, UART_IBRD) = (divisor >> 6) & 0xffff; + UARTREG(base, UART_FBRD) = divisor & 0x3f; + } + // set fifo trigger level UARTREG(uart_to_ptr(i), UART_IFLS) = 0; // 1/8 rxfifo, 1/8 txfifo @@ -91,7 +125,7 @@ void uart_init(void) { UARTREG(uart_to_ptr(i), UART_IMSC) = (1<<6)|(1<<4); // rtim, rxim // enable receive - UARTREG(uart_to_ptr(i), UART_CR) |= (1<<9); // rxen + UARTREG(uart_to_ptr(i), UART_CR) |= (1<<9) | (1<<8) | (1<<0); // rxen, tx_enable, uarten // enable interrupt unmask_interrupt(INTERRUPT_VC_UART + i); @@ -135,4 +169,20 @@ void uart_flush_rx(int port) { void uart_init_port(int port, uint baud) { } +static int cmd_uart_dump(int argc, const cmd_args *argv) { + uintptr_t base = uart_to_ptr(0); + uint32_t baud = 115200; + if (argc >= 2) { + baud = argv[1].u; + } + + dprintf(INFO, "CM_UARTDIV: 0x%x\nCM_UARTCTL: 0x%x\n", *REG32(CM_UARTDIV), *REG32(CM_UARTCTL)); + dprintf(INFO, "UART_IBRD: 0x%x\nUART_FBRD: 0x%x\n", UARTREG(base, UART_IBRD), UARTREG(base, UART_FBRD)); + uint32_t uart_freq = get_uart_base_freq(); + dprintf(INFO, "uart input clock is %d\n", uart_freq); + uint32_t divisor = calculate_baud_divisor(baud); + + dprintf(INFO, "want a uart divisor of 0x%x / 64\n", divisor); + return 0; +} diff --git a/project/rpi3-vpu-test.mk b/project/rpi4-vpu-test.mk similarity index 88% rename from project/rpi3-vpu-test.mk rename to project/rpi4-vpu-test.mk index 065b739836..06bae65486 100644 --- a/project/rpi3-vpu-test.mk +++ b/project/rpi4-vpu-test.mk @@ -1,6 +1,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) -TARGET := rpi3-vpu +TARGET := rpi4-vpu ARCH := vc4 MODULES += \ diff --git a/target/rpi3-vpu/rules.mk b/target/rpi4-vpu/rules.mk similarity index 100% rename from target/rpi3-vpu/rules.mk rename to target/rpi4-vpu/rules.mk From b87e9629328109121f49dd3370968c073533c612 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 14 Jan 2020 17:33:01 -0400 Subject: [PATCH 003/100] [platform][vc4] fix time resolution, start genet driver, fix rpi2-test build --- arch/vc4/timer.c | 4 +- platform/bcm28xx/genet.c | 27 ++++++ platform/bcm28xx/include/platform/bcm28xx.h | 29 ++++++ .../include/platform/bcm28xx/pll_read.h | 18 ++-- platform/bcm28xx/pll_read.c | 91 +++++++++++++++---- platform/bcm28xx/rules.mk | 32 ++++--- platform/bcm28xx/uart.c | 1 - 7 files changed, 159 insertions(+), 43 deletions(-) create mode 100644 platform/bcm28xx/genet.c diff --git a/arch/vc4/timer.c b/arch/vc4/timer.c index 572f090832..0cfea8f641 100644 --- a/arch/vc4/timer.c +++ b/arch/vc4/timer.c @@ -10,11 +10,11 @@ static enum handler_return timer0_irq(void *arg); lk_bigtime_t current_time_hires(void) { //TODO, deal with rollover - return ( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO); + return (( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO)) / 1000; } lk_time_t current_time(void) { - return *REG32(ST_CLO); + return current_time_hires(); } static platform_timer_callback timer_cb = 0;; diff --git a/platform/bcm28xx/genet.c b/platform/bcm28xx/genet.c new file mode 100644 index 0000000000..a49ab780a4 --- /dev/null +++ b/platform/bcm28xx/genet.c @@ -0,0 +1,27 @@ +// based on drivers/net/ethernet/broadcom/genet/bcmgenet.c from linux +// for PHY control, look at the cmd_bits variable in drivers/net/ethernet/broadcom/genet/bcmmii.c + +#include +#include +#include +#include +#include + +static int cmd_genet_dump(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dump_genet", "print genet information", &cmd_genet_dump) +STATIC_COMMAND_END(genet); + +#define SYS_REV_CTRL (GENET_BASE + 0x0) + +static int cmd_genet_dump(int argc, const cmd_args *argv) { + uint32_t reg = *REG32(SYS_REV_CTRL); + uint8_t major = (reg >> 24 & 0x0f); + if (major == 6) major = 5; + else if (major == 5) major = 4; + else if (major == 0) major = 1; + + dprintf(INFO, "found GENET controller version %d\n", major); + return 0; +} diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index f5a3a60826..1ec3a1dfc4 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -41,6 +41,7 @@ #define ARM_BASE (BCM_PERIPH_BASE_VIRT + 0xB000) #define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) #define CM_BASE (BCM_PERIPH_BASE_VIRT + 0x101000) +#define A2W_BASE (BCM_PERIPH_BASE_VIRT + 0x102000) #define PCM_CLOCK_BASE (BCM_PERIPH_BASE_VIRT + 0x101098) #define RNG_BASE (BCM_PERIPH_BASE_VIRT + 0x104000) #define GPIO_BASE (BCM_PERIPH_BASE_VIRT + 0x200000) @@ -55,6 +56,7 @@ #define SMI_BASE (BCM_PERIPH_BASE_VIRT + 0x600000) #define BSC1_BASE (BCM_PERIPH_BASE_VIRT + 0x804000) #define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) +#define GENET_BASE (0x7d580000) // TODO, this is before the normal BCM_PERIPH_BASE_VIRT bank #define MCORE_BASE (BCM_PERIPH_BASE_VIRT + 0x0000) #define ST_CS (ST_BASE + 0x0) @@ -62,6 +64,8 @@ #define ST_CHI (ST_BASE + 0x8) #define ST_C0 (ST_BASE + 0xc) +#define CM_VPUCTL (CM_BASE + 0x008) +#define CM_VPUDIV (CM_BASE + 0x00c) #define CM_UARTCTL (CM_BASE + 0xf0) #define CM_UARTDIV (CM_BASE + 0xf4) @@ -70,12 +74,14 @@ #define IC0_SRC0 (IC0_BASE + 0x8) #define IC0_SRC1 (IC0_BASE + 0xc) #define IC0_VADDR (IC0_BASE + 0x30) +#define IC0_WAKEUP (IC0_BASE + 0x34) #define IC1_C (IC1_BASE + 0x0) #define IC1_S (IC1_BASE + 0x4) #define IC1_SRC0 (IC1_BASE + 0x8) #define IC1_SRC1 (IC1_BASE + 0xc) #define IC1_VADDR (IC1_BASE + 0x30) +#define IC1_WAKEUP (IC1_BASE + 0x34) #define PM_PASSWORD 0x5a000000 #define PM_RSTC (PM_BASE + 0x1c) @@ -83,6 +89,29 @@ #define PM_WDOG (PM_BASE + 0x24) #define PM_WDOG_MASK 0x00000fff +#define A2W_PASSWORD 0x5a000000 +#define A2W_PLLA_CTRL (A2W_BASE + 0x100) +#define A2W_PLLC_CTRL (A2W_BASE + 0x120) +#define A2W_PLLC_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLC_CTRL_NDIV_SET 0x000003ff +#define A2W_PLLC_CTRL_PDIV_LSB 12 +#define A2W_PLLD_CTRL (A2W_BASE + 0x140) +#define A2W_PLLH_CTRL (A2W_BASE + 0x160) +#define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) +#define A2W_PLLA_FRAC (A2W_BASE + 0x200) +#define A2W_PLLC_FRAC (A2W_BASE + 0x220) +#define A2W_PLLD_FRAC (A2W_BASE + 0x240) +#define A2W_PLLH_FRAC (A2W_BASE + 0x260) +#define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) +#define A2W_PLLC_CORE1 (A2W_BASE + 0x420) +#define A2W_PLLC_CORE0 (A2W_BASE + 0x620) +#define A2W_PLLC_CORE0_DIV_SET 0x000000ff +#define A2W_PLLA_FRAC_MASK 0x000fffff +#define A2W_PLLB_FRAC_MASK 0x000fffff +#define A2W_PLLC_FRAC_MASK 0x000fffff +#define A2W_PLLD_FRAC_MASK 0x000fffff +#define A2W_PLLH_FRAC_MASK 0x000fffff + #define ARMCTRL_BASE (ARM_BASE + 0x000) #define ARMCTRL_INTC_BASE (ARM_BASE + 0x200) #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h index f7f95c9dc0..3b28cd7fd8 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -3,15 +3,15 @@ #ifdef __cplusplus extern "C" { #endif -uint32_t clk_get_input_freq(volatile uint32_t *ctlreg); -uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg); -uint32_t get_vpu_per_freq(); -uint32_t get_uart_base_freq(); -uint32_t plla(); -uint32_t pllb(); -uint32_t pllc(); -uint32_t plld(); -uint32_t pllh(); +uint32_t clk_get_input_freq(uint32_t ctlreg); +uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg); +uint32_t get_vpu_per_freq(void); +uint32_t get_uart_base_freq(void); +uint32_t plla(void); +uint32_t pllb(void); +uint32_t pllc(void); +uint32_t plld(void); +uint32_t pllh(void); extern uint32_t xtal_freq; #ifdef __cplusplus } diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 795a107ba6..156b009cf3 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -1,21 +1,31 @@ -#include #include #include +#include +#include +#include +#include uint32_t xtal_freq; -uint32_t get_vpu_per_freq() { - return clk_get_freq(&CM_VPUDIV, &CM_VPUCTL); +static int cmd_pll_dump(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dump_pll_state", "print all pll state", &cmd_pll_dump) +STATIC_COMMAND_END(pll); + +uint32_t get_vpu_per_freq(void) { + return clk_get_freq(CM_VPUDIV, CM_VPUCTL); } uint32_t get_uart_base_freq() { - return clk_get_freq(&CM_UARTDIV, &CM_UARTCTL); + return clk_get_freq(CM_UARTDIV, CM_UARTCTL); } uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { - uint32_t ndiv = A2W_PLLC_CTRL & A2W_PLLC_CTRL_NDIV_SET; - uint32_t pdiv = (A2W_PLLC_CTRL & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; - uint64_t mult1 = (ndiv << 20) | frac; + // FIXME, ignores the addr passed in + uint32_t ndiv = *REG32(ctrl) & A2W_PLLC_CTRL_NDIV_SET; + uint32_t pdiv = (*REG32(ctrl) & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; + uint64_t mult1 = (ndiv << 20) | *REG32(frac); mult1 *= pdiv; // TODO, the optional /2 phase uint32_t freq = (xtal_freq * mult1) >> 20; @@ -23,44 +33,44 @@ uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { } uint32_t plla() { - return compute_pll_freq(A2W_PLLA_CTRL, A2W_PLLA_FRAC & A2W_PLLA_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLA_CTRL), *REG32(A2W_PLLA_FRAC) & A2W_PLLA_FRAC_MASK); } uint32_t pllb() { - return compute_pll_freq(A2W_PLLB_CTRL, A2W_PLLB_FRAC & A2W_PLLB_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLB_CTRL), *REG32(A2W_PLLB_FRAC) & A2W_PLLB_FRAC_MASK); } uint32_t pllc() { //uint32_t ana1 = A2W_PLLC_ANA1; - uint32_t ctrl = A2W_PLLC_CTRL; - uint32_t frac = A2W_PLLC_FRAC & A2W_PLLC_FRAC_MASK; + uint32_t ctrl = *REG32(A2W_PLLC_CTRL); + uint32_t frac = *REG32(A2W_PLLC_FRAC) & A2W_PLLC_FRAC_MASK; return compute_pll_freq(ctrl, frac); } uint32_t plld() { - return compute_pll_freq(A2W_PLLD_CTRL, A2W_PLLD_FRAC & A2W_PLLD_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLD_CTRL), *REG32(A2W_PLLD_FRAC) & A2W_PLLD_FRAC_MASK); } uint32_t pllh() { - return compute_pll_freq(A2W_PLLH_CTRL, A2W_PLLH_FRAC & A2W_PLLH_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLH_CTRL), *REG32(A2W_PLLH_FRAC) & A2W_PLLH_FRAC_MASK); } -uint32_t pllc_core0() { - uint32_t ctrl = A2W_PLLC_CORE0; +uint32_t pllc_core0(void) { + uint32_t ctrl = *REG32(A2W_PLLC_CORE0); uint32_t div = ctrl & A2W_PLLC_CORE0_DIV_SET; uint32_t pllc_freq = pllc(); return pllc_freq / div; } -uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg) { - uint32_t div = *divreg; +uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg) { + uint32_t div = *REG32(divreg); if (div == 0) return 0; uint64_t input_freq = clk_get_input_freq(ctlreg); - return ((input_freq << 12) / *divreg); + return ((input_freq << 12) / div); } -uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) { - uint32_t ctl = *ctlreg; +uint32_t clk_get_input_freq(uint32_t ctlreg) { + uint32_t ctl = *REG32(ctlreg); switch (ctl & 0xf) { case 0: // GND clock source return 0; @@ -85,3 +95,44 @@ uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) { return 0; } } + +static uint32_t dump_pll_state(const char *prefix, uint32_t ctrl, uint32_t frac) { + uint32_t ctrl_val = *REG32(ctrl); + uint32_t frac_value = *REG32(frac); + dprintf(INFO, "A2W_%s_CTRL: 0x%x\n", prefix, ctrl_val); + dprintf(INFO, "A2W_%s_FRAC: 0x%x\n", prefix, frac_value); + uint32_t freq = compute_pll_freq(ctrl, frac); + dprintf(INFO, "%s freq: %u\n", prefix, freq); + return freq; +} + +static void dump_plldiv_state(const char *prefix, uint32_t ctrl, uint32_t input) { + uint32_t ctrl_val = *REG32(ctrl); + dprintf(INFO, "\tA2W_%s: 0x%x\n", prefix, ctrl_val); + uint8_t div = ctrl_val & 0xff; + if (div == 0) return; + uint32_t freq = input / div; + dprintf(INFO, "\t%s freq: %u\n", prefix, freq); +} + +static void dump_plldiv2_state(const char *prefix, uint32_t ctrl, uint32_t div) { + uint32_t ctrl_val = *REG32(ctrl); + uint32_t div_val = *REG32(div); + dprintf(INFO, "CM_%sCTL: 0x%x\n", prefix, ctrl_val); + dprintf(INFO, "CM_%sDIV: 0x%x\n", prefix, div_val); +} + +static int cmd_pll_dump(int argc, const cmd_args *argv) { + dump_pll_state("PLLA", A2W_PLLA_CTRL, A2W_PLLA_FRAC); + dump_pll_state("PLLB", A2W_PLLB_CTRL, A2W_PLLB_FRAC); + uint32_t pllc_freq = dump_pll_state("PLLC", A2W_PLLC_CTRL, A2W_PLLC_FRAC); + if (pllc_freq > 0) { + dump_plldiv_state("PLLC_CORE0", A2W_PLLC_CORE0, pllc_freq); + dump_plldiv_state("PLLC_CORE1", A2W_PLLC_CORE1, pllc_freq); + } + dump_pll_state("PLLD", A2W_PLLD_CTRL, A2W_PLLD_FRAC); + dump_pll_state("PLLH", A2W_PLLH_CTRL, A2W_PLLH_FRAC); + + dump_plldiv2_state("VPU", CM_VPUCTL, CM_VPUDIV); + return 0; +} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 8fd2216f58..5948f5de4d 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -5,12 +5,28 @@ MODULE := $(LOCAL_DIR) WITH_SMP := 1 #LK_HEAP_IMPLEMENTATION ?= dlmalloc -ifeq ($(ARCJ),arm) -MODULE_DEPS := \ +# 1st pass to set arch +ifeq ($(TARGET),rpi2) + ARCH := arm + ARM_CPU := cortex-a7 + GLOBAL_DEFINES += CRYSTAL=19200000 +else ifeq ($(TARGET),rpi3) + ARCH := arm64 + ARM_CPU := cortex-a53 + GLOBAL_DEFINES += CRYSTAL=19200000 +else ifeq ($(TARGET),rpi4-vpu) + ARCH ?= vc4 + GLOBAL_DEFINES += CRYSTAL=54000000 +endif + + +ifeq ($(ARCH),arm) +MODULE_DEPS += \ dev/timer/arm_generic \ lib/cbuf -MODULE_SRCS += +MODULE_SRCS += \ $(LOCAL_DIR)/mailbox.c \ + $(LOCAL_DIR)/intc.c \ endif @@ -24,7 +40,7 @@ endif MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/platform.c \ - #$(LOCAL_DIR)/intc.c \ + $(LOCAL_DIR)/pll_read.c \ MEMBASE := 0x00000000 @@ -36,8 +52,6 @@ LINKER_SCRIPT += \ $(BUILDDIR)/system-onesegment.ld ifeq ($(TARGET),rpi2) -ARCH := arm -ARM_CPU := cortex-a7 # put our kernel at 0x80000000 KERNEL_BASE = 0x80000000 KERNEL_LOAD_OFFSET := 0x00008000 @@ -50,8 +64,6 @@ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c else ifeq ($(TARGET),rpi3) -ARCH := arm64 -ARM_CPU := cortex-a53 KERNEL_LOAD_OFFSET := 0x00080000 MEMSIZE ?= 0x40000000 # 1GB @@ -70,18 +82,16 @@ MODULE_DEPS += \ app/tests \ lib/fdt else ifeq ($(TARGET),rpi4-vpu) -ARCH ?= vc4 MEMSIZE ?= 0x1400000 # 20MB MEMBASE ?= 0 GLOBAL_DEFINES += \ BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ MEMSIZE=$(MEMSIZE) \ MEMBASE=$(MEMBASE) \ - CRYSTAL=54000000 \ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ - $(LOCAL_DIR)/pll_read.c \ + $(LOCAL_DIR)/genet.c \ endif diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 9ff209fb36..6013a39d87 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -102,7 +102,6 @@ void uart_init(void) { // assumes interrupts are contiguous register_int_handler(INTERRUPT_VC_UART + i, &uart_irq, (void *)i); uint32_t divisor = calculate_baud_divisor(115200); - dprintf(INFO, "changing divisor to %d\n", divisor); uart_flush(i); From 6e53a654c6ac01f691001aa2b3efb90d8ca955db Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 20 Jan 2020 00:04:51 -0400 Subject: [PATCH 004/100] various changes, moving repo to another pc --- arch/vc4/arch.c | 34 +++++++++++++++++++++++++++ arch/vc4/include/arch/vc4_pcb.h | 12 +++++----- arch/vc4/intc.c | 41 ++++++++++++++++++++++++++++----- arch/vc4/interrupt.S | 1 - arch/vc4/start.S | 11 +++++++++ arch/vc4/thread.c | 14 ++++++++++- arch/vc4/thread_asm.S | 8 +++++-- kernel/thread.c | 4 ++++ platform/bcm28xx/platform.c | 4 ++++ todo.txt | 4 ++++ 10 files changed, 117 insertions(+), 16 deletions(-) create mode 100644 todo.txt diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index ea74a60122..15a81f740a 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -1,11 +1,32 @@ #include #include #include +#include +#include +#include + +static int cmd_boot_other_core(int argc, const cmd_args *argv); + +static char core2_stack[4096]; +uint32_t core2_stack_top = 0; + +STATIC_COMMAND_START +STATIC_COMMAND("boot_other_core", "boot the 2nd vpu core", &cmd_boot_other_core) +STATIC_COMMAND_END(arch); void arch_early_init(void) { + uint32_t r28, sp, sr; + __asm__ volatile ("mov %0, r28" : "=r"(r28)); + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + __asm__ volatile ("mov %0, sr" : "=r"(sr)); + dprintf(INFO, "arch_early_init\nr28: 0x%x\nsp: 0x%x\nsr: 0x%x\n", r28, sp, sr); } void arch_init(void) { + uint32_t r28, sp; + __asm__ volatile ("mov %0, r28" : "=r"(r28)); + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + dprintf(INFO, "arch_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); } void arch_idle(void) { @@ -16,3 +37,16 @@ void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3 PANIC_UNIMPLEMENTED; } +void core2_start(); + +static int cmd_boot_other_core(int argc, const cmd_args *argv) { + core2_stack_top = (core2_stack + sizeof(core2_stack)) - 4; + *REG32(A2W_PLLC_CORE1) = A2W_PASSWORD | 6; // 3ghz/6 == 500mhz + *REG32(IC1_WAKEUP) = &core2_start; + return 0; +} + +void core2_entry() { + dprintf(INFO, "core2 says hello\n"); + for (;;); +} diff --git a/arch/vc4/include/arch/vc4_pcb.h b/arch/vc4/include/arch/vc4_pcb.h index a334adc331..c4a1231e90 100644 --- a/arch/vc4/include/arch/vc4_pcb.h +++ b/arch/vc4/include/arch/vc4_pcb.h @@ -20,7 +20,7 @@ Process control block. #pragma once typedef struct { - uint32_t r23; + uint32_t r23; // 0 uint32_t r22; uint32_t r21; uint32_t r20; @@ -37,18 +37,18 @@ typedef struct { uint32_t r9; uint32_t r8; uint32_t r7; - uint32_t r6; + uint32_t r6; // +68 uint32_t r5; uint32_t r4; uint32_t r3; uint32_t r2; uint32_t r1; - uint32_t r0; + uint32_t r0; // +92 - uint32_t lr; + uint32_t lr; // +96 - uint32_t sr; - uint32_t pc; + uint32_t sr; // +100 + uint32_t pc; // +104 } vc4_saved_state_t; diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index 57eb95d6f8..f3c21c95c0 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -21,6 +21,8 @@ struct handlerArgPair irq_handlers[64]; // if the highest bit on this addr is set, the cpu will switch into supervisor mode irqType __attribute__ ((aligned (512))) vectorTable[144]; // might only need to be 128 entries +uint8_t irq_stack0[4096]; + static const char* g_ExceptionNames[] = { "Zero", "Misaligned", @@ -50,6 +52,10 @@ void set_interrupt(int intno, bool enable, int core) { void intc_init(void) { + uint32_t r28, sp; + __asm__ volatile ("mov %0, r28" : "=r"(r28)); + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + dprintf(INFO, "intc_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); // TODO for (int i=0; i<64; i++) { irq_handlers[0].h = 0; // is this needed? maybe .bss already took care of it? @@ -77,18 +83,23 @@ void intc_init(void) { } // swi opcode handler for (int i=32; i<=63; i++) { - vectorTable[i] = fleh_irq; + vectorTable[i] = (uint32_t)fleh_irq | 1; } // external interrupts for (int i=64; i<=127; i++) { - vectorTable[i] = fleh_irq; + vectorTable[i] = (uint32_t)fleh_irq | 1; } + uint32_t irq_sp = (irq_stack0 + sizeof(irq_stack0)) - 4; + dprintf(INFO, "r28 = 0x%x\nirq_stack0: %p\nsizeof(irq_stack0): %d\n", irq_sp, irq_stack0, sizeof(irq_stack0)); + + __asm__ volatile ("mov r28, 0xdeadbeef": :"r"(irq_sp)); + *REG32(IC0_VADDR) = vectorTable; *REG32(IC1_VADDR) = vectorTable; if (*REG32(IC0_VADDR) != vectorTable) { - printf("vector table now at 0x%08lx 0x%08lx\n", *REG32(IC0_VADDR), (uint32_t)vectorTable); + printf("vector table now at 0x%08x 0x%08x\n", *REG32(IC0_VADDR), (uint32_t)vectorTable); panic("vector table failed to install"); } } @@ -182,11 +193,25 @@ void sleh_fatal(vc4_saved_state_t* pcb, uint32_t n) { while(true) __asm__ volatile ("nop"); } +// upon entry to this function(before its prologue runs), sp and r0 point to a `struct vc4_saved_state_t` +// r0 (which lands in pcb) contains a copy of that sp from before the prologue +// some common values and offsets: +// r0 + 0: r23 +// ... +// r0 + 92: r0 +// r0 + 96: lr +// r0 + 100: sr +// r0 + 104: pc void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { uint32_t status = *REG32(IC0_S); uint32_t source = status & 0xFF; - uint32_t cs; - int ret; + enum handler_return ret = INT_NO_RESCHEDULE; + + uint32_t r28, sp, sr; + __asm__ volatile ("mov %0, r28" : "=r"(r28)); + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + __asm__ volatile ("mov %0, sr" : "=r"(sr)); + //dprintf(INFO, "sleh_irq\nr28: 0x%x\nsp: 0x%x\nsr: 0x%x\n", r28, sp, sr); //dprintf(INFO, "VPU Received interrupt from source %d\n", source); @@ -195,7 +220,11 @@ void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { case 121: // uart assert(irq_handlers[source - 64].h); ret = irq_handlers[source - 64].h(irq_handlers[source - 64].arg); - if (ret == INT_RESCHEDULE) thread_preempt(); + if (ret == INT_RESCHEDULE) { + //dprintf(INFO, "pre-emptying\n"); + thread_preempt(); + //dprintf(INFO, "done preempt\n"); + } break; case INTERRUPT_ARM: // fired when the arm cpu writes to the arm->vpu mailbox diff --git a/arch/vc4/interrupt.S b/arch/vc4/interrupt.S index 33ce5f4a55..8ea7a68395 100644 --- a/arch/vc4/interrupt.S +++ b/arch/vc4/interrupt.S @@ -48,7 +48,6 @@ fleh_irq: SaveRegsAll mov r0, sp mov r1, r29 - di bl sleh_irq return_from_exception: ldm r16-r23, (sp++) diff --git a/arch/vc4/start.S b/arch/vc4/start.S index 949ee73a70..4cbcf11ff5 100644 --- a/arch/vc4/start.S +++ b/arch/vc4/start.S @@ -9,3 +9,14 @@ _start: bl lk_main loop: b loop + +.global core2_start +core2_start: + mov r0, core2_stack_top + ld sp, (r0) + mov r0, 0 + mov r1, 'A' + bl uart_putc + bl core2_entry +loop2: + b loop2 diff --git a/arch/vc4/thread.c b/arch/vc4/thread.c index c11beac702..3c018a8ffa 100644 --- a/arch/vc4/thread.c +++ b/arch/vc4/thread.c @@ -4,6 +4,11 @@ void vc4_context_switch(uint32_t *oldsp, uint32_t newsp); void arch_context_switch(thread_t *oldthread, thread_t *newthread) { + uint32_t r28, sp; + __asm__ volatile ("mov %0, r28" : "=r"(r28)); + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + //dprintf(INFO, "arch_context_switch\nr28: 0x%x\nsp: 0x%x\n", r28, sp); + //dprintf(INFO, "switching (%s) -> %p(%s)\n", oldthread->name, newthread->arch.sp, newthread->name); vc4_context_switch(&oldthread->arch.sp, newthread->arch.sp); } @@ -17,6 +22,10 @@ static inline void push(thread_t *t, uint32_t val) { static void initial_thread_func(void) __NO_RETURN; static void initial_thread_func(void) { thread_t *ct = get_current_thread(); + uint32_t own_sp; + + __asm__ volatile ("mov %0, sp": "=r"(own_sp)); + dprintf(INFO, "thread %p(%s) starting with sp near 0x%x\n", ct, ct->name, own_sp); int ret = ct->entry(ct->arg); @@ -24,9 +33,12 @@ static void initial_thread_func(void) { } void arch_thread_initialize(thread_t *t) { + printf("thread %p(%s) has a stack of %p+0x%x\n", t, t->name, t->stack, t->stack_size); t->arch.sp = (t->stack + t->stack_size) - 4; push(t, &initial_thread_func); - push(t, 0); // the initial frame-pointer + for (int i=6; i<=23; i++) { + push(t, 0); // r${i} + } } void arch_dump_thread(thread_t *t) { diff --git a/arch/vc4/thread_asm.S b/arch/vc4/thread_asm.S index b61bbcb95a..0a2e652a62 100644 --- a/arch/vc4/thread_asm.S +++ b/arch/vc4/thread_asm.S @@ -3,7 +3,11 @@ // r0 is address to save the sp to // r1 is the new sp to load vc4_context_switch: - stm r6,lr,(--sp) + stm lr, (--sp) + stm r6-r15, (--sp) + stm r16-r23, (--sp) st sp, (r0) mov sp, r1 - ldm r6,pc,(sp++) + ldm r16-r23, (sp++) + ldm r6-r15, (sp++) + ldm pc,(sp++) diff --git a/kernel/thread.c b/kernel/thread.c index 5588ecd742..166b96ae39 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -461,6 +461,8 @@ void thread_resched(void) { thread_t *current_thread = get_current_thread(); uint cpu = arch_curr_cpu_num(); + //dprintf(INFO, "thread_resched called on thread %p(%s) on core %d\n", current_thread, current_thread->name, cpu); + DEBUG_ASSERT(arch_ints_disabled()); DEBUG_ASSERT(spin_lock_held(&thread_lock)); DEBUG_ASSERT(current_thread->state != THREAD_RUNNING); @@ -601,6 +603,8 @@ void thread_yield(void) { THREAD_STATS_INC(yields); + dprintf(INFO, "thread_yield\n"); + /* we are yielding the cpu, so stick ourselves into the tail of the run queue and reschedule */ current_thread->state = THREAD_READY; current_thread->remaining_quantum = 0; diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 33590d71b4..faf28e99b6 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -208,6 +208,10 @@ void platform_early_init(void) { } void platform_init(void) { + uint32_t r28, sp; + __asm__ volatile ("mov %0, r28" : "=r"(r28)); + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + dprintf(INFO, "platform_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); uart_init(); #if BCM2837 init_framebuffer(); diff --git a/todo.txt b/todo.txt new file mode 100644 index 0000000000..02c2b98531 --- /dev/null +++ b/todo.txt @@ -0,0 +1,4 @@ +use TARGET_HAS_DEBUG_LED on rpi + +fix \r\n issues +an IRQ between \r and \n can lead to text getting overwritten From 63983b1e1ae1658a6c7acb24880ead470eb0d55c Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 24 Jan 2020 14:38:33 -0400 Subject: [PATCH 005/100] fix CI and enable hw led --- platform/bcm28xx/platform.c | 16 ++++++++++++++++ platform/bcm28xx/rules.mk | 6 ++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index faf28e99b6..6cda7172ac 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef BCM2XXX_VPU #include @@ -208,10 +209,13 @@ void platform_early_init(void) { } void platform_init(void) { +#ifdef VPU uint32_t r28, sp; __asm__ volatile ("mov %0, r28" : "=r"(r28)); __asm__ volatile ("mov %0, sp" : "=r"(sp)); dprintf(INFO, "platform_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); +#endif + gpio_config(42, 1); uart_init(); #if BCM2837 init_framebuffer(); @@ -248,3 +252,15 @@ void platform_halt(platform_halt_action suggested_action, arch_disable_ints(); for (;;); } + +void target_set_debug_led(unsigned int led, bool on) { + switch (led) { + case 0: +#ifdef RPI4 + gpio_set(42, on); +#endif + break; + default: + break; + } +} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 5948f5de4d..8ce982ed0c 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -82,12 +82,14 @@ MODULE_DEPS += \ app/tests \ lib/fdt else ifeq ($(TARGET),rpi4-vpu) -MEMSIZE ?= 0x1400000 # 20MB -MEMBASE ?= 0 +MEMSIZE ?= 0x01400000 # 20MB +MEMBASE := 0xc0000000 GLOBAL_DEFINES += \ BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ MEMSIZE=$(MEMSIZE) \ MEMBASE=$(MEMBASE) \ + RPI4=1 \ + VPU=1 \ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ From 7688dad5eab1d74264b72dee094596b51083b913 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 29 Jan 2020 02:32:04 -0400 Subject: [PATCH 006/100] most of the code needed to make an rpi3 bootcode.bin --- default.nix | 29 +++++ platform/bcm28xx/bootcode.ld | 47 +++++++++ platform/bcm28xx/gpio.c | 111 ++++++++++++++++++++ platform/bcm28xx/include/platform/bcm28xx.h | 9 +- platform/bcm28xx/platform.c | 6 +- platform/bcm28xx/rules.mk | 26 ++++- platform/bcm28xx/uart.c | 24 ++++- project/rpi3-bootcode.mk | 16 +++ target/rpi3-vpu/rules.mk | 11 ++ target/rpi4-vpu/rules.mk | 2 + 10 files changed, 273 insertions(+), 8 deletions(-) create mode 100644 default.nix create mode 100644 platform/bcm28xx/bootcode.ld create mode 100644 project/rpi3-bootcode.mk create mode 100644 target/rpi3-vpu/rules.mk diff --git a/default.nix b/default.nix new file mode 100644 index 0000000000..b70434bad4 --- /dev/null +++ b/default.nix @@ -0,0 +1,29 @@ +let + sources = import ./nix/sources.nix; + pkgs = import (builtins.fetchTarball https://github.com/input-output-hk/nixpkgs/archive/0ee0489d42e.tar.gz) {}; + lib = pkgs.lib; + overlay = self: super: { + littlekernel = self.stdenv.mkDerivation { + name = "littlekernel"; + src = lib.cleanSource ./.; + nativeBuildInputs = [ x86_64.uart-manager ]; + }; + uart-manager = self.stdenv.mkDerivation { + name = "uart-manager"; + src = sources.rpi-open-firmware + "/uart-manager"; + }; + }; + vc4 = pkgs.pkgsCross.vc4.extend overlay; + x86_64 = pkgs.extend overlay; + arm7 = pkgs.pkgsCross.armv7l-hf-multiplatform.extend overlay; +in { + arm7 = { + inherit (arm7) littlekernel; + }; + vc4 = { + inherit (vc4) littlekernel; + }; + x86_64 = { + inherit (x86_64) uart-manager; + }; +} diff --git a/platform/bcm28xx/bootcode.ld b/platform/bcm28xx/bootcode.ld new file mode 100644 index 0000000000..bbe44309a6 --- /dev/null +++ b/platform/bcm28xx/bootcode.ld @@ -0,0 +1,47 @@ +MEMORY { + ram (rwx) : ORIGIN = 0x80000000, LENGTH = 128K +} +GROUP(-lgcc) +SECTIONS { + .text : { + . = 0x0; + . = 0x200; + _text = .; + *(.text.start) + *(.text) + *(.text.*) + *(.gnu.warning) + _etext = .; + } + + .rodata : { + *(.rodata) + *(.rodata.*) + _erodata = .; + } + + .init_array : { + . = ALIGN(16); + PROVIDE(__ctor_list = .); + KEEP(*(.init_array)) + KEEP(*(.init_array.*)) + KEEP(*(.ctors)) + KEEP(*(.ctors.*)) + __ctor_end = .; + } + + .data : { + *(.data) + _edata = .; + } + + .bss : { + . = ALIGN(4); + __bss_start = .; + *(.bss) + *(COMMON) + . = ALIGN(4); + _end = .; + } + _fstack = ORIGIN(ram) + LENGTH(ram) - 4; +} diff --git a/platform/bcm28xx/gpio.c b/platform/bcm28xx/gpio.c index bc736f9610..21745c164a 100644 --- a/platform/bcm28xx/gpio.c +++ b/platform/bcm28xx/gpio.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #define NUM_PINS 54 #define BITS_PER_REG 32 @@ -16,6 +19,16 @@ #define PINS_PER_REG (BITS_PER_REG / BITS_PER_PIN) #define GPIOREG(base, nr) (REG32(base) + (nr / BITS_PER_REG)) +static int cmd_gpio_mode(int argc, const cmd_args *argv); +static int cmd_gpio_write(int argc, const cmd_args *argv); +static int cmd_gpio_dump_state(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("gpio_mode", "set the gpio alt mode", &cmd_gpio_mode) +STATIC_COMMAND("gpio_write", "set gpio output", &cmd_gpio_write) +STATIC_COMMAND("gpio_dump_state", "dump current gpio state", &cmd_gpio_dump_state) +STATIC_COMMAND_END(gpio); + int gpio_config(unsigned nr, unsigned flags) { unsigned mask = 0x7; if (nr >= NUM_PINS || flags & ~mask) @@ -28,6 +41,17 @@ int gpio_config(unsigned nr, unsigned flags) { return 0; } +int gpio_get_config(unsigned nr) { + unsigned mask = 0x7; + if (nr >= NUM_PINS) + return -EINVAL; + unsigned register_number = nr / PINS_PER_REG; + unsigned offset = (nr % PINS_PER_REG) * BITS_PER_PIN; + unsigned shifted_mask = mask << offset; + volatile uint32_t *reg = REG32(GPIO_GPFSEL0) + register_number; + return (*reg & shifted_mask) >> offset; +} + void gpio_set(unsigned nr, unsigned on) { unsigned offset = nr % BITS_PER_REG; *GPIOREG(on ? GPIO_GPSET0 : GPIO_GPCLR0, nr) = 1 << offset; @@ -37,3 +61,90 @@ int gpio_get(unsigned nr) { unsigned offset = nr % BITS_PER_REG; return (*GPIOREG(GPIO_GPLEV0, nr) & (1 << offset)) >> offset; } + +#ifdef RPI4 +int gpio_get_pull(unsigned nr) { + unsigned offset = (nr % 16) * 2; + volatile uint32_t *pull_cfg = REG32(GPIO_2711_PULL); + return (pull_cfg[nr / 16] >> offset) & 0x3; +} +#endif + +static int cmd_gpio_mode(int argc, const cmd_args *argv) { + if (argc != 3) { + printf("usage: gpio_mode 42 (in|out|alt0|alt1|alt2|alt3|alt4|alt5)\n"); + return -1; + } + int mode = 0; + if (strcmp(argv[2].str, "in") == 0) { + mode = 0; + } else if (strcmp(argv[2].str, "out") == 0) { + mode = 1; + } else if (strcmp(argv[2].str, "alt0") == 0) { + mode = 4; + } else if (strcmp(argv[2].str, "alt1") == 0) { + mode = 5; + } else if (strcmp(argv[2].str, "alt2") == 0) { + mode = 6; + } else if (strcmp(argv[2].str, "alt3") == 0) { + mode = 7; + } else if (strcmp(argv[2].str, "alt4") == 0) { + mode = 3; + } else if (strcmp(argv[2].str, "alt5") == 0) { + mode = 2; + } else { + printf("unknown mode %s\n", argv[2].str); + return -1; + } + gpio_config(argv[1].u, mode); + printf("done\n"); + return 0; +} + +static int cmd_gpio_write(int argc, const cmd_args *argv) { + if (argc != 3) { + printf("usage: gpio_write 42 1\n"); + return -1; + } + gpio_set(argv[1].u, argv[2].u); + printf("done\n"); + return 0; +} + + +const char *mode_names[] = { + "IN", + "OUT", + "ALT5", + "ALT4", + "ALT0", + "ALT1", + "ALT2", + "ALT3", + "" +}; + +const char *levels[] = { "LOW", "HIGH" }; + +const char *pull_names[] = { "--", "^^", "\\/", "invalid", "" }; + +static int cmd_gpio_dump_state(int argc, const cmd_args *argv) { + for (int i=0; i<32; i++) { + int lflags, rflags = 8; + lflags = gpio_get_config(i); + int l_level = gpio_get(i); + int r_level = gpio_get(i+32); + if ((i+32) < NUM_PINS) rflags = gpio_get_config(i+32); + +#if RPI4 + int l_pull = gpio_get_pull(i); + int r_pull = gpio_get_pull(i+32); +#else + int l_pull = 4, r_pull = 4; +#endif + + printf("GPIO%02d %4s %s %4s | %4s %s %4s GPIO%02d\n", i, mode_names[lflags], pull_names[l_pull], levels[l_level], + levels[r_level], pull_names[r_pull], mode_names[rflags], i+32); + } + return 0; +} diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 1ec3a1dfc4..31b8343df9 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -21,7 +21,7 @@ #elif BCM2837 #define BCM_PERIPH_BASE_VIRT (0xffffffffc0000000ULL) #define MEMORY_APERTURE_SIZE (1024 * 1024 * 1024) -#elif BCM2XXX_VPU +#elif VPU #define BCM_PERIPH_BASE_VIRT (0x7e000000U) #else #error Unknown BCM28XX Variant @@ -84,6 +84,10 @@ #define IC1_WAKEUP (IC1_BASE + 0x34) #define PM_PASSWORD 0x5a000000 +#define CM_PASSWORD 0x5a000000 +#define CM_SRC_OSC 1 +#define CM_UARTCTL_FRAC_SET 0x00000200 +#define CM_UARTCTL_ENAB_SET 0x00000010 #define PM_RSTC (PM_BASE + 0x1c) #define PM_RSTC_WRCFG_CLR 0xffffffcf // mask to keep everything but the watchdog config #define PM_WDOG (PM_BASE + 0x24) @@ -267,3 +271,6 @@ #define GPIO_GPPUD (GPIO_BASE + 0x94) #define GPIO_GPPUDCLK0 (GPIO_BASE + 0x98) #define GPIO_GPPUDCLK1 (GPIO_BASE + 0x9C) +#define GPIO_2711_PULL (GPIO_BASE + 0xe4) +// 2 bits per reg, 16 pins per reg, 4 regs total +// 0=none, 1=up, 2=down diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 6cda7172ac..a4743be987 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -17,7 +17,7 @@ #include #include -#ifndef BCM2XXX_VPU +#ifndef VPU #include #endif @@ -95,7 +95,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { #define DEBUG_UART 1 -#elif BCM2XXX_VPU +#elif VPU #define DEBUG_UART 0 #else #error Unknown BCM28XX Variant @@ -170,7 +170,7 @@ void platform_early_init(void) { #elif BCM2836 arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 1000000); -#elif BCM2XXX_VPU +#elif VPU #else #error Unknown BCM28XX Variant #endif diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 8ce982ed0c..f9088467e6 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -14,6 +14,8 @@ else ifeq ($(TARGET),rpi3) ARCH := arm64 ARM_CPU := cortex-a53 GLOBAL_DEFINES += CRYSTAL=19200000 +else ifeq ($(TARGET),rpi3-vpu) + GLOBAL_DEFINES += CRYSTAL=19200000 else ifeq ($(TARGET),rpi4-vpu) ARCH ?= vc4 GLOBAL_DEFINES += CRYSTAL=54000000 @@ -28,6 +30,14 @@ MODULE_SRCS += \ $(LOCAL_DIR)/mailbox.c \ $(LOCAL_DIR)/intc.c \ +LINKER_SCRIPT += \ + $(BUILDDIR)/system-onesegment.ld +else # VPU + ifeq ($(BOOTCODE),1) + LINKER_SCRIPT += $(LOCAL_DIR)/bootcode.ld + else + LINKER_SCRIPT += $(LOCAL_DIR)/start.ld + endif endif @@ -48,9 +58,6 @@ MEMBASE := 0x00000000 GLOBAL_DEFINES += \ ARM_ARCH_WAIT_FOR_SECONDARIES=1 -LINKER_SCRIPT += \ - $(BUILDDIR)/system-onesegment.ld - ifeq ($(TARGET),rpi2) # put our kernel at 0x80000000 KERNEL_BASE = 0x80000000 @@ -81,6 +88,19 @@ MODULE_DEPS += \ app/shell \ app/tests \ lib/fdt +else ifeq ($(TARGET),rpi3-vpu) + MEMSIZE := 0x20000 # 128kb + MEMBASE := 0x80000000 # in the 8 alias + GLOBAL_DEFINES += \ + MEMSIZE=$(MEMSIZE) \ + MEMBASE=$(MEMBASE) \ + RPI3=1 \ + VPU=1 \ + SMP_MAX_CPUS=1 \ + + MODULE_SRCS += \ + $(LOCAL_DIR)/uart.c \ + else ifeq ($(TARGET),rpi4-vpu) MEMSIZE ?= 0x01400000 # 20MB MEMBASE := 0xc0000000 diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 6013a39d87..686e65fbc1 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -16,6 +16,7 @@ #include #include #include +#include /* TODO: extract this into a generic PL011 driver */ @@ -92,6 +93,8 @@ static void uart_flush(int port) { } void uart_init(void) { + gpio_config(14, 4); + gpio_config(15, 4); for (size_t i = 0; i < NUM_UART; i++) { uintptr_t base = uart_to_ptr(i); @@ -131,10 +134,29 @@ void uart_init(void) { } } +int uart_putc(int port, char c); + void uart_init_early(void) { + if (*REG32(CM_UARTDIV) == 0) { + // CM_UARTDIV can range from 0 to 1023 with a fractional resolution of 1/4096th + // on the rpi1-3, this sets the freq to 19.2 / (0x3900 / 0x1000) == ~5.3mhz + // TODO, have a better default for other models? + *REG32(CM_UARTDIV) = CM_PASSWORD | 0x3900; + *REG32(CM_UARTCTL) = CM_PASSWORD | CM_SRC_OSC | CM_UARTCTL_FRAC_SET | CM_UARTCTL_ENAB_SET; + } + for (size_t i = 0; i < NUM_UART; i++) { - UARTREG(uart_to_ptr(i), UART_CR) = (1<<8)|(1<<0); // tx_enable, uarten + uintptr_t base = uart_to_ptr(i); + uint32_t divisor = calculate_baud_divisor(115200); + UARTREG(base, UART_CR) = 0; // shutdown the entire uart + UARTREG(base, UART_LCRH) = 0x70; // fifo enable, 8bit mode + if (divisor > 0) { + UARTREG(base, UART_IBRD) = (divisor >> 6) & 0xffff; + UARTREG(base, UART_FBRD) = divisor & 0x3f; + } + UARTREG(base, UART_CR) = (1<<8)|(1<<0); // tx_enable, uarten } + gpio_config(14, 4); } int uart_putc(int port, char c) { diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk new file mode 100644 index 0000000000..cd8de74173 --- /dev/null +++ b/project/rpi3-bootcode.mk @@ -0,0 +1,16 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi3-vpu +ARCH := vc4 + +MODULES += \ + app/shell \ + app/stringtests \ + lib/cksum \ + lib/debugcommands \ + #app/tests \ + +GLOBAL_DEFINES += BOOTCODE=1 + + +BOOTCODE := 1 diff --git a/target/rpi3-vpu/rules.mk b/target/rpi3-vpu/rules.mk new file mode 100644 index 0000000000..4faae1f4a9 --- /dev/null +++ b/target/rpi3-vpu/rules.mk @@ -0,0 +1,11 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +GLOBAL_INCLUDES += \ + $(LOCAL_DIR)/include + +GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 VPU=1 MODEL=3 + +PLATFORM := bcm28xx + +#include make/module.mk + diff --git a/target/rpi4-vpu/rules.mk b/target/rpi4-vpu/rules.mk index fe10d50d72..d4586a2f10 100644 --- a/target/rpi4-vpu/rules.mk +++ b/target/rpi4-vpu/rules.mk @@ -3,6 +3,8 @@ LOCAL_DIR := $(GET_LOCAL_DIR) GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include +GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 VPU=1 MODEL=4 + PLATFORM := bcm28xx #include make/module.mk From 34a6c863d9ea8200c18873c4f61725b6fbbe2e03 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 29 Jan 2020 02:34:24 -0400 Subject: [PATCH 007/100] various changes done on an rpi4 --- arch/vc4/arch.c | 28 +++++++++++++++++++++-- arch/vc4/include/arch/arch_ops.h | 9 ++++---- arch/vc4/include/arch/arch_thread.h | 1 + arch/vc4/include/arch/spinlock.h | 5 ++++- arch/vc4/include/arch/vc4_traps.h | 29 ++++++++++++------------ arch/vc4/intc.c | 17 +++++++++----- arch/vc4/interrupt.S | 22 ++++++++++++++++++ arch/vc4/start.S | 10 ++++++++- arch/vc4/thread.c | 18 ++++++++++----- arch/vc4/thread_asm.S | 35 +++++++++++++++++++++++++++-- arch/vc4/timer.c | 2 +- 11 files changed, 140 insertions(+), 36 deletions(-) diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index 15a81f740a..60b8a6d012 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -4,14 +4,17 @@ #include #include #include +#include static int cmd_boot_other_core(int argc, const cmd_args *argv); +static int cmd_testit(int argc, const cmd_args *argv); static char core2_stack[4096]; uint32_t core2_stack_top = 0; STATIC_COMMAND_START STATIC_COMMAND("boot_other_core", "boot the 2nd vpu core", &cmd_boot_other_core) +STATIC_COMMAND("testit", "do some asm tests", &cmd_testit) STATIC_COMMAND_END(arch); void arch_early_init(void) { @@ -19,7 +22,7 @@ void arch_early_init(void) { __asm__ volatile ("mov %0, r28" : "=r"(r28)); __asm__ volatile ("mov %0, sp" : "=r"(sp)); __asm__ volatile ("mov %0, sr" : "=r"(sr)); - dprintf(INFO, "arch_early_init\nr28: 0x%x\nsp: 0x%x\nsr: 0x%x\n", r28, sp, sr); + //dprintf(INFO, "arch_early_init\nr28: 0x%x\nsp: 0x%x\nsr: 0x%x\n", r28, sp, sr); } void arch_init(void) { @@ -37,7 +40,7 @@ void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3 PANIC_UNIMPLEMENTED; } -void core2_start(); +void core2_start(void); static int cmd_boot_other_core(int argc, const cmd_args *argv) { core2_stack_top = (core2_stack + sizeof(core2_stack)) - 4; @@ -50,3 +53,24 @@ void core2_entry() { dprintf(INFO, "core2 says hello\n"); for (;;); } + +void testit(uint32_t *, uint32_t, uint32_t, uint32_t, uint32_t); + +static int cmd_testit(int argc, const cmd_args *argv) { + uint32_t target[4]; + testit(target, 0x11, 0x22, 0x33, 0x44); + printf("%x %x %x %x\n", target[0], target[1], target[2], target[3]); + return 0; +} + +int vc4_atomic_add(volatile int *ptr, int val) { + // TODO + //spin_lock_saved_state_t state; + //arch_interrupt_save(&state, SPIN_LOCK_FLAG_INTERRUPTS); + THREAD_LOCK(state); + int old = *ptr; + *ptr += val; + //arch_interrupt_restore(&state, SPIN_LOCK_FLAG_INTERRUPTS); + THREAD_UNLOCK(state); + return old; +} diff --git a/arch/vc4/include/arch/arch_ops.h b/arch/vc4/include/arch/arch_ops.h index 01c9ebb4ce..9333f5d960 100644 --- a/arch/vc4/include/arch/arch_ops.h +++ b/arch/vc4/include/arch/arch_ops.h @@ -18,10 +18,10 @@ static inline bool arch_ints_disabled(void) { return !(state & 0x40000000); } +int vc4_atomic_add(volatile int *ptr, int val); + static inline int atomic_add(volatile int *ptr, int val) { - // TODO - *ptr += val; - return *ptr; + return vc4_atomic_add(ptr, val); } static inline int atomic_or(volatile int *ptr, int val) { @@ -36,7 +36,7 @@ static inline int atomic_swap(volatile int *ptr, int val) { return __atomic_exchange_n(ptr, val, __ATOMIC_RELAXED); } static inline struct thread *get_current_thread(void) { - uint32_t thread_reg; + struct thread *thread_reg; __asm__ volatile("mov %0, r29" : "=r"(thread_reg)); return thread_reg; } @@ -51,5 +51,6 @@ static inline uint arch_curr_cpu_num(void) { uint32_t cpuid; __asm__("version %0" : "=r"(cpuid)); // TODO, one of the bits in the cpuid is the cpu#, dont remember which one + // a pdf for an older ARC model says the cpuid contains a 16bit vendor id, 8bit coreid, and 8bit cpuid return 0; } diff --git a/arch/vc4/include/arch/arch_thread.h b/arch/vc4/include/arch/arch_thread.h index 5d790ce073..5e288a88d3 100644 --- a/arch/vc4/include/arch/arch_thread.h +++ b/arch/vc4/include/arch/arch_thread.h @@ -4,4 +4,5 @@ struct arch_thread { uint32_t sp; + uint32_t sr; }; diff --git a/arch/vc4/include/arch/spinlock.h b/arch/vc4/include/arch/spinlock.h index 7cc8c923cb..2e252d8524 100644 --- a/arch/vc4/include/arch/spinlock.h +++ b/arch/vc4/include/arch/spinlock.h @@ -55,14 +55,17 @@ arch_interrupt_save(spin_lock_saved_state_t *statep, spin_lock_save_flags_t flag if (!arch_ints_disabled()) { state |= SPIN_LOCK_STATE_RESTORE_IRQ; arch_disable_ints(); + //printf("irq was on, disabled\n"); } *statep = state; } static inline void arch_interrupt_restore(spin_lock_saved_state_t old_state, spin_lock_save_flags_t flags) { - if (old_state & SPIN_LOCK_STATE_RESTORE_IRQ) + if (old_state & SPIN_LOCK_STATE_RESTORE_IRQ) { + //printf("restoring ints\n"); arch_enable_ints(); + } } diff --git a/arch/vc4/include/arch/vc4_traps.h b/arch/vc4/include/arch/vc4_traps.h index 1d30d36c2b..954fc28bb9 100644 --- a/arch/vc4/include/arch/vc4_traps.h +++ b/arch/vc4/include/arch/vc4_traps.h @@ -4,18 +4,19 @@ void fleh_zero(void); void fleh_misaligned(void); -void fleh_dividebyzero(); -void fleh_undefinedinstruction(); -void fleh_forbiddeninstruction(); -void fleh_illegalmemory(); -void fleh_buserror(); -void fleh_floatingpoint(); -void fleh_isp(); -void fleh_dummy(); -void fleh_icache(); -void fleh_veccore(); -void fleh_badl2alias(); -void fleh_breakpoint(); -void fleh_unknown(); -void fleh_irq(); +void fleh_dividebyzero(void); +void fleh_undefinedinstruction(void); +void fleh_forbiddeninstruction(void); +void fleh_illegalmemory(void); +void fleh_buserror(void); +void fleh_floatingpoint(void); +void fleh_isp(void); +void fleh_dummy(void); +void fleh_icache(void); +void fleh_veccore(void); +void fleh_badl2alias(void); +void fleh_breakpoint(void); +void fleh_unknown(void); +void fleh_irq(void); +void fleh_swi(void); void print_vpu_state(vc4_saved_state_t* pcb); diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index f3c21c95c0..cff3b4d174 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -19,7 +19,7 @@ struct handlerArgPair irq_handlers[64]; // it will then push pc and sr onto the new stack // it will then read an entry from this vector table, and set the PC to that entry // if the highest bit on this addr is set, the cpu will switch into supervisor mode -irqType __attribute__ ((aligned (512))) vectorTable[144]; // might only need to be 128 entries +irqType __attribute__ ((aligned (512))) vectorTable[128]; // might only need to be 128 entries uint8_t irq_stack0[4096]; @@ -83,7 +83,7 @@ void intc_init(void) { } // swi opcode handler for (int i=32; i<=63; i++) { - vectorTable[i] = (uint32_t)fleh_irq | 1; + vectorTable[i] = (uint32_t)fleh_swi; } // external interrupts for (int i=64; i<=127; i++) { @@ -93,12 +93,12 @@ void intc_init(void) { uint32_t irq_sp = (irq_stack0 + sizeof(irq_stack0)) - 4; dprintf(INFO, "r28 = 0x%x\nirq_stack0: %p\nsizeof(irq_stack0): %d\n", irq_sp, irq_stack0, sizeof(irq_stack0)); - __asm__ volatile ("mov r28, 0xdeadbeef": :"r"(irq_sp)); + __asm__ volatile ("mov r28, %0": :"r"(irq_sp)); - *REG32(IC0_VADDR) = vectorTable; - *REG32(IC1_VADDR) = vectorTable; + *REG32(IC0_VADDR) = (uint32_t)vectorTable; + *REG32(IC1_VADDR) = (uint32_t)vectorTable; - if (*REG32(IC0_VADDR) != vectorTable) { + if (((void *)*REG32(IC0_VADDR)) != vectorTable) { printf("vector table now at 0x%08x 0x%08x\n", *REG32(IC0_VADDR), (uint32_t)vectorTable); panic("vector table failed to install"); } @@ -234,3 +234,8 @@ void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { panic("unknown interrupt source!"); } } + +void sleh_swi(vc4_saved_state_t* pcb) { + dprintf(INFO, "got SWI\n"); + print_vpu_state(pcb); +} diff --git a/arch/vc4/interrupt.S b/arch/vc4/interrupt.S index 8ea7a68395..2343721341 100644 --- a/arch/vc4/interrupt.S +++ b/arch/vc4/interrupt.S @@ -1,6 +1,14 @@ .macro SaveRegsLower stm lr, (--sp) + nop + nop + nop + nop stm r0-r5, (--sp) + nop + nop + nop + nop .endm .macro SaveRegsUpper @@ -55,3 +63,17 @@ return_from_exception: ldm r0-r5, (sp++) ld lr, (sp++) rti + +.global fleh_swi +fleh_swi: + stm lr, (--sp) + stm r0-r5, (--sp) + stm r6-r15, (--sp) + stm r16-r23, (--sp) + mov r0, sp + bl sleh_swi + ldm r16-r23, (sp++) + ldm r6-r15, (sp++) + ldm r0-r5, (sp++) + ld lr, (sp++) + rti diff --git a/arch/vc4/start.S b/arch/vc4/start.S index 4cbcf11ff5..44d40a3cba 100644 --- a/arch/vc4/start.S +++ b/arch/vc4/start.S @@ -1,6 +1,6 @@ #include -.text +.section .text.start FUNCTION(_start) .global _start _start: @@ -20,3 +20,11 @@ core2_start: bl core2_entry loop2: b loop2 + +.global testit +testit: + st r1, (r0) + st r2, (r0+4) + st r3, (r0+8) + st r4, (r0+12) + rts diff --git a/arch/vc4/thread.c b/arch/vc4/thread.c index 3c018a8ffa..90bc75b685 100644 --- a/arch/vc4/thread.c +++ b/arch/vc4/thread.c @@ -9,7 +9,14 @@ void arch_context_switch(thread_t *oldthread, thread_t *newthread) { __asm__ volatile ("mov %0, sp" : "=r"(sp)); //dprintf(INFO, "arch_context_switch\nr28: 0x%x\nsp: 0x%x\n", r28, sp); //dprintf(INFO, "switching (%s) -> %p(%s)\n", oldthread->name, newthread->arch.sp, newthread->name); - vc4_context_switch(&oldthread->arch.sp, newthread->arch.sp); + //dprintf(INFO, "old: %p %s\nSP: 0x%x\nSR: 0x%x\n", oldthread, oldthread->name, oldthread->arch.sp, oldthread->arch.sr); + //dprintf(INFO, "new: %p %s\nSP: 0x%x\nSR: 0x%x\n", newthread, newthread->name, newthread->arch.sp, newthread->arch.sr); + vc4_context_switch(&oldthread->arch, &newthread->arch); + //dprintf(INFO, "switched\n\n"); +} + +void boop() { + dprintf(INFO, "boop\n"); } static inline void push(thread_t *t, uint32_t val) { @@ -22,10 +29,10 @@ static inline void push(thread_t *t, uint32_t val) { static void initial_thread_func(void) __NO_RETURN; static void initial_thread_func(void) { thread_t *ct = get_current_thread(); - uint32_t own_sp; + uint32_t own_sp, sr; __asm__ volatile ("mov %0, sp": "=r"(own_sp)); - dprintf(INFO, "thread %p(%s) starting with sp near 0x%x\n", ct, ct->name, own_sp); + //dprintf(INFO, "thread %p(%s) starting with sp near 0x%x\n", ct, ct->name, own_sp); int ret = ct->entry(ct->arg); @@ -33,9 +40,10 @@ static void initial_thread_func(void) { } void arch_thread_initialize(thread_t *t) { - printf("thread %p(%s) has a stack of %p+0x%x\n", t, t->name, t->stack, t->stack_size); + //printf("thread %p(%s) has a stack of %p+0x%x\n", t, t->name, t->stack, t->stack_size); t->arch.sp = (t->stack + t->stack_size) - 4; - push(t, &initial_thread_func); + __asm__ volatile ("mov %0, sr": "=r"(t->arch.sr)); + push(t, &initial_thread_func); // lr for (int i=6; i<=23; i++) { push(t, 0); // r${i} } diff --git a/arch/vc4/thread_asm.S b/arch/vc4/thread_asm.S index 0a2e652a62..fdcbe39732 100644 --- a/arch/vc4/thread_asm.S +++ b/arch/vc4/thread_asm.S @@ -1,8 +1,36 @@ .text .global vc4_context_switch -// r0 is address to save the sp to -// r1 is the new sp to load +// r0 is address of the old arch_thread +// r1 is address of the new arch_thread vc4_context_switch: + // save all state that is caller saved + stm lr, (--sp) + stm r6-r15, (--sp) + stm r16-r23, (--sp) + + + // swap stacks + st sp, (r0) + mov r2, sr + st r2, (r0+4) + + ld sp, (r1) + mov r3, sp + //swi 0 + + // restore all state from stack + ldm r16-r23, (sp++) + ldm r6-r15, (sp++) + ldm r0, (sp++) + mov lr, r0 + + lea r0, vc4_context_switch_finish + st r0, (--sp) + ld r1, (r1+4) // load saved SR + st r1, (--sp) + rti + +oldvc4_context_switch: stm lr, (--sp) stm r6-r15, (--sp) stm r16-r23, (--sp) @@ -11,3 +39,6 @@ vc4_context_switch: ldm r16-r23, (sp++) ldm r6-r15, (sp++) ldm pc,(sp++) + +vc4_context_switch_finish: + rts diff --git a/arch/vc4/timer.c b/arch/vc4/timer.c index 0cfea8f641..d5e74e1a73 100644 --- a/arch/vc4/timer.c +++ b/arch/vc4/timer.c @@ -10,7 +10,7 @@ static enum handler_return timer0_irq(void *arg); lk_bigtime_t current_time_hires(void) { //TODO, deal with rollover - return (( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO)) / 1000; + return ( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO); } lk_time_t current_time(void) { From 8057162b840860270fe77eeb0cdbddeab9d9a051 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 29 Jan 2020 02:49:06 -0400 Subject: [PATCH 008/100] add the basis for nix CI --- arch/vc4/intc.c | 2 +- default.nix | 4 +- lk.nix | 16 ++++ nix/sources.json | 38 ++++++++ nix/sources.nix | 93 ++++++++++++++++++++ {arch/vc4 => platform/bcm28xx}/start.ld | 0 project/{rpi4-vpu-test.mk => rpi4-start4.mk} | 0 release.nix | 7 ++ 8 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 lk.nix create mode 100644 nix/sources.json create mode 100644 nix/sources.nix rename {arch/vc4 => platform/bcm28xx}/start.ld (100%) rename project/{rpi4-vpu-test.mk => rpi4-start4.mk} (100%) create mode 100644 release.nix diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index cff3b4d174..35942329d2 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -19,7 +19,7 @@ struct handlerArgPair irq_handlers[64]; // it will then push pc and sr onto the new stack // it will then read an entry from this vector table, and set the PC to that entry // if the highest bit on this addr is set, the cpu will switch into supervisor mode -irqType __attribute__ ((aligned (512))) vectorTable[128]; // might only need to be 128 entries +irqType __attribute__ ((aligned (512))) vectorTable[128]; uint8_t irq_stack0[4096]; diff --git a/default.nix b/default.nix index b70434bad4..c5af5236c7 100644 --- a/default.nix +++ b/default.nix @@ -21,7 +21,9 @@ in { inherit (arm7) littlekernel; }; vc4 = { - inherit (vc4) littlekernel; + shell = vc4.littlekernel; + rpi3.bootcode = vc4.callPackage ./lk.nix { project = "rpi3-bootcode"; }; + rpi4.start4 = vc4.callPackage ./lk.nix { project = "rpi4-start4"; }; }; x86_64 = { inherit (x86_64) uart-manager; diff --git a/lk.nix b/lk.nix new file mode 100644 index 0000000000..42b64b7df2 --- /dev/null +++ b/lk.nix @@ -0,0 +1,16 @@ +{ stdenv, project }: + +stdenv.mkDerivation { + name = "littlekernel-${project}"; + src = stdenv.lib.cleanSource ./.; + makeFlags = [ "PROJECT=${project}" ]; + hardeningDisable = [ "format" ]; + installPhase = '' + mkdir -p $out/nix-support + cp -r build-${project}/{config.h,lk.*} $out + cat < $out/nix-support/hydra-metrics + lk.bin $(stat --printf=%s $out/lk.bin) bytes + lk.elf $(stat --printf=%s $out/lk.elf) bytes + EOF + ''; +} diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 0000000000..1687272a5d --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,38 @@ +{ + "niv": { + "branch": "master", + "description": "Easy dependency management for Nix projects", + "homepage": "https://github.com/nmattia/niv", + "owner": "nmattia", + "repo": "niv", + "rev": "61b61d1e5f8096fe65fb825bec23f33e861c51d0", + "sha256": "1dwfkd942wisccpsv0kf47abl0n17d9v4zasv4bm8lvy1dhv82ia", + "type": "tarball", + "url": "https://github.com/nmattia/niv/archive/61b61d1e5f8096fe65fb825bec23f33e861c51d0.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs": { + "branch": "nixos-19.03", + "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", + "homepage": "https://github.com/NixOS/nixpkgs", + "owner": "NixOS", + "repo": "nixpkgs-channels", + "rev": "c8db7a8a16ee9d54103cade6e766509e1d1c8d7b", + "sha256": "1b3h4mwpi10blzpvgsc0191k4shaw3nw0qd2p82hygbr8vv4g9dv", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs-channels/archive/c8db7a8a16ee9d54103cade6e766509e1d1c8d7b.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "rpi-open-firmware": { + "branch": "master", + "description": "Open source VPU side bootloader for Raspberry Pi.", + "homepage": null, + "owner": "cleverca22", + "repo": "rpi-open-firmware", + "rev": "b2d019aca2cc788a8f656ea28ca91c0df9ff7291", + "sha256": "1kiimh0gbjai6nbd1i06kbk1ymvhyr4xqd0196048hq8a9wf8kdb", + "type": "tarball", + "url": "https://github.com/cleverca22/rpi-open-firmware/archive/b2d019aca2cc788a8f656ea28ca91c0df9ff7291.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/nix/sources.nix b/nix/sources.nix new file mode 100644 index 0000000000..d4ac577f25 --- /dev/null +++ b/nix/sources.nix @@ -0,0 +1,93 @@ +# This file has been generated by Niv. + +# A record, from name to path, of the third-party packages +with rec +{ + pkgs = + if hasNixpkgsPath + then + if hasThisAsNixpkgsPath + then import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {} + else import {} + else + import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {}; + + sources_nixpkgs = + if builtins.hasAttr "nixpkgs" sources + then sources.nixpkgs + else abort + '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = + { url, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball { inherit url; } + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = + { url, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl { inherit url; } + else + fetchurl attrs; + + # A wrapper around pkgs.fetchzip that has inspectable arguments, + # annoyingly this means we have to specify them + fetchzip = { url, sha256 }@attrs: pkgs.fetchzip attrs; + + # A wrapper around pkgs.fetchurl that has inspectable arguments, + # annoyingly this means we have to specify them + fetchurl = { url, sha256 }@attrs: pkgs.fetchurl attrs; + + hasNixpkgsPath = (builtins.tryEval ).success; + hasThisAsNixpkgsPath = + (builtins.tryEval ).success && == ./.; + + sources = builtins.fromJSON (builtins.readFile ./sources.json); + + mapAttrs = builtins.mapAttrs or + (f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))); + + # borrowed from nixpkgs + functionArgs = f: f.__functionArgs or (builtins.functionArgs f); + callFunctionWith = autoArgs: f: args: + let auto = builtins.intersectAttrs (functionArgs f) autoArgs; + in f (auto // args); + + getFetcher = spec: + let fetcherName = + if builtins.hasAttr "type" spec + then builtins.getAttr "type" spec + else "builtin-tarball"; + in builtins.getAttr fetcherName { + "tarball" = fetchzip; + "builtin-tarball" = builtins_fetchTarball; + "file" = fetchurl; + "builtin-url" = builtins_fetchurl; + }; +}; +# NOTE: spec must _not_ have an "outPath" attribute +mapAttrs (_: spec: + if builtins.hasAttr "outPath" spec + then abort + "The values in sources.json should not have an 'outPath' attribute" + else + if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec + then + spec // + { outPath = callFunctionWith spec (getFetcher spec) { }; } + else spec + ) sources diff --git a/arch/vc4/start.ld b/platform/bcm28xx/start.ld similarity index 100% rename from arch/vc4/start.ld rename to platform/bcm28xx/start.ld diff --git a/project/rpi4-vpu-test.mk b/project/rpi4-start4.mk similarity index 100% rename from project/rpi4-vpu-test.mk rename to project/rpi4-start4.mk diff --git a/release.nix b/release.nix new file mode 100644 index 0000000000..dd170fb250 --- /dev/null +++ b/release.nix @@ -0,0 +1,7 @@ +let + self = import ./.; +in { + vc4 = { + inherit (self.vc4) rpi3 rpi4; + }; +} From e6aa53e3fb85194c1791f5fdedd19a8a40ca58f9 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 29 Jan 2020 12:57:56 -0400 Subject: [PATCH 009/100] add the rpi ddr2 controller --- app/rpi-vpu-bootload/bootloader.c | 0 app/rpi-vpu-bootload/rules.mk | 9 + default.nix | 9 +- platform/bcm28xx/rpi-ddr2/LICENSE | 241 +++++++++++ platform/bcm28xx/rpi-ddr2/ddr2.h | 117 ++++++ platform/bcm28xx/rpi-ddr2/rules.mk | 7 + platform/bcm28xx/rpi-ddr2/sdram.c | 623 +++++++++++++++++++++++++++++ platform/bcm28xx/rpi-ddr2/sdram.h | 13 + project/rpi3-bootcode.mk | 3 +- 9 files changed, 1019 insertions(+), 3 deletions(-) create mode 100644 app/rpi-vpu-bootload/bootloader.c create mode 100644 app/rpi-vpu-bootload/rules.mk create mode 100644 platform/bcm28xx/rpi-ddr2/LICENSE create mode 100644 platform/bcm28xx/rpi-ddr2/ddr2.h create mode 100644 platform/bcm28xx/rpi-ddr2/rules.mk create mode 100644 platform/bcm28xx/rpi-ddr2/sdram.c create mode 100644 platform/bcm28xx/rpi-ddr2/sdram.h diff --git a/app/rpi-vpu-bootload/bootloader.c b/app/rpi-vpu-bootload/bootloader.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/rpi-vpu-bootload/rules.mk b/app/rpi-vpu-bootload/rules.mk new file mode 100644 index 0000000000..8f0014cf71 --- /dev/null +++ b/app/rpi-vpu-bootload/rules.mk @@ -0,0 +1,9 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += platform/bcm28xx/rpi-ddr2 + +MODULE_SRCS += $(LOCAL_DIR)/bootloader.c + +include make/module.mk diff --git a/default.nix b/default.nix index c5af5236c7..e5dc20f704 100644 --- a/default.nix +++ b/default.nix @@ -16,7 +16,7 @@ let vc4 = pkgs.pkgsCross.vc4.extend overlay; x86_64 = pkgs.extend overlay; arm7 = pkgs.pkgsCross.armv7l-hf-multiplatform.extend overlay; -in { +in lib.fix (self: { arm7 = { inherit (arm7) littlekernel; }; @@ -28,4 +28,9 @@ in { x86_64 = { inherit (x86_64) uart-manager; }; -} + testcycle = pkgs.writeShellScript "testcycle" '' + set -e + scp ${self.vc4.rpi3.bootcode}/lk.bin root@router.localnet:/tftproot/open-firmware/bootcode.bin + exec ${x86_64.uart-manager}/bin/uart-manager + ''; +}) diff --git a/platform/bcm28xx/rpi-ddr2/LICENSE b/platform/bcm28xx/rpi-ddr2/LICENSE new file mode 100644 index 0000000000..8f854e4e14 --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/LICENSE @@ -0,0 +1,241 @@ +Code copyrighted to Broadom Corporation is released under BSD 3-Clause License +============================================================================== + +Copyright (c) 2009-2014, Broadcom Corporation All rights reserved. Redistribution and use in source +and binary forms, with or without modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. +3. Neither the name of the copyright holder nor the +names of its contributors may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +All other code released under GPLv2+ with an exception as specified in https://github.com/christinaa/rpi-open-firmware/issues/29. +==================================== + +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, +MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing +it is not allowed. Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By +contrast, the GNU General Public License is intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. This General Public License +applies to most of the Free Software Foundation's software and to any other program whose authors +commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser +General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses +are designed to make sure that you have the freedom to distribute copies of free software (and +charge for this service if you wish), that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free programs; and that you know you can +do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or +to ask you to surrender the rights. These restrictions translate to certain responsibilities for you +if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give +the recipients all the rights that you have. You must make sure that they, too, receive or can get +the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license +which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that +there is no warranty for this free software. If the software is modified by someone else and passed +on, we want its recipients to know that what they have is not the original, so that any problems +introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger +that redistributors of a free program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright +holder saying it may be distributed under the terms of this General Public License. The "Program", +below, refers to any such program or work, and a "work based on the Program" means either the +Program or any derivative work under copyright law: that is to say, a work containing the Program or +a portion of it, either verbatim or with modifications and/or translated into another language. +(Hereinafter, translation is included without limitation in the term "modification".) Each licensee +is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they +are outside its scope. The act of running the Program is not restricted, and the output from the +Program is covered only if its contents constitute a work based on the Program (independent of +having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in +any medium, provided that you conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the Program a copy of this +License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer +warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based +on the Program, and copy and distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices stating that you changed the files +and the date of any change. b) You must cause any work that you distribute or publish, that in whole +or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at +no charge to all third parties under the terms of this License. c) If the modified program normally +reads commands interactively when run, you must cause it, when started running for such interactive +use in the most ordinary way, to print or display an announcement including an appropriate copyright +notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that +users may redistribute the program under these conditions, and telling the user how to view a copy +of this License. (Exception: if the Program itself is interactive but does not normally print such +an announcement, your work based on the Program is not required to print an announcement.) These +requirements apply to the modified work as a whole. If identifiable sections of that work are not +derived from the Program, and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those sections when you distribute +them as separate works. But when you distribute the same sections as part of a whole which is a work +based on the Program, the distribution of the whole must be on the terms of this License, whose +permissions for other licensees extend to the entire whole, and thus to each and every part +regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written +entirely by you; rather, the intent is to exercise the right to control the distribution of +derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a +work based on the Program) on a volume of a storage or distribution medium does not bring the other +work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code +or executable form under the terms of Sections 1 and 2 above provided that you also do one of the +following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be +distributed under the terms of Sections 1 and 2 above on a medium customarily used for software +interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any +third party, for a charge no more than your cost of physically performing source distribution, a +complete machine-readable copy of the corresponding source code, to be distributed under the terms +of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it +with the information you received as to the offer to distribute corresponding source code. (This +alternative is allowed only for noncommercial distribution and only if you received the program in +object code or executable form with such an offer, in accord with Subsection b above.) The source +code for a work means the preferred form of the work for making modifications to it. For an +executable work, complete source code means all the source code for all modules it contains, plus +any associated interface definition files, plus the scripts used to control compilation and +installation of the executable. However, as a special exception, the source code distributed need +not include anything that is normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on which the executable runs, +unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated +place, then offering equivalent access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not compelled to copy the source +along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided +under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. However, parties who have +received copies, or rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else +grants you permission to modify or distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by modifying or distributing the +Program (or any work based on the Program), you indicate your acceptance of this License to do so, +and all its terms and conditions for copying, distributing or modifying the Program or works based +on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient +automatically receives a license from the original licensor to copy, distribute or modify the +Program subject to these terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance +by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other +reason (not limited to patent issues), conditions are imposed on you (whether by court order, +agreement or otherwise) that contradict the conditions of this License, they do not excuse you from +the conditions of this License. If you cannot distribute so as to satisfy simultaneously your +obligations under this License and any other pertinent obligations, then as a consequence you may +not distribute the Program at all. For example, if a patent license would not permit royalty-free +redistribution of the Program by all those who receive copies directly or indirectly through you, +then the only way you could satisfy both it and this License would be to refrain entirely from +distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, +the balance of the section is intended to apply and the section as a whole is intended to apply in +other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right +claims or to contest validity of any such claims; this section has the sole purpose of protecting +the integrity of the free software distribution system, which is implemented by public license +practices. Many people have made generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that system; it is up to the +author/donor to decide if he or she is willing to distribute software through any other system and a +licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest +of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by +patents or by copyrighted interfaces, the original copyright holder who places the Program under +this License may add an explicit geographical distribution limitation excluding those countries, so +that distribution is permitted only in or among countries not thus excluded. In such case, this +License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public +License from time to time. Such new versions will be similar in spirit to the present version, but +may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of +this License which applies to it and "any later version", you have the option of following the terms +and conditions either of that version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of this License, you may choose any +version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution +conditions are different, write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing and reuse of software +generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE +EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS +AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR +IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. +SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, +OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO +YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF +THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO +OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS diff --git a/platform/bcm28xx/rpi-ddr2/ddr2.h b/platform/bcm28xx/rpi-ddr2/ddr2.h new file mode 100644 index 0000000000..4856df0e8c --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/ddr2.h @@ -0,0 +1,117 @@ +#pragma once + +// heavily copied from bcm2708_chip/sdc_ctrl.h +// from the rpi-open-firmware repo +// (from the v3d source release??) +// TODO, replace this with the official headers + +#define SD_CS_SDUP_SET 0x00008000 +#define SD_CS_DEL_KEEP_SET 0x00040000 +#define SD_MR_RDATA_SET 0x00ff0000 +#define SD_MR_RDATA_LSB 16 +#define SD_MR_RW_SET 0x10000000 +#define SD_MR_HI_Z_SET 0x20000000 +#define SD_MR_TIMEOUT_SET 0x40000000 +#define SD_MR_DONE_SET 0x80000000 + +#define CM_SDCCTL 0x7e1011a8 +#define CM_SDCCTL_SRC_CLR 0xfffffff0 +#define CM_SDCCTL_ENAB_SET 0x00000010 +#define CM_SDCCTL_BUSY_SET 0x00000080 +#define CM_SDCCTL_CTRL_CLR 0xffff0fff +#define CM_SDCCTL_CTRL_LSB 12 +#define CM_SDCCTL_ACCPT_SET 0x00010000 +#define CM_SDCCTL_UPDATE_SET 0x00020000 +#define CM_SDCCTL_UPDATE_CLR 0xfffdffff +#define CM_SDCDIV 0x7e1011ac +#define CM_SDCDIV_DIV_LSB 12 +#define CM_SDCCTL_CTRL_SET 0x0000f000 + +#define SD_CS 0x7ee00000 +#define SD_CS_RESTRT_SET 0x00000001 +#define SD_CS_EN_SET 0x00000002 +#define SD_CS_DPD_SET 0x00000004 +#define SD_CS_STBY_SET 0x00000008 +#define SD_CS_STATEN_SET 0x00000040 +#define SD_CS_STOP_SET 0x00000080 +#define SD_CS_ASHDN_T_LSB 19 +#define SD_SA 0x7ee00004 +#define SD_SA_POWSAVE_SET 0x00000001 +#define SD_SA_CLKSTOP_SET 0x00000080 +#define SD_SA_PGEHLDE_SET 0x00000100 +#define SD_SA_RFSH_T_LSB 16 +#define SD_SB 0x7ee00008 +#define SD_SB_COLBITS_LSB 0 +#define SD_SB_ROWBITS_LSB 2 +#define SD_SB_BANKLOW_LSB 5 +#define SD_SB_EIGHTBANK_SET 0x00000010 +#define SD_SB_REORDER_SET 0x00000080 +#define SD_SC 0x7ee0000c +#define SD_SC_WL_LSB 0 +#define SD_SC_T_WTR_LSB 4 +#define SD_SC_T_WR_LSB 8 +#define SD_SC_T_RRD_LSB 20 +#define SD_SC_T_RFC_LSB 24 +#define SD_PT2 0x7ee00010 +#define SD_PT2_T_INIT5_LSB 0 +#define SD_PT1 0x7ee00014 +#define SD_PT1_T_INIT1_LSB 0 +#define SD_PT1_T_INIT3_LSB 8 +#define SD_PHYC 0x7ee00060 +#define SD_PHYC_PHYRST_SET 0x00000001 +#define SD_MRT 0x7ee00064 +#define SD_MRT_T_MRW_LSB 0 +#define SD_MR 0x7ee00090 +#define SD_SD 0x7ee00094 +#define SD_SD_T_RCD_LSB 0 +#define SD_SD_T_RPpb_LSB 4 +#define SD_SD_T_RAS_LSB 8 +#define SD_SD_T_XP_LSB 16 +#define SD_SD_T_RC_LSB 20 +#define SD_SD_T_RPab_LSB 28 +#define SD_SE 0x7ee00098 +#define SD_SE_T_XSR_LSB 0 +#define SD_SE_T_RTP_LSB 8 +#define SD_SE_T_FAW_LSB 12 +#define SD_SE_RL_LSB 20 +#define SD_SE_RL_EN_LSB 28 + +#define APHY_CSR_GLBL_ADDR_DLL_RESET 0x7ee06004 +#define APHY_CSR_GLBL_ADR_DLL_LOCK_STAT 0x7ee06020 +#define APHY_CSR_DDR_PLL_GLOBAL_RESET 0x7ee06024 +#define APHY_CSR_DDR_PLL_POST_DIV_RESET 0x7ee06028 +#define APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0 0x7ee0602c +#define APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1 0x7ee06030 +#define APHY_CSR_DDR_PLL_MDIV_VALUE 0x7ee06034 +#define APHY_CSR_DDR_PLL_LOCK_STATUS 0x7ee06048 +#define APHY_CSR_DDR_PLL_PWRDWN 0x7ee06058 +#define APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL 0x7ee06068 +#define APHY_CSR_ADDR_PVT_COMP_CTRL 0x7ee06070 +#define APHY_CSR_ADDR_PVT_COMP_STATUS 0x7ee06078 +#define APHY_CSR_PHY_BIST_CNTRL_SPR 0x7ee06080 + +#define DPHY_CSR_GLBL_DQ_DLL_RESET 0x7ee07004 +#define DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT 0x7ee07018 +#define DPHY_CSR_BOOT_READ_DQS_GATE_CTRL 0x7ee07040 +#define DPHY_CSR_DQ_PHY_MISC_CTRL 0x7ee07048 +#define DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL 0x7ee0704c +#define DPHY_CSR_DQ_PAD_MISC_CTRL 0x7ee07050 +#define DPHY_CSR_DQ_PVT_COMP_CTRL 0x7ee07054 +#define DPHY_CSR_DQ_PVT_COMP_STATUS 0x7ee0705c + +#define A2W_PASSWORD 0x5a000000 + +#define A2W_XOSC_CTRL 0x7e102190 +#define A2W_XOSC_CTRL_DDREN_SET 0x00000010 +#define A2W_XOSC_CTRLR HW_REGISTER_RW( 0x7e102990 ) +#define A2W_SMPS_LDO0 0x7e1020d0 +#define A2W_SMPS_LDO1 0x7e1020d4 + +#define PM_SMPS 0x7e10006c + +// copied from rpi-open-firmware +#define LPDDR2_MR_DEVICE_FEATURE_2 2 +#define LPDDR2_MR_IO_CONFIG 3 +#define LPDDR2_MR_MANUFACTURER_ID 5 +#define LPDDR2_MR_METRICS 8 +#define LPDDR2_MR_CALIBRATION 10 diff --git a/platform/bcm28xx/rpi-ddr2/rules.mk b/platform/bcm28xx/rpi-ddr2/rules.mk new file mode 100644 index 0000000000..b7e707cf31 --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/rules.mk @@ -0,0 +1,7 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += $(LOCAL_DIR)/sdram.c + +include make/module.mk diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c new file mode 100644 index 0000000000..6e5950eacb --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -0,0 +1,623 @@ +/*============================================================================= +Copyright (C) 2016-2017 Authors of rpi-open-firmware +Copyright (C) 2016 Julian Brown +All rights reserved. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +FILE DESCRIPTION +VideoCoreIV SDRAM initialization code. + +=============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "sdram.h" +#include "ddr2.h" + +#define ALWAYS_INLINE __attribute__((always_inline)) inline + +const char* size_to_string[] = { + "1GB", + "512MB", + "256MB", + "128MB", + "2GB", + "4GB", + "UNKNOWN" +}; + +enum RamSize g_RAMSize = kRamSizeUnknown; + +/* + Registers + ========= + + SC: AC Timing (Page 202) + SB: ??? + SD: AC Timing (Page 202) + SE: AC Timing (Page 202) + + PT1: + Minimum Idle time after first CKE assertion + Minimum CKE low time after completion of power ramp + PT2: + DAI Duration + */ + +#define MR_REQUEST_SUCCESS(x) ((SD_MR_TIMEOUT_SET & x) != SD_MR_TIMEOUT_SET) +#define MR_GET_RDATA(x) ((x & SD_MR_RDATA_SET) >> SD_MR_RDATA_LSB) + +#define SIP_DEBUG(x) x +#define SCLKU_DEBUG(x) //SIP_DEBUG(x) + +#define BIST_pvt 0x20 +#define BIST_reset 0x10 + +#define PVT_calibrate_request 0x1 + +#define logf(fmt, ...) print_timestamp(); printf("[SDRAM:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); + +// TODO, move this to a better place +void udelay(uint32_t t) { + uint32_t tv = *REG32(ST_CLO); + for (;;) { + /* nop still takes a cycle i think? */ + __asm__ __volatile__ ("nop" :::); + if ((*REG32(ST_CLO) - tv) > t) return; + } +} + +void print_timestamp() { + uint32_t clock_lo = *REG32(ST_CLO); + + printf("%3ld.%06ld ", clock_lo / 1000000, clock_lo % 1000000); +} + +static const char* lpddr2_manufacturer_name(uint32_t mr) { + switch (mr) { + case 1: + return "Samsung"; + case 2: + return "Qimonda"; + case 3: + return "Elpida"; + case 4: + return "Etron"; + case 5: + return "Nanya"; + case 6: + return "Hynix"; + default: + return "Unknown"; + } +} + +#define MR8_DENSITY_SHIFT 0x2 +#define MR8_DENSITY_MASK (0xF << 0x2) + +static enum RamSize lpddr2_size(uint32_t mr) { + switch (mr) { + case 0x58: + return kRamSize1GB; + case 0x18: + return kRamSize512MB; + case 0x14: + return kRamSize256MB; + case 0x10: + return kRamSize128MB; + default: + return kRamSizeUnknown; + } +} + +/***************************************************************************** + * Guts + *****************************************************************************/ + +ALWAYS_INLINE inline void clkman_update_begin(void) { + *REG32(CM_SDCCTL) |= CM_PASSWORD | CM_SDCCTL_UPDATE_SET; + SCLKU_DEBUG(logf("waiting for ACCPT (%X) ...\n", *REG32(CM_SDCCTL))); + for (;;) if (*REG32(CM_SDCCTL) & CM_SDCCTL_ACCPT_SET) break; + SCLKU_DEBUG(logf("ACCPT received! (%X)\n", *REG32(CM_SDCCTL))); +} + +ALWAYS_INLINE inline void clkman_update_end(void) { + *REG32(CM_SDCCTL) = CM_PASSWORD | (*REG32(CM_SDCCTL) & CM_SDCCTL_UPDATE_CLR); + SCLKU_DEBUG(logf("waiting for ACCPT clear (%X) ...\n", *REG32(CM_SDCCTL))); + for (;;) if ((*REG32(CM_SDCCTL) & CM_SDCCTL_ACCPT_SET) == 0) break; + SCLKU_DEBUG(logf("ACCPT cleared! (%X)\n", *REG32(CM_SDCCTL))); +} + +ALWAYS_INLINE void reset_phy_dll(void) { + SIP_DEBUG(logf("resetting aphy and dphy dlls ...\n")); + + /* politely tell sdc that we'll be messing with address lines */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x30; + + *REG32(DPHY_CSR_GLBL_DQ_DLL_RESET) = 0x1; + *REG32(APHY_CSR_GLBL_ADDR_DLL_RESET) = 0x1; + + /* stall ... */ + *REG32(SD_CS); + *REG32(SD_CS); + *REG32(SD_CS); + *REG32(SD_CS); + + *REG32(DPHY_CSR_GLBL_DQ_DLL_RESET) = 0x0; + *REG32(APHY_CSR_GLBL_ADDR_DLL_RESET) = 0x0; + + SIP_DEBUG(logf("waiting for dphy master dll to lock ...\n")); + for (;;) if ((*REG32(DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT) & 0xFFFF) == 0xFFFF) break; + SIP_DEBUG(logf("dphy master dll locked!\n")); +} + +typedef struct { + uint32_t max_freq; + uint32_t RL; + uint32_t tRPab; + uint32_t tRPpb; + uint32_t tRCD; + uint32_t tWR; + uint32_t tRASmin; + uint32_t tRRD; + uint32_t tWTR; + uint32_t tXSR; + uint32_t tXP; + uint32_t tRFCab; + uint32_t tRTP; + uint32_t tCKE; + uint32_t tCKESR; + uint32_t tDQSCKMAXx2; + uint32_t tRASmax; + uint32_t tFAW; + uint32_t tRC; + uint32_t tREFI; + + uint32_t tINIT1; + uint32_t tINIT3; + uint32_t tINIT5; + + uint32_t rowbits; + uint32_t colbits; + uint32_t banklow; +} lpddr2_timings_t; + +// 7.8 / (1.0 / 400) + +lpddr2_timings_t g_InitSdramParameters = { + /* SA (us) */ + .tREFI = 3113, //Refresh rate: 3113 * (1.0 / 400) = 7.78us + /* SC (ns) */ + .tRFCab = 50, + .tRRD = 2, + .tWR = 7, + .tWTR = 4, + /* SD (ns) */ + .tRPab = 7, + .tRC = 24, + .tXP = 1, + .tRASmin = 15, + .tRPpb = 6, + .tRCD = 6, + /* SE (ns) */ + .tFAW = 18, + .tRTP = 1, + .tXSR = 54, + /* PT */ + .tINIT1 = 40, // Minimum CKE low time after completion of power ramp: 40 * (1.0 / 0.4) = 100ns + .tINIT3 = 79800, // Minimum Idle time after first CKE assertion: 79800 * (1.0 / 400) = 199.5us ~ 200us + .tINIT5 = 3990, //Max DAI: 3990* (1.0 / 400) = 9.9us ~ 10us + /* SB */ + .rowbits = 2, + .colbits = 1, + .banklow = 2 +}; + +static void reset_with_timing(lpddr2_timings_t* T) { + uint32_t ctrl = 0x4; + + *REG32(SD_CS) = (*REG32(SD_CS) & ~(SD_CS_DEL_KEEP_SET|SD_CS_DPD_SET|SD_CS_RESTRT_SET)) | SD_CS_STBY_SET; + + /* wait for SDRAM controller to go down */ + SIP_DEBUG(logf("waiting for SDRAM controller to go down (%X) ...\n", *REG32(SD_CS))); + for (;;) if ((*REG32(SD_CS) & SD_CS_SDUP_SET) == 0) break; + SIP_DEBUG(logf("SDRAM controller down!\n")); + + /* disable SDRAM clock */ + clkman_update_begin(); + *REG32(CM_SDCCTL) = (*REG32(CM_SDCCTL) & ~(CM_SDCCTL_ENAB_SET|CM_SDCCTL_CTRL_SET)) | CM_PASSWORD; + clkman_update_end(); + + SIP_DEBUG(logf("SDRAM clock disabled!\n")); + + /* + * Migrate over to master PLL. + */ + + *REG32(APHY_CSR_DDR_PLL_PWRDWN) = 0; + *REG32(APHY_CSR_DDR_PLL_GLOBAL_RESET) = 0; + *REG32(APHY_CSR_DDR_PLL_POST_DIV_RESET) = 0; + + /* 400MHz */ + *REG32(APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0) = (1 << 16) | 0x53; + *REG32(APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1) = 0; + *REG32(APHY_CSR_DDR_PLL_MDIV_VALUE) = 0; + + *REG32(APHY_CSR_DDR_PLL_GLOBAL_RESET) = 1; + + SIP_DEBUG(logf("waiting for master ddr pll to lock ...\n")); + for (;;) if (*REG32(APHY_CSR_DDR_PLL_LOCK_STATUS) & (1 << 16)) break; + SIP_DEBUG(logf("master ddr pll locked!\n")); + + *REG32(APHY_CSR_DDR_PLL_POST_DIV_RESET) = 1; + + clkman_update_begin(); + *REG32(CM_SDCCTL) = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (*REG32(CM_SDCCTL) & CM_SDCCTL_CTRL_CLR); + clkman_update_end(); + + *REG32(SD_SA) = + (T->tREFI << SD_SA_RFSH_T_LSB) + | SD_SA_PGEHLDE_SET + | SD_SA_CLKSTOP_SET + | SD_SA_POWSAVE_SET + | 0x3214; + + *REG32(SD_SB) = + SD_SB_REORDER_SET + | (T->banklow << SD_SB_BANKLOW_LSB) + | SD_SB_EIGHTBANK_SET + | (T->rowbits << SD_SB_ROWBITS_LSB) + | (T->colbits << SD_SB_COLBITS_LSB); + + logf("SDRAM Addressing Mode: Bank=%d Row=%d Col=%d SB=0x%X\n", T->banklow, T->rowbits, T->colbits, *REG32(SD_SB)); + + *REG32(SD_SC) = + (T->tRFCab << SD_SC_T_RFC_LSB) + | (T->tRRD << SD_SC_T_RRD_LSB) + | (T->tWR << SD_SC_T_WR_LSB) + | (T->tWTR << SD_SC_T_WTR_LSB) + | (3 << SD_SC_WL_LSB); + + *REG32(SD_SD) = + (T->tRPab << SD_SD_T_RPab_LSB) + | (T->tRC << SD_SD_T_RC_LSB) + | (T->tXP << SD_SD_T_XP_LSB) + | (T->tRASmin << SD_SD_T_RAS_LSB) + | (T->tRPpb << SD_SD_T_RPpb_LSB) + | (T->tRCD << SD_SD_T_RCD_LSB); + + *REG32(SD_SE) = + (1 << SD_SE_RL_EN_LSB) + | (4 << SD_SE_RL_LSB) + | (T->tFAW << SD_SE_T_FAW_LSB) + | (T->tRTP << SD_SE_T_RTP_LSB) + | (T->tXSR << SD_SE_T_XSR_LSB); + + *REG32(SD_PT1) = + (T->tINIT3 << SD_PT1_T_INIT3_LSB) + | (T->tINIT1 << SD_PT1_T_INIT1_LSB); + + *REG32(SD_PT2) = + T->tINIT5 << SD_PT2_T_INIT5_LSB; + + *REG32(SD_MRT) = + 0x3 << SD_MRT_T_MRW_LSB; + + reset_phy_dll(); + + /* wait for address line pll to come back */ + SIP_DEBUG(logf("waiting for address dll to lock ...\n")); + for (;;) if (*REG32(APHY_CSR_GLBL_ADR_DLL_LOCK_STAT) == 3) break; + SIP_DEBUG(logf("address dll locked!\n")); + + /* tell sdc we're done messing with address lines */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; + + /* woo, turn on sdram! */ + *REG32(SD_CS) = + (((4 << SD_CS_ASHDN_T_LSB) + | SD_CS_STATEN_SET + | SD_CS_EN_SET) + & ~(SD_CS_STOP_SET|SD_CS_STBY_SET)) | SD_CS_RESTRT_SET; +} + +static unsigned int read_mr(unsigned int addr) { + while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + *REG32(SD_MR) = addr & 0xFF; + unsigned int mrr; + while (((mrr = *REG32(SD_MR)) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + return mrr; +} + +static unsigned int write_mr(unsigned int addr, unsigned int data, bool wait) { + while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + + *REG32(SD_MR) = (addr & 0xFF) | ((data & 0xFF) << 8) | SD_MR_RW_SET; + + if (wait) { + unsigned int mrr; + while (((mrr = *REG32(SD_MR)) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + + if (mrr & SD_MR_TIMEOUT_SET) + panic("MR write timed out (addr=%d data=0x%X)", addr, data); + + return mrr; + } else { + return 0; + } +} + +static void reset_phy(void) { + logf("%s: resetting SDRAM PHY ...\n", __FUNCTION__); + + /* reset PHYC */ + *REG32(SD_PHYC) = SD_PHYC_PHYRST_SET; + udelay(64); + *REG32(SD_PHYC) = 0; + + logf("%s: resetting DPHY CTRL ...\n", __FUNCTION__); + + *REG32(DPHY_CSR_DQ_PHY_MISC_CTRL) = 0x7; + *REG32(DPHY_CSR_DQ_PAD_MISC_CTRL) = 0x0; + *REG32(DPHY_CSR_BOOT_READ_DQS_GATE_CTRL) = 0x11; + + reset_phy_dll(); + + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; +} + +static void switch_to_cprman_clock(unsigned int source, unsigned int div) { + *REG32(CM_SDCDIV) = CM_PASSWORD | (div << CM_SDCDIV_DIV_LSB); + *REG32(CM_SDCCTL) = CM_PASSWORD | (*REG32(CM_SDCCTL) & CM_SDCCTL_SRC_CLR) | source; + *REG32(CM_SDCCTL) |= CM_PASSWORD | CM_SDCCTL_ENAB_SET; + + logf("switching sdram to cprman clock (src=%d, div=%d), waiting for busy (0x%X) ...\n", source, div, *REG32(CM_SDCCTL)); + + for (;;) if (*REG32(CM_SDCCTL) & CM_SDCCTL_BUSY_SET) break; + + logf("busy set, switch complete!\n"); +} + +static void init_clkman(void) { + uint32_t ctrl = 0; + + clkman_update_begin(); + *REG32(CM_SDCCTL) = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (*REG32(CM_SDCCTL) & CM_SDCCTL_CTRL_CLR); + clkman_update_end(); +} + +#define CALL_INIT_CLKMAN init_clkman(); + + +/***************************************************************************** + * Calibration + *****************************************************************************/ + +static void calibrate_pvt_early(void) { + /* some hw revisions require different slews */ + uint32_t cpuid; + __asm__ ("version %0" : "=r"(cpuid)); + // tests for a cpuid ending in 0x___14_ + bool st = ((cpuid >> 4) & 0xFFF) == 0x14; + uint32_t dq_slew = (st ? 2 : 3); + logf("cpuid 0x%x and dq_slew %d\n", cpuid, dq_slew); + + /* i don't get it, the spec says do not use this register */ + write_mr(0xFF, 0, true); + /* RL = 6 / WL = 3 */ + write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, true); + + *REG32(APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL) = 0x333; + *REG32(DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL) = (dq_slew << 8) | (dq_slew << 4) | 3; + + logf("DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = 0x%X\n", *REG32(DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL)); + + /* tell sdc we want to calibrate */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = BIST_pvt; + + /* pvt compensation */ + *REG32(APHY_CSR_ADDR_PVT_COMP_CTRL) = PVT_calibrate_request; + logf("waiting for address PVT calibration ...\n"); + for (;;) if (*REG32(APHY_CSR_ADDR_PVT_COMP_STATUS) & 2) break; + + *REG32(DPHY_CSR_DQ_PVT_COMP_CTRL) = PVT_calibrate_request; + logf("waiting for data PVT calibration ...\n"); + for (;;) if (*REG32(DPHY_CSR_DQ_PVT_COMP_STATUS) & 2) break; + + /* tell sdc we're done calibrating */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; + + /* send calibration command */ + uint32_t old_mrt = *REG32(SD_MRT); + *REG32(SD_MRT) = 20; + logf("waiting for SDRAM calibration command ...\n"); + *REG32(SD_MR) = LPDDR2_MR_CALIBRATION | (0xFF << 8) | SD_MR_RW_SET | SD_MR_HI_Z_SET; + while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + *REG32(SD_MRT) = old_mrt; + + write_mr(LPDDR2_MR_IO_CONFIG, st ? 3 : 2, false); +} + + +/***************************************************************************** + * Late init + *****************************************************************************/ + +static void init_late(void) { +} + +/***************************************************************************** + * Self-test + *****************************************************************************/ + +#define RT_BASE 0xC0000000 + +#define RT_PAT0 0xAAAAAAAA +#define RT_PAT1 0xFF00AA00 +#define RT_PAT2 0x99999999 + +#define RT_ASSERT(i_, expected) \ + if (ram[(i_)] != expected) { \ + logf("ERROR: At 0x%p, was expecting 0x%X from read, got 0x%X instead!\n", \ + &ram[(i_)], \ + expected, \ + ram[(i_)]); \ + panic("SDRAM self test failed!"); \ + } + +// tests a 16kb chunk of ram, starting at addr +static void selftest_at(uint32_t addr) { + logf("Testing region at 0x%X ...\n", addr); + + // do all acceess via the uncached alias, otherwise it would be an L2 cache hit + volatile uint32_t* ram = (volatile uint32_t*)(addr | RT_BASE); + + for (int i = 0; i < 0x1000; i += 4) { + ram[i] = RT_PAT0; + ram[i + 1] = RT_PAT1; + ram[i + 2] = RT_PAT2; + ram[i + 3] = RT_PAT0; + } + + for (int i = 0; i < 0x1000; i += 4) { + RT_ASSERT(i, RT_PAT0); + RT_ASSERT(i + 1, RT_PAT1); + RT_ASSERT(i + 2, RT_PAT2); + RT_ASSERT(i + 3, RT_PAT0); + } +} + +static void selftest(void) { + logf("Starting self test ...\n"); + + switch (g_RAMSize) { + case kRamSize1GB: + selftest_at(0x3FF00000); // 1023mb + selftest_at(0x2FF00000); // 767mb + case kRamSize512MB: + selftest_at(0x1FF00000); // 511mb + case kRamSize256MB: + selftest_at(0xFF00000); // 255mb + default: + selftest_at(0x0); + } + + logf("Self test successful!\n"); +} + +#undef RT_ASSERT + +void sdram_init() { + uint32_t vendor_id, bc; + + logf("(0) SD_CS = 0x%X\n", *REG32(SD_CS)); + + *REG32(PM_SMPS) = PM_PASSWORD | 0x1; + *REG32(A2W_SMPS_LDO1) = A2W_PASSWORD | 0x40000; + *REG32(A2W_SMPS_LDO0) = A2W_PASSWORD | 0x0; + + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_DDREN_SET; + + /* + * STEP 1: + * configure the low-frequency PLL and enable SDC and perform + * the calibration sequence. + */ + + switch_to_cprman_clock(CM_SRC_OSC, 1); + + CALL_INIT_CLKMAN; + + reset_phy(); + + /* magic values */ + *REG32(SD_SA) = 0x006E3395; + *REG32(SD_SB) = 0x0F9; + *REG32(SD_SC) = 0x6000431; + *REG32(SD_SD) = 0x10000011; + *REG32(SD_SE) = 0x10106000; + *REG32(SD_PT1) = 0x0AF002; + *REG32(SD_PT2) = 0x8C; + *REG32(SD_MRT) = 0x3; + *REG32(SD_CS) = 0x200042; + + /* wait for SDRAM controller */ + logf("waiting for SDUP (%X) ...\n", *REG32(SD_CS)); + for (;;) if (*REG32(SD_CS) & SD_CS_SDUP_SET) break; + logf("SDRAM controller has arrived! (%X)\n", *REG32(SD_CS)); + + /* RL = 6 / WL = 3 */ + write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, false); + calibrate_pvt_early(); + + /* identify installed memory */ + vendor_id = read_mr(LPDDR2_MR_MANUFACTURER_ID); + if (!MR_REQUEST_SUCCESS(vendor_id)) { + panic("vendor id memory register read timed out"); + } + vendor_id = MR_GET_RDATA(vendor_id); + + bc = read_mr(LPDDR2_MR_METRICS); + if (!MR_REQUEST_SUCCESS(bc)) { + panic("basic configuration memory register read timed out"); + } + bc = MR_GET_RDATA(bc); + + g_RAMSize = lpddr2_size(bc); + + logf("SDRAM Type: %s %s LPDDR2 (BC=0x%X)\n", + lpddr2_manufacturer_name(vendor_id), + size_to_string[g_RAMSize], + bc); + + if (g_RAMSize == kRamSizeUnknown) + panic("unknown ram size (MR8 response was 0x%X)", bc); + + /* + * STEP 2: + * after calibration, enable high-freq SDRAM PLL. because we're + * running from cache, we can freely mess with SDRAM clock without + * any issues, removing the need to copy the SDRAM late init stuff + * to bootrom ram. if later code that's running from SDRAM wants to + * mess with SDRAM clock it would need to do that. + */ + + if (g_RAMSize == kRamSize1GB) { + g_InitSdramParameters.colbits = 3; + g_InitSdramParameters.rowbits = 3; + g_InitSdramParameters.banklow = 3; + } else if (g_RAMSize == kRamSize512MB) { + g_InitSdramParameters.colbits = 2; + } + + reset_with_timing(&g_InitSdramParameters); + init_late(); + selftest(); +} + +static void ddr2_init(const struct app_descriptor *app) { +} + +static void ddr2_entry(const struct app_descriptor *app, void *args) { + sdram_init(); +} + +APP_START(ddr2) + .init = ddr2_init, + .entry = ddr2_entry, +APP_END diff --git a/platform/bcm28xx/rpi-ddr2/sdram.h b/platform/bcm28xx/rpi-ddr2/sdram.h new file mode 100644 index 0000000000..eb5d29ce4e --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/sdram.h @@ -0,0 +1,13 @@ +#pragma once + +void sdram_init(void); + +enum RamSize { + kRamSize1GB = 0, + kRamSize512MB = 1, + kRamSize256MB = 2, + kRamSize128MB = 3, + kRamSize2GB = 4, + kRamSize4GB = 5, + kRamSizeUnknown +}; diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk index cd8de74173..b359d1ea92 100644 --- a/project/rpi3-bootcode.mk +++ b/project/rpi3-bootcode.mk @@ -4,10 +4,11 @@ TARGET := rpi3-vpu ARCH := vc4 MODULES += \ - app/shell \ app/stringtests \ + app/rpi-vpu-bootload \ lib/cksum \ lib/debugcommands \ + #app/shell \ #app/tests \ GLOBAL_DEFINES += BOOTCODE=1 From 964020e2a7eccf27eeefa2efbd3d4c71e8c028e9 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 30 Jan 2020 16:06:24 -0400 Subject: [PATCH 010/100] move the vector table --- arch/vc4/intc.c | 2 +- platform/bcm28xx/bootcode.ld | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index 35942329d2..ffe62b8e4c 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -19,7 +19,7 @@ struct handlerArgPair irq_handlers[64]; // it will then push pc and sr onto the new stack // it will then read an entry from this vector table, and set the PC to that entry // if the highest bit on this addr is set, the cpu will switch into supervisor mode -irqType __attribute__ ((aligned (512))) vectorTable[128]; +irqType vectorTable[128] __attribute__ ((section(".data.vectorTable"))); uint8_t irq_stack0[4096]; diff --git a/platform/bcm28xx/bootcode.ld b/platform/bcm28xx/bootcode.ld index bbe44309a6..a3698ba835 100644 --- a/platform/bcm28xx/bootcode.ld +++ b/platform/bcm28xx/bootcode.ld @@ -3,9 +3,11 @@ MEMORY { } GROUP(-lgcc) SECTIONS { - .text : { + .vectorTable : { . = 0x0; - . = 0x200; + *(.data.vectorTable) + } + .text : { _text = .; *(.text.start) *(.text) From 265ddb4e6b6131e3ea895b28fd879b6b897e935b Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 12 Feb 2020 05:23:03 -0400 Subject: [PATCH 011/100] bootcode.bin bootloader start --- app/rpi-vpu-bootload/bootloader.c | 19 +++ app/rpi-vpu-bootload/rules.mk | 5 +- arch/vc4/intc.c | 11 +- arch/vc4/start.S | 38 ++++++ kernel/novm/novm.c | 1 + kernel/thread.c | 2 +- .../bcm28xx/include/platform/bcm28xx/otp.h | 3 + .../platform/bcm28xx}/sdram.h | 0 platform/bcm28xx/otp/otp.c | 72 +++++++++++ platform/bcm28xx/otp/otp_asm.S | 112 ++++++++++++++++++ platform/bcm28xx/otp/rules.mk | 10 ++ platform/bcm28xx/platform.c | 3 + platform/bcm28xx/rpi-ddr2/sdram.c | 24 +--- platform/bcm28xx/rules.mk | 1 + platform/bcm28xx/uart.c | 3 + platform/bcm28xx/udelay.c | 12 ++ 16 files changed, 288 insertions(+), 28 deletions(-) create mode 100644 platform/bcm28xx/include/platform/bcm28xx/otp.h rename platform/bcm28xx/{rpi-ddr2 => include/platform/bcm28xx}/sdram.h (100%) create mode 100644 platform/bcm28xx/otp/otp.c create mode 100644 platform/bcm28xx/otp/otp_asm.S create mode 100644 platform/bcm28xx/otp/rules.mk create mode 100644 platform/bcm28xx/udelay.c diff --git a/app/rpi-vpu-bootload/bootloader.c b/app/rpi-vpu-bootload/bootloader.c index e69de29bb2..d63c317433 100644 --- a/app/rpi-vpu-bootload/bootloader.c +++ b/app/rpi-vpu-bootload/bootloader.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +static void bootloader_init(const struct app_descriptor *app) { + printf("bootloader init\n"); +} + +static void bootloader_entry(const struct app_descriptor *app, void *args) { + printf("bootloader entry\n\n"); + otp_pretty_print(); + //sdram_init(); +} + +APP_START(bootloader) + .init = bootloader_init, + .entry = bootloader_entry, +APP_END diff --git a/app/rpi-vpu-bootload/rules.mk b/app/rpi-vpu-bootload/rules.mk index 8f0014cf71..5a254d42f4 100644 --- a/app/rpi-vpu-bootload/rules.mk +++ b/app/rpi-vpu-bootload/rules.mk @@ -2,7 +2,10 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) -MODULE_DEPS += platform/bcm28xx/rpi-ddr2 +MODULE_DEPS += \ + platform/bcm28xx/rpi-ddr2 \ + platform/bcm28xx/otp \ + MODULE_SRCS += $(LOCAL_DIR)/bootloader.c diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index ffe62b8e4c..6ab07c59ce 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -59,9 +59,14 @@ void intc_init(void) { // TODO for (int i=0; i<64; i++) { irq_handlers[0].h = 0; // is this needed? maybe .bss already took care of it? - set_interrupt(i, false, 0); - set_interrupt(i, false, 1); } + // rather then call set_interrupt for each bit in each byte, just blanket clear all + // this will disable every hardware irq + volatile uint32_t *maskreg = IC0_BASE + 0x10; + for (int i=0; i<8; i++) maskreg[i] = 0; + maskreg = IC1_BASE + 0x10; + for (int i=0; i<8; i++) maskreg[i] = 0; + // https://github.com/hermanhermitage/videocoreiv/wiki/VideoCore-IV-Programmers-Manual#interrupts // processor internal exceptions vectorTable[0] = fleh_zero; @@ -100,7 +105,7 @@ void intc_init(void) { if (((void *)*REG32(IC0_VADDR)) != vectorTable) { printf("vector table now at 0x%08x 0x%08x\n", *REG32(IC0_VADDR), (uint32_t)vectorTable); - panic("vector table failed to install"); + panic("vector table failed to install\n"); } } diff --git a/arch/vc4/start.S b/arch/vc4/start.S index 44d40a3cba..1d0352fae7 100644 --- a/arch/vc4/start.S +++ b/arch/vc4/start.S @@ -1,11 +1,17 @@ #include +#define MANUAL_UART + .section .text.start FUNCTION(_start) .global _start _start: di mov sp, _fstack +#ifdef MANUAL_UART + bl manual_uart_cfg +#endif + bl zero_bss bl lk_main loop: b loop @@ -28,3 +34,35 @@ testit: st r3, (r0+8) st r4, (r0+12) rts + +#ifdef MANUAL_UART +manual_uart_cfg: + mov r0, 0x7e200004 + mov r1, 0x00004000 + st r1, (r0) + mov r0, 0x7e1010f4 + mov r1, 0x5a003900 + st r1, (r0) + mov r0, 0x7e1010f0 + mov r1, 0x5a000211 + st r1, (r0) + mov r0, 0x7e201044 + mov r1, 0x000007ff + st r1, (r0) + mov r0, 0x7e20102c + mov r1, 0x00000070 + st r1, (r0) + mov r0, 0x7e201024 + mov r1, 0x00000002 + st r1, (r0) + mov r0, 0x7e201028 + mov r1, 0x0000003b + st r1, (r0) + mov r0, 0x7e201030 + mov r1, 0x00000301 + st r1, (r0) + mov r0, 0x7e201000 + mov r1, 'U' + st r1, (r0) + rts +#endif diff --git a/kernel/novm/novm.c b/kernel/novm/novm.c index ba664ee241..04a41bc2bb 100644 --- a/kernel/novm/novm.c +++ b/kernel/novm/novm.c @@ -299,6 +299,7 @@ static void novm_dump_arena(struct novm_arena *n) { mutex_acquire(&n->lock); printf("name '%s', %zu pages, each %zdk (%zdk in all)\n", n->name, n->pages, (size_t)PAGE_SIZE >> 10, (size_t)(PAGE_SIZE * n->pages) >> 10); printf(" range: %p-%p\n", (void *)n->base, (char *)n->base + n->size); + printf(" size: 0x%x\n", n->size); printf(" unaligned range: %p-%p\n", n->unaligned_area, n->unaligned_area + n->unaligned_size); unsigned i; size_t in_use = 0; diff --git a/kernel/thread.c b/kernel/thread.c index 166b96ae39..e46b4e0b99 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -603,7 +603,7 @@ void thread_yield(void) { THREAD_STATS_INC(yields); - dprintf(INFO, "thread_yield\n"); + //dprintf(INFO, "thread_yield\n"); /* we are yielding the cpu, so stick ourselves into the tail of the run queue and reschedule */ current_thread->state = THREAD_READY; diff --git a/platform/bcm28xx/include/platform/bcm28xx/otp.h b/platform/bcm28xx/include/platform/bcm28xx/otp.h new file mode 100644 index 0000000000..cd97dcfd86 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/otp.h @@ -0,0 +1,3 @@ +#pragma once + +uint32_t otp_read(uint8_t addr); diff --git a/platform/bcm28xx/rpi-ddr2/sdram.h b/platform/bcm28xx/include/platform/bcm28xx/sdram.h similarity index 100% rename from platform/bcm28xx/rpi-ddr2/sdram.h rename to platform/bcm28xx/include/platform/bcm28xx/sdram.h diff --git a/platform/bcm28xx/otp/otp.c b/platform/bcm28xx/otp/otp.c new file mode 100644 index 0000000000..77b5135480 --- /dev/null +++ b/platform/bcm28xx/otp/otp.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +static int cmd_otp_pretty(int argc, const cmd_args *argv); +uint32_t otp_read_internal(uint32_t addr); + +STATIC_COMMAND_START +STATIC_COMMAND("otp_pretty_print", "pretty-print all known otp values", &cmd_otp_pretty) +STATIC_COMMAND_END(otp); + +uint32_t otp_read(uint8_t addr) { + return otp_read_internal(addr); +} + +void dump_all_otp(void) { + printf("full otp dump\n"); + for (uint8_t addr=0; addr < 67; addr++) { + uint32_t value = otp_read(addr); + printf("%02d:%08x\n", addr, value); + } +} + +void otp_pretty_print(void) { + // https://github.com/raspberrypi/firmware/issues/974 + // addr 32 contains warrenty flag + uint32_t bootmode = otp_read(17); + printf("OTP17: 0x%08x\n", bootmode); + if (bootmode & (1<< 1)) printf(" 19.2mhz crystal present\n"); + if (bootmode & (1<< 3)) printf(" SDIO pullups should be on?\n"); + if (bootmode & (1<<19)) printf(" GPIO boot mode\n"); + if (bootmode & (1<<20)) printf(" GPIO boot mode bank bit is set\n"); + if (bootmode & (1<<21)) printf(" SD card boot enabled\n"); + if (bootmode & (1<<22)) printf(" bank to boot from set\n"); + if (bootmode & (1<<28)) printf(" USB device boot enabled\n"); + if (bootmode & (1<<29)) printf(" USB host boot enabled (ethernet/mass-storage)\n"); + if (bootmode != otp_read(18)) printf("WARNING: boot mode duplicate doesnt match\n"); + uint32_t serial = otp_read(28); + printf("\nSoC serial# 0x%08x\n", serial); + if (~serial != otp_read(29)) printf("WARNING: serial# duplicate doesnt match\n"); + uint32_t revision = otp_read(30); + // https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md + printf("\nHW revision: 0x%08x\n", revision); + if (revision & (1 <<23)) { // new style revision + printf(" Type: %d\n", (revision >> 4) & 0xff); + printf(" Rev: %d\n", revision & 0xf); + printf(" Proc: %d\n", (revision >> 12) & 0xf); + printf(" Manufacturer: %d\n", (revision >> 16) & 0xf); + printf(" Ram: %d\n", (revision >> 20) & 0x7); + } + uint32_t maclow = otp_read(64); + uint32_t machi = otp_read(65); + printf("\nOptional Mac Override: %08x%x\n", maclow, machi); + + uint32_t advanced_boot = otp_read(66); + printf("\nOTP66: 0x%08x\n", advanced_boot); + if (advanced_boot & (1<<7)) { + printf(" ETH_CLK on GPIO%d\n", advanced_boot & 0x7f); + if (advanced_boot & (1<<25)) printf(" ETH_CLK 24mhz\n"); + else printf(" ETH_CLK 25mhz\n"); + } + if (advanced_boot & (1<<15)) { + printf(" LAN_RUN on GPIO%d\n", (advanced_boot >> 8) & 0x7f); + } + if (advanced_boot & (1<<24)) printf(" extended USB timeout\n"); +} + +int cmd_otp_pretty(int argc, const cmd_args *argv) { + otp_pretty_print(); + return 0; +} diff --git a/platform/bcm28xx/otp/otp_asm.S b/platform/bcm28xx/otp/otp_asm.S new file mode 100644 index 0000000000..6479797616 --- /dev/null +++ b/platform/bcm28xx/otp/otp_asm.S @@ -0,0 +1,112 @@ +// copied from https://github.com/ptesarik/vc4boot + +A2W_BASE = 0x7e102000 +A2W_XOSC0 = 0x090 + +OTP_BASE = 0x7e20f000 +OTP_CONFIG_REG = 0x04 +OTP_CTRL_LO_REG = 0x08 +OTP_CTRL_HI_REG = 0x0c +OTP_STATUS_REG = 0x10 +OTP_DATA_REG = 0x18 +OTP_ADDR_REG = 0x1c + +#if RPI4 + OTP_READY_BIT = 1 +#else + OTP_READY_BIT = 0 +#endif + +.text +.global otp_read_internal +otp_read_internal: + stm r6-r7,lr,(--sp) + + mov r6, r0 // save arg0 in r6 + bl otp_open + mov r0, r6 + bl otp_read_reg + mov r7, r0 // set the result asside so close wont clobber + bl otp_close + mov r0, r7 + + ldm r6-r7,pc,(sp++) + +otp_open: + stm lr, (--sp) + mov r2, 0x03 + mov r1, OTP_BASE + mov r3, A2W_BASE + A2W_XOSC0 + st r2, (r1 + OTP_CONFIG_REG) // OTP_CONFIG_REG = 0x3 + + mov r0, 2 +1: + ld r2, (r3) // read A2W_XOSC0 + addcmpbge r0, -1, 0, 1b // repeat 2 times total + + mov r2, 0 + st r2, (r1 + OTP_CTRL_HI_REG) // OTP_CTRL_HI_REG = 0 + st r2, (r1 + OTP_CTRL_LO_REG) // OTP_CTRL_LO_REG = 0 + + mov r0, 2 +1: + ld r2, (r3) // read A2W_XOSC0 + addcmpbge r0, -1, 0, 1b // repeat 2 times total + + mov r2, 0x2 + st r2, (r1 + OTP_CONFIG_REG) // OTP_CONFIG_REG = 2 + ldm pc, (sp++) + +otp_read_reg: + stm lr, (--sp) + mov r1, OTP_BASE + mov r3, A2W_BASE + A2W_XOSC0 + st r0, (r1 + OTP_ADDR_REG) // OTP_ADDR_REG = arg0 + + mov r0, 2 +1: + ld r2, (r3) + addcmpbge r0, -1, 0, 1b // repeat 2 times total + + mov r2, 0 + ld r0, (r1 + OTP_ADDR_REG) // r0 = OTP_ADDR_REG + st r2, (r1 + OTP_CTRL_HI_REG) // OTP_CTRL_HI_REG = 0 + st r2, (r1 + OTP_CTRL_LO_REG) // OTP_CTRL_LO_REG = 0 + + mov r0, 2 +1: + ld r2, (r3) + addcmpbge r0, -1, 0, 1b // repeat 2 times total + + mov r2, 1 + ld r0, (r1 + OTP_CTRL_LO_REG) // read ctrl low + st r2, (r1 + OTP_CTRL_LO_REG) // ctrl low = 1 + ld r0, (r1 + OTP_CTRL_LO_REG) // read ctrl low again +1: + mov r0, 2 +2: + ld r2, (r3) + addcmpbge r0, -1, 0, 2b // repeat 2 times total + + ld r0, (r1 + OTP_STATUS_REG) // read status reg + btest r0, OTP_READY_BIT // check if its ready + beq 1b // if not ready, stall some more and try again + ld r0, (r1 + OTP_DATA_REG) // read final answer + ldm pc, (sp++) + +otp_close: + stm lr, (--sp) + mov r2, 0 + mov r1, OTP_BASE + mov r3, A2W_BASE + A2W_XOSC0 + st r2, (r1 + OTP_CTRL_HI_REG) // OTP_CTRL_HI_REG = 0 + st r2, (r1 + OTP_CTRL_LO_REG) // OTP_CTRL_LO_REG = 0 + + mov r0, 2 +1: + ld r2, (r3) + addcmpbge r0, -1, 0, 1b // repeat 2 times total + + mov r2, 0 + st r2, (r1 + OTP_CONFIG_REG) + ldm pc, (sp++) diff --git a/platform/bcm28xx/otp/rules.mk b/platform/bcm28xx/otp/rules.mk new file mode 100644 index 0000000000..378fc01fd9 --- /dev/null +++ b/platform/bcm28xx/otp/rules.mk @@ -0,0 +1,10 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/otp.c \ + $(LOCAL_DIR)/otp_asm.S \ + + +include make/module.mk diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index a4743be987..768cd7ea9e 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -215,7 +215,10 @@ void platform_init(void) { __asm__ volatile ("mov %0, sp" : "=r"(sp)); dprintf(INFO, "platform_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); #endif + +#ifdef RPI4 gpio_config(42, 1); +#endif uart_init(); #if BCM2837 init_framebuffer(); diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index 6e5950eacb..80eb3f2438 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -26,7 +26,7 @@ VideoCoreIV SDRAM initialization code. #include #include -#include "sdram.h" +#include #include "ddr2.h" #define ALWAYS_INLINE __attribute__((always_inline)) inline @@ -72,16 +72,6 @@ enum RamSize g_RAMSize = kRamSizeUnknown; #define logf(fmt, ...) print_timestamp(); printf("[SDRAM:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); -// TODO, move this to a better place -void udelay(uint32_t t) { - uint32_t tv = *REG32(ST_CLO); - for (;;) { - /* nop still takes a cycle i think? */ - __asm__ __volatile__ ("nop" :::); - if ((*REG32(ST_CLO) - tv) > t) return; - } -} - void print_timestamp() { uint32_t clock_lo = *REG32(ST_CLO); @@ -609,15 +599,3 @@ void sdram_init() { init_late(); selftest(); } - -static void ddr2_init(const struct app_descriptor *app) { -} - -static void ddr2_entry(const struct app_descriptor *app, void *args) { - sdram_init(); -} - -APP_START(ddr2) - .init = ddr2_init, - .entry = ddr2_entry, -APP_END diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index f9088467e6..bc4cb7f475 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -100,6 +100,7 @@ else ifeq ($(TARGET),rpi3-vpu) MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ + $(LOCAL_DIR)/udelay.c \ else ifeq ($(TARGET),rpi4-vpu) MEMSIZE ?= 0x01400000 # 20MB diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 686e65fbc1..af0e410352 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -135,6 +135,7 @@ void uart_init(void) { } int uart_putc(int port, char c); +void udelay(uint32_t t); void uart_init_early(void) { if (*REG32(CM_UARTDIV) == 0) { @@ -144,6 +145,7 @@ void uart_init_early(void) { *REG32(CM_UARTDIV) = CM_PASSWORD | 0x3900; *REG32(CM_UARTCTL) = CM_PASSWORD | CM_SRC_OSC | CM_UARTCTL_FRAC_SET | CM_UARTCTL_ENAB_SET; } + udelay(100); for (size_t i = 0; i < NUM_UART; i++) { uintptr_t base = uart_to_ptr(i); @@ -157,6 +159,7 @@ void uart_init_early(void) { UARTREG(base, UART_CR) = (1<<8)|(1<<0); // tx_enable, uarten } gpio_config(14, 4); + printf("uart early init done\n"); } int uart_putc(int port, char c) { diff --git a/platform/bcm28xx/udelay.c b/platform/bcm28xx/udelay.c new file mode 100644 index 0000000000..9a3f3f53ab --- /dev/null +++ b/platform/bcm28xx/udelay.c @@ -0,0 +1,12 @@ +#include +#include +#include + +void udelay(uint32_t t) { + uint32_t tv = *REG32(ST_CLO); + for (;;) { + /* nop still takes a cycle i think? */ + __asm__ __volatile__ ("nop" :::); + if ((*REG32(ST_CLO) - tv) > t) return; + } +} From a8a179621013b545faba839c42b689b98e09f657 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 12 Feb 2020 05:25:07 -0400 Subject: [PATCH 012/100] start the rpi3 start.elf code --- arch/vc4/arch.c | 8 ++++++++ arch/vc4/intc.c | 1 - default.nix | 1 + platform/bcm28xx/start.ld | 4 ++++ platform/bcm28xx/uart.c | 18 ++++++++++++++---- project/rpi3-start.mk | 12 ++++++++++++ 6 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 project/rpi3-start.mk diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index 60b8a6d012..4d01282a94 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -5,6 +5,7 @@ #include #include #include +#include static int cmd_boot_other_core(int argc, const cmd_args *argv); static int cmd_testit(int argc, const cmd_args *argv); @@ -17,6 +18,13 @@ STATIC_COMMAND("boot_other_core", "boot the 2nd vpu core", &cmd_boot_other_core) STATIC_COMMAND("testit", "do some asm tests", &cmd_testit) STATIC_COMMAND_END(arch); +extern uint8_t _fbss; +extern uint8_t _ebss; + +void zero_bss() { + bzero(&_fbss, &_ebss - &_fbss); +} + void arch_early_init(void) { uint32_t r28, sp, sr; __asm__ volatile ("mov %0, r28" : "=r"(r28)); diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index 6ab07c59ce..090d76c019 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -50,7 +50,6 @@ void set_interrupt(int intno, bool enable, int core) { *REG32(base + offset) = enable ? v | slot : v; } - void intc_init(void) { uint32_t r28, sp; __asm__ volatile ("mov %0, r28" : "=r"(r28)); diff --git a/default.nix b/default.nix index e5dc20f704..aa7d1bbc4f 100644 --- a/default.nix +++ b/default.nix @@ -23,6 +23,7 @@ in lib.fix (self: { vc4 = { shell = vc4.littlekernel; rpi3.bootcode = vc4.callPackage ./lk.nix { project = "rpi3-bootcode"; }; + rpi3.start = vc4.callPackage ./lk.nix { project = "rpi3-start"; }; rpi4.start4 = vc4.callPackage ./lk.nix { project = "rpi4-start4"; }; }; x86_64 = { diff --git a/platform/bcm28xx/start.ld b/platform/bcm28xx/start.ld index b481f243fd..5a00a8271a 100644 --- a/platform/bcm28xx/start.ld +++ b/platform/bcm28xx/start.ld @@ -43,6 +43,10 @@ SECTIONS { __ctor_end = .; } >ram + .vectorTable : ALIGN(512) { + *(.data.vectorTable) + } >ram + .data : { . = ALIGN(4); _fdata = .; diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index af0e410352..74d09f4964 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -77,10 +77,20 @@ static enum handler_return uart_irq(void *arg) { /* while fifo is not empty, read chars out of it */ while ((UARTREG(base, UART_TFR) & (1<<4)) == 0) { - char c = UARTREG(base, UART_DR); - cbuf_write_char(rxbuf, c, false); - - resched = true; + uint32_t data = UARTREG(base, UART_DR); + char c = data & 0xff; + if (data & 0x400) { + dprintf(INFO, "UART break detected\n"); + } else if (data & 0x100) { + dprintf(INFO, "UART framing error\n"); + } else { + if (data & 0x800) { + dprintf(INFO, "UART input overflow\n"); + } + cbuf_write_char(rxbuf, c, false); + + resched = true; + } } } diff --git a/project/rpi3-start.mk b/project/rpi3-start.mk new file mode 100644 index 0000000000..381d0d4a28 --- /dev/null +++ b/project/rpi3-start.mk @@ -0,0 +1,12 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi3-vpu +ARCH := vc4 + +MODULES += \ + app/shell \ + app/stringtests \ + app/tests \ + lib/cksum \ + lib/debugcommands \ + platform/bcm28xx/otp \ From bba0459937e04cd792304e8eb0641c3ae5dda15e Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 12 Feb 2020 05:36:43 -0400 Subject: [PATCH 013/100] fix CI errors on hydra --- platform/bcm28xx/bootcode.ld | 3 ++- platform/bcm28xx/include/platform/bcm28xx/otp.h | 1 + platform/bcm28xx/include/platform/bcm28xx/udelay.h | 5 +++++ platform/bcm28xx/rpi-ddr2/sdram.c | 2 +- platform/bcm28xx/rules.mk | 1 + platform/bcm28xx/udelay.c | 1 + 6 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 platform/bcm28xx/include/platform/bcm28xx/udelay.h diff --git a/platform/bcm28xx/bootcode.ld b/platform/bcm28xx/bootcode.ld index a3698ba835..c6a8a7e6f9 100644 --- a/platform/bcm28xx/bootcode.ld +++ b/platform/bcm28xx/bootcode.ld @@ -39,10 +39,11 @@ SECTIONS { .bss : { . = ALIGN(4); - __bss_start = .; + _fbss = .; *(.bss) *(COMMON) . = ALIGN(4); + _ebss = .; _end = .; } _fstack = ORIGIN(ram) + LENGTH(ram) - 4; diff --git a/platform/bcm28xx/include/platform/bcm28xx/otp.h b/platform/bcm28xx/include/platform/bcm28xx/otp.h index cd97dcfd86..92d0af41ce 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/otp.h +++ b/platform/bcm28xx/include/platform/bcm28xx/otp.h @@ -1,3 +1,4 @@ #pragma once uint32_t otp_read(uint8_t addr); +void otp_pretty_print(void); diff --git a/platform/bcm28xx/include/platform/bcm28xx/udelay.h b/platform/bcm28xx/include/platform/bcm28xx/udelay.h new file mode 100644 index 0000000000..3598e9af99 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/udelay.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void udelay(uint32_t usec); diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index 80eb3f2438..e88ac20f85 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -25,7 +25,7 @@ VideoCoreIV SDRAM initialization code. #include #include #include - +#include #include #include "ddr2.h" diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index bc4cb7f475..181dcca410 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -115,6 +115,7 @@ GLOBAL_DEFINES += \ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ $(LOCAL_DIR)/genet.c \ + $(LOCAL_DIR)/udelay.c \ endif diff --git a/platform/bcm28xx/udelay.c b/platform/bcm28xx/udelay.c index 9a3f3f53ab..2b68356be2 100644 --- a/platform/bcm28xx/udelay.c +++ b/platform/bcm28xx/udelay.c @@ -1,6 +1,7 @@ #include #include #include +#include void udelay(uint32_t t) { uint32_t tv = *REG32(ST_CLO); From bbd44bf5a2325f502659ec9a39656878703570fc Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 16 Feb 2020 02:31:25 -0400 Subject: [PATCH 014/100] many improvements add sdhost code add gpio pullup test fix peripheral address implement batch gpio pull config changes fix memory information to be based on boot stage, not model add rpi4 recovery.bin support --- arch/vc4/arch.c | 4 +- arch/vc4/start.S | 9 +- platform/bcm28xx/block_device.hpp | 36 + platform/bcm28xx/gpio.c | 45 +- platform/bcm28xx/include/platform/bcm28xx.h | 16 +- .../bcm28xx/include/platform/bcm28xx/gpio.h | 49 + .../bcm28xx/include/platform/bcm28xx/sdhost.h | 33 + .../bcm28xx/include/platform/bcm28xx/udelay.h | 6 + platform/bcm28xx/otp/otp.c | 7 + platform/bcm28xx/print_timestamp.c | 9 + platform/bcm28xx/rpi-ddr2/sdram.c | 1196 ++++++++--------- platform/bcm28xx/rules.mk | 15 +- platform/bcm28xx/sd_proto.hpp | 370 +++++ platform/bcm28xx/sdhost_impl.cpp | 613 +++++++++ project/rpi3-bootcode.mk | 7 +- project/rpi4-recovery.mk | 11 + project/rpi4-start4.mk | 9 +- 17 files changed, 1809 insertions(+), 626 deletions(-) create mode 100644 platform/bcm28xx/block_device.hpp create mode 100644 platform/bcm28xx/include/platform/bcm28xx/gpio.h create mode 100644 platform/bcm28xx/include/platform/bcm28xx/sdhost.h create mode 100644 platform/bcm28xx/print_timestamp.c create mode 100644 platform/bcm28xx/sd_proto.hpp create mode 100644 platform/bcm28xx/sdhost_impl.cpp create mode 100644 project/rpi4-recovery.mk diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index 4d01282a94..db65395eb0 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -21,7 +21,7 @@ STATIC_COMMAND_END(arch); extern uint8_t _fbss; extern uint8_t _ebss; -void zero_bss() { +void zero_bss(void) { bzero(&_fbss, &_ebss - &_fbss); } @@ -57,7 +57,7 @@ static int cmd_boot_other_core(int argc, const cmd_args *argv) { return 0; } -void core2_entry() { +void core2_entry(void) { dprintf(INFO, "core2 says hello\n"); for (;;); } diff --git a/arch/vc4/start.S b/arch/vc4/start.S index 1d0352fae7..ffc3c1cd00 100644 --- a/arch/vc4/start.S +++ b/arch/vc4/start.S @@ -37,13 +37,14 @@ testit: #ifdef MANUAL_UART manual_uart_cfg: - mov r0, 0x7e200004 + mov r0, 0x7e200004 // GP_FSEL1 mov r1, 0x00004000 st r1, (r0) - mov r0, 0x7e1010f4 - mov r1, 0x5a003900 + mov r0, 0x7e1010f4 // CM_UARTDIV + //mov r1, 0x5a003900 19.2mhz divisor + mov r1, 0x5a00a050 // 54mhz divisor st r1, (r0) - mov r0, 0x7e1010f0 + mov r0, 0x7e1010f0 // CM_UARTCTL mov r1, 0x5a000211 st r1, (r0) mov r0, 0x7e201044 diff --git a/platform/bcm28xx/block_device.hpp b/platform/bcm28xx/block_device.hpp new file mode 100644 index 0000000000..f1eae63f65 --- /dev/null +++ b/platform/bcm28xx/block_device.hpp @@ -0,0 +1,36 @@ +/*============================================================================= +Copyright (C) 2016-2017 Authors of rpi-open-firmware +All rights reserved. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +FILE DESCRIPTION +Block device. + +=============================================================================*/ + +struct BlockDevice { + unsigned int block_size; + + template + inline bool read_block(uint32_t sector, T* dest_buffer) { + return read_block(sector, reinterpret_cast(dest_buffer)); + } + + inline unsigned int get_block_size() { + return block_size; + } + + virtual bool read_block(uint32_t sector, uint32_t* buf) = 0; + + /* called to stop the block device */ + virtual void stop() {} +}; diff --git a/platform/bcm28xx/gpio.c b/platform/bcm28xx/gpio.c index 21745c164a..b263d87012 100644 --- a/platform/bcm28xx/gpio.c +++ b/platform/bcm28xx/gpio.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #define NUM_PINS 54 #define BITS_PER_REG 32 @@ -22,11 +24,13 @@ static int cmd_gpio_mode(int argc, const cmd_args *argv); static int cmd_gpio_write(int argc, const cmd_args *argv); static int cmd_gpio_dump_state(int argc, const cmd_args *argv); +static int cmd_gpio_test(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("gpio_mode", "set the gpio alt mode", &cmd_gpio_mode) STATIC_COMMAND("gpio_write", "set gpio output", &cmd_gpio_write) STATIC_COMMAND("gpio_dump_state", "dump current gpio state", &cmd_gpio_dump_state) +STATIC_COMMAND("gpio_test", "test gpio pullup/down", &cmd_gpio_test) STATIC_COMMAND_END(gpio); int gpio_config(unsigned nr, unsigned flags) { @@ -62,7 +66,27 @@ int gpio_get(unsigned nr) { return (*GPIOREG(GPIO_GPLEV0, nr) & (1 << offset)) >> offset; } -#ifdef RPI4 +#ifndef RPI4 +// rpi1-3 models +void gpio_set_pull(unsigned nr, enum pull_mode mode) { +} +void gpio_apply_batch(struct gpio_pull_batch *batch) { + for (enum pull_mode mode = 0; mode <=2; mode++) { + if (batch->bank[mode][0] | batch->bank[mode][1]) { + *REG32(GPIO_GPPUD) = mode; + udelay(500); + *REG32(GPIO_GPPUDCLK0) = batch->bank[mode][0]; + *REG32(GPIO_GPPUDCLK1) = batch->bank[mode][1]; + udelay(500); + *REG32(GPIO_GPPUDCLK0) = 0; + *REG32(GPIO_GPPUDCLK1) = 0; + *REG32(GPIO_GPPUD) = 0; + udelay(500); + } + } +} +#else +// rpi4 int gpio_get_pull(unsigned nr) { unsigned offset = (nr % 16) * 2; volatile uint32_t *pull_cfg = REG32(GPIO_2711_PULL); @@ -148,3 +172,22 @@ static int cmd_gpio_dump_state(int argc, const cmd_args *argv) { } return 0; } + +static int cmd_gpio_test(int argc, const cmd_args *argv) { + uint8_t pins[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }; + for (int i=0; i + +#ifdef __cplusplus +extern "C" { +#endif + +enum BCM2708PinmuxSetting { + kBCM2708PinmuxIn = 0, + kBCM2708PinmuxOut = 1, + kBCM2708Pinmux_ALT5 = 2, + kBCM2708Pinmux_ALT4 = 3, + kBCM2708Pinmux_ALT0 = 4, + kBCM2708Pinmux_ALT1 = 5, + kBCM2708Pinmux_ALT2 = 6, + kBCM2708Pinmux_ALT3 = 7 +}; + +enum pull_mode { + kPullOff = 0, + kPullDown = 1, + kPullUp = 2 +}; + +#ifndef RPI4 +struct gpio_pull_batch { + uint32_t bank[3][2]; +}; + +#define GPIO_PULL_CLEAR(batch) { bzero(&batch, sizeof(batch)); } +#define GPIO_PULL_SET(batch, pin, mode) { batch.bank[mode][pin / 32] |= 1 << (pin % 32); } + +void gpio_apply_batch(struct gpio_pull_batch *batch); +#else +struct gpio_pull_batch { + uint32_t bank[4]; + uint32_t mask[4]; +}; +#define GPIO_PULL_CLEAR(batch) +#define GPIO_PULL_SET(batch, pin, mode) +static inline void gpio_apply_batch(struct gpio_pull_batch *batch) {} +#endif + +void gpio_set_pull(unsigned nr, enum pull_mode mode); + +#ifdef __cplusplus +} +#endif diff --git a/platform/bcm28xx/include/platform/bcm28xx/sdhost.h b/platform/bcm28xx/include/platform/bcm28xx/sdhost.h new file mode 100644 index 0000000000..c98314b0ff --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/sdhost.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#define SH_BASE (BCM_PERIPH_BASE_PHYS + 0x202000) + +#define SH_CMD (SH_BASE + 0x00) +#define SH_CMD_NEW_FLAG_SET 0x8000 +#define SH_CMD_FAIL_FLAG_SET 0x4000 +#define SH_CMD_BUSY_CMD_SET 0x0800 +#define SH_CMD_NO_RESPONSE_SET 0x0400 +#define SH_CMD_LONG_RESPONSE_SET 0x0200 +#define SH_CMD_READ_CMD_SET 0x0040 +#define SH_CMD_COMMAND_SET 0x003f +#define SH_ARG (SH_BASE + 0x04) +#define SH_TOUT (SH_BASE + 0x08) +#define SH_CDIV (SH_BASE + 0x0c) +#define SH_RSP0 (SH_BASE + 0x10) +#define SH_RSP1 (SH_BASE + 0x14) +#define SH_RSP2 (SH_BASE + 0x18) +#define SH_RSP3 (SH_BASE + 0x1c) +#define SH_HSTS (SH_BASE + 0x20) +#define SH_HSTS_DATA_FLAG_SET 0x01 +#define SH_VDD (SH_BASE + 0x30) +#define SH_VDD_POWER_ON_SET 0x01 +#define SH_EDM (SH_BASE + 0x34) +#define SH_HCFG (SH_BASE + 0x38) +#define SH_HCFG_SLOW_CARD_SET 0x8 +#define SH_HCFG_WIDE_EXT_BUS_SET 0x4 +#define SH_HCFG_WIDE_INT_BUS_SET 0x2 +#define SH_HBCT (SH_BASE + 0x3c) +#define SH_DATA (SH_BASE + 0x40) +#define SH_HBLC (SH_BASE + 0x50) diff --git a/platform/bcm28xx/include/platform/bcm28xx/udelay.h b/platform/bcm28xx/include/platform/bcm28xx/udelay.h index 3598e9af99..b7120e8b3d 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/udelay.h +++ b/platform/bcm28xx/include/platform/bcm28xx/udelay.h @@ -2,4 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif void udelay(uint32_t usec); +#ifdef __cplusplus +} +#endif diff --git a/platform/bcm28xx/otp/otp.c b/platform/bcm28xx/otp/otp.c index 77b5135480..01f6ff2e9e 100644 --- a/platform/bcm28xx/otp/otp.c +++ b/platform/bcm28xx/otp/otp.c @@ -4,10 +4,12 @@ #include static int cmd_otp_pretty(int argc, const cmd_args *argv); +static int cmd_otp_full(int argc, const cmd_args *argv); uint32_t otp_read_internal(uint32_t addr); STATIC_COMMAND_START STATIC_COMMAND("otp_pretty_print", "pretty-print all known otp values", &cmd_otp_pretty) +STATIC_COMMAND("otp_dump_all","dump all OTP values", &cmd_otp_full) STATIC_COMMAND_END(otp); uint32_t otp_read(uint8_t addr) { @@ -22,6 +24,11 @@ void dump_all_otp(void) { } } +static int cmd_otp_full(int argc, const cmd_args *argv) { + dump_all_otp(); + return 0; +} + void otp_pretty_print(void) { // https://github.com/raspberrypi/firmware/issues/974 // addr 32 contains warrenty flag diff --git a/platform/bcm28xx/print_timestamp.c b/platform/bcm28xx/print_timestamp.c new file mode 100644 index 0000000000..0bd7a8c059 --- /dev/null +++ b/platform/bcm28xx/print_timestamp.c @@ -0,0 +1,9 @@ +#include +#include +#include + +void print_timestamp() { + uint32_t clock_lo = *REG32(ST_CLO); + + printf("%3ld.%06ld ", clock_lo / 1000000, clock_lo % 1000000); +} diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index e88ac20f85..741a87867d 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -1,601 +1,595 @@ -/*============================================================================= -Copyright (C) 2016-2017 Authors of rpi-open-firmware -Copyright (C) 2016 Julian Brown -All rights reserved. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -FILE DESCRIPTION -VideoCoreIV SDRAM initialization code. - -=============================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ddr2.h" - -#define ALWAYS_INLINE __attribute__((always_inline)) inline - -const char* size_to_string[] = { - "1GB", - "512MB", - "256MB", - "128MB", - "2GB", - "4GB", - "UNKNOWN" -}; - -enum RamSize g_RAMSize = kRamSizeUnknown; - -/* - Registers - ========= - - SC: AC Timing (Page 202) - SB: ??? - SD: AC Timing (Page 202) - SE: AC Timing (Page 202) - - PT1: - Minimum Idle time after first CKE assertion - Minimum CKE low time after completion of power ramp - PT2: - DAI Duration - */ - -#define MR_REQUEST_SUCCESS(x) ((SD_MR_TIMEOUT_SET & x) != SD_MR_TIMEOUT_SET) -#define MR_GET_RDATA(x) ((x & SD_MR_RDATA_SET) >> SD_MR_RDATA_LSB) - -#define SIP_DEBUG(x) x -#define SCLKU_DEBUG(x) //SIP_DEBUG(x) - -#define BIST_pvt 0x20 -#define BIST_reset 0x10 - -#define PVT_calibrate_request 0x1 - -#define logf(fmt, ...) print_timestamp(); printf("[SDRAM:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); - -void print_timestamp() { - uint32_t clock_lo = *REG32(ST_CLO); - - printf("%3ld.%06ld ", clock_lo / 1000000, clock_lo % 1000000); -} - -static const char* lpddr2_manufacturer_name(uint32_t mr) { - switch (mr) { - case 1: - return "Samsung"; - case 2: - return "Qimonda"; - case 3: - return "Elpida"; - case 4: - return "Etron"; - case 5: - return "Nanya"; - case 6: - return "Hynix"; - default: - return "Unknown"; - } -} - -#define MR8_DENSITY_SHIFT 0x2 -#define MR8_DENSITY_MASK (0xF << 0x2) - -static enum RamSize lpddr2_size(uint32_t mr) { - switch (mr) { - case 0x58: - return kRamSize1GB; - case 0x18: - return kRamSize512MB; - case 0x14: - return kRamSize256MB; - case 0x10: - return kRamSize128MB; - default: - return kRamSizeUnknown; - } -} - -/***************************************************************************** - * Guts - *****************************************************************************/ - -ALWAYS_INLINE inline void clkman_update_begin(void) { - *REG32(CM_SDCCTL) |= CM_PASSWORD | CM_SDCCTL_UPDATE_SET; - SCLKU_DEBUG(logf("waiting for ACCPT (%X) ...\n", *REG32(CM_SDCCTL))); - for (;;) if (*REG32(CM_SDCCTL) & CM_SDCCTL_ACCPT_SET) break; - SCLKU_DEBUG(logf("ACCPT received! (%X)\n", *REG32(CM_SDCCTL))); -} - -ALWAYS_INLINE inline void clkman_update_end(void) { - *REG32(CM_SDCCTL) = CM_PASSWORD | (*REG32(CM_SDCCTL) & CM_SDCCTL_UPDATE_CLR); - SCLKU_DEBUG(logf("waiting for ACCPT clear (%X) ...\n", *REG32(CM_SDCCTL))); - for (;;) if ((*REG32(CM_SDCCTL) & CM_SDCCTL_ACCPT_SET) == 0) break; - SCLKU_DEBUG(logf("ACCPT cleared! (%X)\n", *REG32(CM_SDCCTL))); -} - -ALWAYS_INLINE void reset_phy_dll(void) { - SIP_DEBUG(logf("resetting aphy and dphy dlls ...\n")); - - /* politely tell sdc that we'll be messing with address lines */ - *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x30; - - *REG32(DPHY_CSR_GLBL_DQ_DLL_RESET) = 0x1; - *REG32(APHY_CSR_GLBL_ADDR_DLL_RESET) = 0x1; - - /* stall ... */ - *REG32(SD_CS); - *REG32(SD_CS); - *REG32(SD_CS); - *REG32(SD_CS); - - *REG32(DPHY_CSR_GLBL_DQ_DLL_RESET) = 0x0; - *REG32(APHY_CSR_GLBL_ADDR_DLL_RESET) = 0x0; - - SIP_DEBUG(logf("waiting for dphy master dll to lock ...\n")); - for (;;) if ((*REG32(DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT) & 0xFFFF) == 0xFFFF) break; - SIP_DEBUG(logf("dphy master dll locked!\n")); -} - -typedef struct { - uint32_t max_freq; - uint32_t RL; - uint32_t tRPab; - uint32_t tRPpb; - uint32_t tRCD; - uint32_t tWR; - uint32_t tRASmin; - uint32_t tRRD; - uint32_t tWTR; - uint32_t tXSR; - uint32_t tXP; - uint32_t tRFCab; - uint32_t tRTP; - uint32_t tCKE; - uint32_t tCKESR; - uint32_t tDQSCKMAXx2; - uint32_t tRASmax; - uint32_t tFAW; - uint32_t tRC; - uint32_t tREFI; - - uint32_t tINIT1; - uint32_t tINIT3; - uint32_t tINIT5; - - uint32_t rowbits; - uint32_t colbits; - uint32_t banklow; -} lpddr2_timings_t; - -// 7.8 / (1.0 / 400) - -lpddr2_timings_t g_InitSdramParameters = { - /* SA (us) */ - .tREFI = 3113, //Refresh rate: 3113 * (1.0 / 400) = 7.78us - /* SC (ns) */ - .tRFCab = 50, - .tRRD = 2, - .tWR = 7, - .tWTR = 4, - /* SD (ns) */ - .tRPab = 7, - .tRC = 24, - .tXP = 1, - .tRASmin = 15, - .tRPpb = 6, - .tRCD = 6, - /* SE (ns) */ - .tFAW = 18, - .tRTP = 1, - .tXSR = 54, - /* PT */ - .tINIT1 = 40, // Minimum CKE low time after completion of power ramp: 40 * (1.0 / 0.4) = 100ns - .tINIT3 = 79800, // Minimum Idle time after first CKE assertion: 79800 * (1.0 / 400) = 199.5us ~ 200us - .tINIT5 = 3990, //Max DAI: 3990* (1.0 / 400) = 9.9us ~ 10us - /* SB */ - .rowbits = 2, - .colbits = 1, - .banklow = 2 -}; - -static void reset_with_timing(lpddr2_timings_t* T) { - uint32_t ctrl = 0x4; - - *REG32(SD_CS) = (*REG32(SD_CS) & ~(SD_CS_DEL_KEEP_SET|SD_CS_DPD_SET|SD_CS_RESTRT_SET)) | SD_CS_STBY_SET; - - /* wait for SDRAM controller to go down */ - SIP_DEBUG(logf("waiting for SDRAM controller to go down (%X) ...\n", *REG32(SD_CS))); - for (;;) if ((*REG32(SD_CS) & SD_CS_SDUP_SET) == 0) break; - SIP_DEBUG(logf("SDRAM controller down!\n")); - - /* disable SDRAM clock */ - clkman_update_begin(); - *REG32(CM_SDCCTL) = (*REG32(CM_SDCCTL) & ~(CM_SDCCTL_ENAB_SET|CM_SDCCTL_CTRL_SET)) | CM_PASSWORD; - clkman_update_end(); - - SIP_DEBUG(logf("SDRAM clock disabled!\n")); - - /* - * Migrate over to master PLL. - */ - - *REG32(APHY_CSR_DDR_PLL_PWRDWN) = 0; - *REG32(APHY_CSR_DDR_PLL_GLOBAL_RESET) = 0; - *REG32(APHY_CSR_DDR_PLL_POST_DIV_RESET) = 0; - - /* 400MHz */ - *REG32(APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0) = (1 << 16) | 0x53; - *REG32(APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1) = 0; - *REG32(APHY_CSR_DDR_PLL_MDIV_VALUE) = 0; - - *REG32(APHY_CSR_DDR_PLL_GLOBAL_RESET) = 1; - - SIP_DEBUG(logf("waiting for master ddr pll to lock ...\n")); - for (;;) if (*REG32(APHY_CSR_DDR_PLL_LOCK_STATUS) & (1 << 16)) break; - SIP_DEBUG(logf("master ddr pll locked!\n")); - - *REG32(APHY_CSR_DDR_PLL_POST_DIV_RESET) = 1; - - clkman_update_begin(); - *REG32(CM_SDCCTL) = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (*REG32(CM_SDCCTL) & CM_SDCCTL_CTRL_CLR); - clkman_update_end(); - - *REG32(SD_SA) = - (T->tREFI << SD_SA_RFSH_T_LSB) - | SD_SA_PGEHLDE_SET - | SD_SA_CLKSTOP_SET - | SD_SA_POWSAVE_SET - | 0x3214; - - *REG32(SD_SB) = - SD_SB_REORDER_SET - | (T->banklow << SD_SB_BANKLOW_LSB) - | SD_SB_EIGHTBANK_SET - | (T->rowbits << SD_SB_ROWBITS_LSB) - | (T->colbits << SD_SB_COLBITS_LSB); - - logf("SDRAM Addressing Mode: Bank=%d Row=%d Col=%d SB=0x%X\n", T->banklow, T->rowbits, T->colbits, *REG32(SD_SB)); - - *REG32(SD_SC) = - (T->tRFCab << SD_SC_T_RFC_LSB) - | (T->tRRD << SD_SC_T_RRD_LSB) - | (T->tWR << SD_SC_T_WR_LSB) - | (T->tWTR << SD_SC_T_WTR_LSB) - | (3 << SD_SC_WL_LSB); - - *REG32(SD_SD) = - (T->tRPab << SD_SD_T_RPab_LSB) - | (T->tRC << SD_SD_T_RC_LSB) - | (T->tXP << SD_SD_T_XP_LSB) - | (T->tRASmin << SD_SD_T_RAS_LSB) - | (T->tRPpb << SD_SD_T_RPpb_LSB) - | (T->tRCD << SD_SD_T_RCD_LSB); - - *REG32(SD_SE) = - (1 << SD_SE_RL_EN_LSB) - | (4 << SD_SE_RL_LSB) - | (T->tFAW << SD_SE_T_FAW_LSB) - | (T->tRTP << SD_SE_T_RTP_LSB) - | (T->tXSR << SD_SE_T_XSR_LSB); - - *REG32(SD_PT1) = - (T->tINIT3 << SD_PT1_T_INIT3_LSB) - | (T->tINIT1 << SD_PT1_T_INIT1_LSB); - - *REG32(SD_PT2) = - T->tINIT5 << SD_PT2_T_INIT5_LSB; - - *REG32(SD_MRT) = - 0x3 << SD_MRT_T_MRW_LSB; - - reset_phy_dll(); - - /* wait for address line pll to come back */ - SIP_DEBUG(logf("waiting for address dll to lock ...\n")); - for (;;) if (*REG32(APHY_CSR_GLBL_ADR_DLL_LOCK_STAT) == 3) break; - SIP_DEBUG(logf("address dll locked!\n")); - - /* tell sdc we're done messing with address lines */ - *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; - - /* woo, turn on sdram! */ - *REG32(SD_CS) = - (((4 << SD_CS_ASHDN_T_LSB) - | SD_CS_STATEN_SET - | SD_CS_EN_SET) - & ~(SD_CS_STOP_SET|SD_CS_STBY_SET)) | SD_CS_RESTRT_SET; -} - -static unsigned int read_mr(unsigned int addr) { - while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} - *REG32(SD_MR) = addr & 0xFF; - unsigned int mrr; - while (((mrr = *REG32(SD_MR)) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} - return mrr; -} - -static unsigned int write_mr(unsigned int addr, unsigned int data, bool wait) { - while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} - - *REG32(SD_MR) = (addr & 0xFF) | ((data & 0xFF) << 8) | SD_MR_RW_SET; - - if (wait) { - unsigned int mrr; - while (((mrr = *REG32(SD_MR)) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} - - if (mrr & SD_MR_TIMEOUT_SET) - panic("MR write timed out (addr=%d data=0x%X)", addr, data); - - return mrr; - } else { - return 0; - } -} - -static void reset_phy(void) { - logf("%s: resetting SDRAM PHY ...\n", __FUNCTION__); - - /* reset PHYC */ - *REG32(SD_PHYC) = SD_PHYC_PHYRST_SET; - udelay(64); - *REG32(SD_PHYC) = 0; - - logf("%s: resetting DPHY CTRL ...\n", __FUNCTION__); - - *REG32(DPHY_CSR_DQ_PHY_MISC_CTRL) = 0x7; - *REG32(DPHY_CSR_DQ_PAD_MISC_CTRL) = 0x0; - *REG32(DPHY_CSR_BOOT_READ_DQS_GATE_CTRL) = 0x11; - - reset_phy_dll(); - - *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; -} - -static void switch_to_cprman_clock(unsigned int source, unsigned int div) { - *REG32(CM_SDCDIV) = CM_PASSWORD | (div << CM_SDCDIV_DIV_LSB); - *REG32(CM_SDCCTL) = CM_PASSWORD | (*REG32(CM_SDCCTL) & CM_SDCCTL_SRC_CLR) | source; - *REG32(CM_SDCCTL) |= CM_PASSWORD | CM_SDCCTL_ENAB_SET; - - logf("switching sdram to cprman clock (src=%d, div=%d), waiting for busy (0x%X) ...\n", source, div, *REG32(CM_SDCCTL)); - - for (;;) if (*REG32(CM_SDCCTL) & CM_SDCCTL_BUSY_SET) break; - - logf("busy set, switch complete!\n"); -} - -static void init_clkman(void) { - uint32_t ctrl = 0; - - clkman_update_begin(); - *REG32(CM_SDCCTL) = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (*REG32(CM_SDCCTL) & CM_SDCCTL_CTRL_CLR); - clkman_update_end(); -} - -#define CALL_INIT_CLKMAN init_clkman(); - - -/***************************************************************************** - * Calibration - *****************************************************************************/ - -static void calibrate_pvt_early(void) { - /* some hw revisions require different slews */ - uint32_t cpuid; - __asm__ ("version %0" : "=r"(cpuid)); - // tests for a cpuid ending in 0x___14_ - bool st = ((cpuid >> 4) & 0xFFF) == 0x14; - uint32_t dq_slew = (st ? 2 : 3); - logf("cpuid 0x%x and dq_slew %d\n", cpuid, dq_slew); - - /* i don't get it, the spec says do not use this register */ - write_mr(0xFF, 0, true); - /* RL = 6 / WL = 3 */ - write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, true); - - *REG32(APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL) = 0x333; - *REG32(DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL) = (dq_slew << 8) | (dq_slew << 4) | 3; - - logf("DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = 0x%X\n", *REG32(DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL)); - - /* tell sdc we want to calibrate */ - *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = BIST_pvt; - - /* pvt compensation */ - *REG32(APHY_CSR_ADDR_PVT_COMP_CTRL) = PVT_calibrate_request; - logf("waiting for address PVT calibration ...\n"); - for (;;) if (*REG32(APHY_CSR_ADDR_PVT_COMP_STATUS) & 2) break; - - *REG32(DPHY_CSR_DQ_PVT_COMP_CTRL) = PVT_calibrate_request; - logf("waiting for data PVT calibration ...\n"); - for (;;) if (*REG32(DPHY_CSR_DQ_PVT_COMP_STATUS) & 2) break; - - /* tell sdc we're done calibrating */ - *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; - - /* send calibration command */ - uint32_t old_mrt = *REG32(SD_MRT); - *REG32(SD_MRT) = 20; - logf("waiting for SDRAM calibration command ...\n"); - *REG32(SD_MR) = LPDDR2_MR_CALIBRATION | (0xFF << 8) | SD_MR_RW_SET | SD_MR_HI_Z_SET; - while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} - *REG32(SD_MRT) = old_mrt; - - write_mr(LPDDR2_MR_IO_CONFIG, st ? 3 : 2, false); -} - - -/***************************************************************************** - * Late init - *****************************************************************************/ - -static void init_late(void) { -} - -/***************************************************************************** - * Self-test - *****************************************************************************/ - -#define RT_BASE 0xC0000000 - -#define RT_PAT0 0xAAAAAAAA -#define RT_PAT1 0xFF00AA00 -#define RT_PAT2 0x99999999 - -#define RT_ASSERT(i_, expected) \ - if (ram[(i_)] != expected) { \ - logf("ERROR: At 0x%p, was expecting 0x%X from read, got 0x%X instead!\n", \ - &ram[(i_)], \ - expected, \ - ram[(i_)]); \ - panic("SDRAM self test failed!"); \ - } - -// tests a 16kb chunk of ram, starting at addr -static void selftest_at(uint32_t addr) { - logf("Testing region at 0x%X ...\n", addr); - - // do all acceess via the uncached alias, otherwise it would be an L2 cache hit - volatile uint32_t* ram = (volatile uint32_t*)(addr | RT_BASE); - - for (int i = 0; i < 0x1000; i += 4) { - ram[i] = RT_PAT0; - ram[i + 1] = RT_PAT1; - ram[i + 2] = RT_PAT2; - ram[i + 3] = RT_PAT0; - } - - for (int i = 0; i < 0x1000; i += 4) { - RT_ASSERT(i, RT_PAT0); - RT_ASSERT(i + 1, RT_PAT1); - RT_ASSERT(i + 2, RT_PAT2); - RT_ASSERT(i + 3, RT_PAT0); - } -} - -static void selftest(void) { - logf("Starting self test ...\n"); - - switch (g_RAMSize) { - case kRamSize1GB: - selftest_at(0x3FF00000); // 1023mb - selftest_at(0x2FF00000); // 767mb - case kRamSize512MB: - selftest_at(0x1FF00000); // 511mb - case kRamSize256MB: - selftest_at(0xFF00000); // 255mb - default: - selftest_at(0x0); - } - - logf("Self test successful!\n"); -} - -#undef RT_ASSERT - -void sdram_init() { - uint32_t vendor_id, bc; - - logf("(0) SD_CS = 0x%X\n", *REG32(SD_CS)); - - *REG32(PM_SMPS) = PM_PASSWORD | 0x1; - *REG32(A2W_SMPS_LDO1) = A2W_PASSWORD | 0x40000; - *REG32(A2W_SMPS_LDO0) = A2W_PASSWORD | 0x0; - - *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_DDREN_SET; - - /* - * STEP 1: - * configure the low-frequency PLL and enable SDC and perform - * the calibration sequence. - */ - - switch_to_cprman_clock(CM_SRC_OSC, 1); - - CALL_INIT_CLKMAN; - - reset_phy(); - - /* magic values */ - *REG32(SD_SA) = 0x006E3395; - *REG32(SD_SB) = 0x0F9; - *REG32(SD_SC) = 0x6000431; - *REG32(SD_SD) = 0x10000011; - *REG32(SD_SE) = 0x10106000; - *REG32(SD_PT1) = 0x0AF002; - *REG32(SD_PT2) = 0x8C; - *REG32(SD_MRT) = 0x3; - *REG32(SD_CS) = 0x200042; - - /* wait for SDRAM controller */ - logf("waiting for SDUP (%X) ...\n", *REG32(SD_CS)); - for (;;) if (*REG32(SD_CS) & SD_CS_SDUP_SET) break; - logf("SDRAM controller has arrived! (%X)\n", *REG32(SD_CS)); - - /* RL = 6 / WL = 3 */ - write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, false); - calibrate_pvt_early(); - - /* identify installed memory */ - vendor_id = read_mr(LPDDR2_MR_MANUFACTURER_ID); - if (!MR_REQUEST_SUCCESS(vendor_id)) { - panic("vendor id memory register read timed out"); - } - vendor_id = MR_GET_RDATA(vendor_id); - - bc = read_mr(LPDDR2_MR_METRICS); - if (!MR_REQUEST_SUCCESS(bc)) { - panic("basic configuration memory register read timed out"); - } - bc = MR_GET_RDATA(bc); - - g_RAMSize = lpddr2_size(bc); - - logf("SDRAM Type: %s %s LPDDR2 (BC=0x%X)\n", - lpddr2_manufacturer_name(vendor_id), - size_to_string[g_RAMSize], - bc); - - if (g_RAMSize == kRamSizeUnknown) - panic("unknown ram size (MR8 response was 0x%X)", bc); - - /* - * STEP 2: - * after calibration, enable high-freq SDRAM PLL. because we're - * running from cache, we can freely mess with SDRAM clock without - * any issues, removing the need to copy the SDRAM late init stuff - * to bootrom ram. if later code that's running from SDRAM wants to - * mess with SDRAM clock it would need to do that. - */ - - if (g_RAMSize == kRamSize1GB) { - g_InitSdramParameters.colbits = 3; - g_InitSdramParameters.rowbits = 3; - g_InitSdramParameters.banklow = 3; - } else if (g_RAMSize == kRamSize512MB) { - g_InitSdramParameters.colbits = 2; - } - - reset_with_timing(&g_InitSdramParameters); - init_late(); - selftest(); -} +/*============================================================================= +Copyright (C) 2016-2017 Authors of rpi-open-firmware +Copyright (C) 2016 Julian Brown +All rights reserved. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +FILE DESCRIPTION +VideoCoreIV SDRAM initialization code. + +=============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ddr2.h" + +#define ALWAYS_INLINE __attribute__((always_inline)) inline + +const char* size_to_string[] = { + "1GB", + "512MB", + "256MB", + "128MB", + "2GB", + "4GB", + "UNKNOWN" +}; + +enum RamSize g_RAMSize = kRamSizeUnknown; + +/* + Registers + ========= + + SC: AC Timing (Page 202) + SB: ??? + SD: AC Timing (Page 202) + SE: AC Timing (Page 202) + + PT1: + Minimum Idle time after first CKE assertion + Minimum CKE low time after completion of power ramp + PT2: + DAI Duration + */ + +#define MR_REQUEST_SUCCESS(x) ((SD_MR_TIMEOUT_SET & x) != SD_MR_TIMEOUT_SET) +#define MR_GET_RDATA(x) ((x & SD_MR_RDATA_SET) >> SD_MR_RDATA_LSB) + +#define SIP_DEBUG(x) x +#define SCLKU_DEBUG(x) //SIP_DEBUG(x) + +#define BIST_pvt 0x20 +#define BIST_reset 0x10 + +#define PVT_calibrate_request 0x1 + +#define logf(fmt, ...) print_timestamp(); printf("[SDRAM:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); + +static const char* lpddr2_manufacturer_name(uint32_t mr) { + switch (mr) { + case 1: + return "Samsung"; + case 2: + return "Qimonda"; + case 3: + return "Elpida"; + case 4: + return "Etron"; + case 5: + return "Nanya"; + case 6: + return "Hynix"; + default: + return "Unknown"; + } +} + +#define MR8_DENSITY_SHIFT 0x2 +#define MR8_DENSITY_MASK (0xF << 0x2) + +static enum RamSize lpddr2_size(uint32_t mr) { + switch (mr) { + case 0x58: + return kRamSize1GB; + case 0x18: + return kRamSize512MB; + case 0x14: + return kRamSize256MB; + case 0x10: + return kRamSize128MB; + default: + return kRamSizeUnknown; + } +} + +/***************************************************************************** + * Guts + *****************************************************************************/ + +ALWAYS_INLINE inline void clkman_update_begin(void) { + *REG32(CM_SDCCTL) |= CM_PASSWORD | CM_SDCCTL_UPDATE_SET; + SCLKU_DEBUG(logf("waiting for ACCPT (%X) ...\n", *REG32(CM_SDCCTL))); + for (;;) if (*REG32(CM_SDCCTL) & CM_SDCCTL_ACCPT_SET) break; + SCLKU_DEBUG(logf("ACCPT received! (%X)\n", *REG32(CM_SDCCTL))); +} + +ALWAYS_INLINE inline void clkman_update_end(void) { + *REG32(CM_SDCCTL) = CM_PASSWORD | (*REG32(CM_SDCCTL) & CM_SDCCTL_UPDATE_CLR); + SCLKU_DEBUG(logf("waiting for ACCPT clear (%X) ...\n", *REG32(CM_SDCCTL))); + for (;;) if ((*REG32(CM_SDCCTL) & CM_SDCCTL_ACCPT_SET) == 0) break; + SCLKU_DEBUG(logf("ACCPT cleared! (%X)\n", *REG32(CM_SDCCTL))); +} + +ALWAYS_INLINE void reset_phy_dll(void) { + SIP_DEBUG(logf("resetting aphy and dphy dlls ...\n")); + + /* politely tell sdc that we'll be messing with address lines */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x30; + + *REG32(DPHY_CSR_GLBL_DQ_DLL_RESET) = 0x1; + *REG32(APHY_CSR_GLBL_ADDR_DLL_RESET) = 0x1; + + /* stall ... */ + *REG32(SD_CS); + *REG32(SD_CS); + *REG32(SD_CS); + *REG32(SD_CS); + + *REG32(DPHY_CSR_GLBL_DQ_DLL_RESET) = 0x0; + *REG32(APHY_CSR_GLBL_ADDR_DLL_RESET) = 0x0; + + SIP_DEBUG(logf("waiting for dphy master dll to lock ...\n")); + for (;;) if ((*REG32(DPHY_CSR_GLBL_MSTR_DLL_LOCK_STAT) & 0xFFFF) == 0xFFFF) break; + SIP_DEBUG(logf("dphy master dll locked!\n")); +} + +typedef struct { + uint32_t max_freq; + uint32_t RL; + uint32_t tRPab; + uint32_t tRPpb; + uint32_t tRCD; + uint32_t tWR; + uint32_t tRASmin; + uint32_t tRRD; + uint32_t tWTR; + uint32_t tXSR; + uint32_t tXP; + uint32_t tRFCab; + uint32_t tRTP; + uint32_t tCKE; + uint32_t tCKESR; + uint32_t tDQSCKMAXx2; + uint32_t tRASmax; + uint32_t tFAW; + uint32_t tRC; + uint32_t tREFI; + + uint32_t tINIT1; + uint32_t tINIT3; + uint32_t tINIT5; + + uint32_t rowbits; + uint32_t colbits; + uint32_t banklow; +} lpddr2_timings_t; + +// 7.8 / (1.0 / 400) + +lpddr2_timings_t g_InitSdramParameters = { + /* SA (us) */ + .tREFI = 3113, //Refresh rate: 3113 * (1.0 / 400) = 7.78us + /* SC (ns) */ + .tRFCab = 50, + .tRRD = 2, + .tWR = 7, + .tWTR = 4, + /* SD (ns) */ + .tRPab = 7, + .tRC = 24, + .tXP = 1, + .tRASmin = 15, + .tRPpb = 6, + .tRCD = 6, + /* SE (ns) */ + .tFAW = 18, + .tRTP = 1, + .tXSR = 54, + /* PT */ + .tINIT1 = 40, // Minimum CKE low time after completion of power ramp: 40 * (1.0 / 0.4) = 100ns + .tINIT3 = 79800, // Minimum Idle time after first CKE assertion: 79800 * (1.0 / 400) = 199.5us ~ 200us + .tINIT5 = 3990, //Max DAI: 3990* (1.0 / 400) = 9.9us ~ 10us + /* SB */ + .rowbits = 2, + .colbits = 1, + .banklow = 2 +}; + +static void reset_with_timing(lpddr2_timings_t* T) { + uint32_t ctrl = 0x4; + + *REG32(SD_CS) = (*REG32(SD_CS) & ~(SD_CS_DEL_KEEP_SET|SD_CS_DPD_SET|SD_CS_RESTRT_SET)) | SD_CS_STBY_SET; + + /* wait for SDRAM controller to go down */ + SIP_DEBUG(logf("waiting for SDRAM controller to go down (%X) ...\n", *REG32(SD_CS))); + for (;;) if ((*REG32(SD_CS) & SD_CS_SDUP_SET) == 0) break; + SIP_DEBUG(logf("SDRAM controller down!\n")); + + /* disable SDRAM clock */ + clkman_update_begin(); + *REG32(CM_SDCCTL) = (*REG32(CM_SDCCTL) & ~(CM_SDCCTL_ENAB_SET|CM_SDCCTL_CTRL_SET)) | CM_PASSWORD; + clkman_update_end(); + + SIP_DEBUG(logf("SDRAM clock disabled!\n")); + + /* + * Migrate over to master PLL. + */ + + *REG32(APHY_CSR_DDR_PLL_PWRDWN) = 0; + *REG32(APHY_CSR_DDR_PLL_GLOBAL_RESET) = 0; + *REG32(APHY_CSR_DDR_PLL_POST_DIV_RESET) = 0; + + /* 400MHz */ + *REG32(APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL0) = (1 << 16) | 0x53; + *REG32(APHY_CSR_DDR_PLL_VCO_FREQ_CNTRL1) = 0; + *REG32(APHY_CSR_DDR_PLL_MDIV_VALUE) = 0; + + *REG32(APHY_CSR_DDR_PLL_GLOBAL_RESET) = 1; + + SIP_DEBUG(logf("waiting for master ddr pll to lock ...\n")); + for (;;) if (*REG32(APHY_CSR_DDR_PLL_LOCK_STATUS) & (1 << 16)) break; + SIP_DEBUG(logf("master ddr pll locked!\n")); + + *REG32(APHY_CSR_DDR_PLL_POST_DIV_RESET) = 1; + + clkman_update_begin(); + *REG32(CM_SDCCTL) = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (*REG32(CM_SDCCTL) & CM_SDCCTL_CTRL_CLR); + clkman_update_end(); + + *REG32(SD_SA) = + (T->tREFI << SD_SA_RFSH_T_LSB) + | SD_SA_PGEHLDE_SET + | SD_SA_CLKSTOP_SET + | SD_SA_POWSAVE_SET + | 0x3214; + + *REG32(SD_SB) = + SD_SB_REORDER_SET + | (T->banklow << SD_SB_BANKLOW_LSB) + | SD_SB_EIGHTBANK_SET + | (T->rowbits << SD_SB_ROWBITS_LSB) + | (T->colbits << SD_SB_COLBITS_LSB); + + logf("SDRAM Addressing Mode: Bank=%d Row=%d Col=%d SB=0x%X\n", T->banklow, T->rowbits, T->colbits, *REG32(SD_SB)); + + *REG32(SD_SC) = + (T->tRFCab << SD_SC_T_RFC_LSB) + | (T->tRRD << SD_SC_T_RRD_LSB) + | (T->tWR << SD_SC_T_WR_LSB) + | (T->tWTR << SD_SC_T_WTR_LSB) + | (3 << SD_SC_WL_LSB); + + *REG32(SD_SD) = + (T->tRPab << SD_SD_T_RPab_LSB) + | (T->tRC << SD_SD_T_RC_LSB) + | (T->tXP << SD_SD_T_XP_LSB) + | (T->tRASmin << SD_SD_T_RAS_LSB) + | (T->tRPpb << SD_SD_T_RPpb_LSB) + | (T->tRCD << SD_SD_T_RCD_LSB); + + *REG32(SD_SE) = + (1 << SD_SE_RL_EN_LSB) + | (4 << SD_SE_RL_LSB) + | (T->tFAW << SD_SE_T_FAW_LSB) + | (T->tRTP << SD_SE_T_RTP_LSB) + | (T->tXSR << SD_SE_T_XSR_LSB); + + *REG32(SD_PT1) = + (T->tINIT3 << SD_PT1_T_INIT3_LSB) + | (T->tINIT1 << SD_PT1_T_INIT1_LSB); + + *REG32(SD_PT2) = + T->tINIT5 << SD_PT2_T_INIT5_LSB; + + *REG32(SD_MRT) = + 0x3 << SD_MRT_T_MRW_LSB; + + reset_phy_dll(); + + /* wait for address line pll to come back */ + SIP_DEBUG(logf("waiting for address dll to lock ...\n")); + for (;;) if (*REG32(APHY_CSR_GLBL_ADR_DLL_LOCK_STAT) == 3) break; + SIP_DEBUG(logf("address dll locked!\n")); + + /* tell sdc we're done messing with address lines */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; + + /* woo, turn on sdram! */ + *REG32(SD_CS) = + (((4 << SD_CS_ASHDN_T_LSB) + | SD_CS_STATEN_SET + | SD_CS_EN_SET) + & ~(SD_CS_STOP_SET|SD_CS_STBY_SET)) | SD_CS_RESTRT_SET; +} + +static unsigned int read_mr(unsigned int addr) { + while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + *REG32(SD_MR) = addr & 0xFF; + unsigned int mrr; + while (((mrr = *REG32(SD_MR)) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + return mrr; +} + +static unsigned int write_mr(unsigned int addr, unsigned int data, bool wait) { + while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + + *REG32(SD_MR) = (addr & 0xFF) | ((data & 0xFF) << 8) | SD_MR_RW_SET; + + if (wait) { + unsigned int mrr; + while (((mrr = *REG32(SD_MR)) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + + if (mrr & SD_MR_TIMEOUT_SET) + panic("MR write timed out (addr=%d data=0x%X)", addr, data); + + return mrr; + } else { + return 0; + } +} + +static void reset_phy(void) { + logf("%s: resetting SDRAM PHY ...\n", __FUNCTION__); + + /* reset PHYC */ + *REG32(SD_PHYC) = SD_PHYC_PHYRST_SET; + udelay(64); + *REG32(SD_PHYC) = 0; + + logf("%s: resetting DPHY CTRL ...\n", __FUNCTION__); + + *REG32(DPHY_CSR_DQ_PHY_MISC_CTRL) = 0x7; + *REG32(DPHY_CSR_DQ_PAD_MISC_CTRL) = 0x0; + *REG32(DPHY_CSR_BOOT_READ_DQS_GATE_CTRL) = 0x11; + + reset_phy_dll(); + + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; +} + +static void switch_to_cprman_clock(unsigned int source, unsigned int div) { + *REG32(CM_SDCDIV) = CM_PASSWORD | (div << CM_SDCDIV_DIV_LSB); + *REG32(CM_SDCCTL) = CM_PASSWORD | (*REG32(CM_SDCCTL) & CM_SDCCTL_SRC_CLR) | source; + *REG32(CM_SDCCTL) |= CM_PASSWORD | CM_SDCCTL_ENAB_SET; + + logf("switching sdram to cprman clock (src=%d, div=%d), waiting for busy (0x%X) ...\n", source, div, *REG32(CM_SDCCTL)); + + for (;;) if (*REG32(CM_SDCCTL) & CM_SDCCTL_BUSY_SET) break; + + logf("busy set, switch complete!\n"); +} + +static void init_clkman(void) { + uint32_t ctrl = 0; + + clkman_update_begin(); + *REG32(CM_SDCCTL) = CM_PASSWORD | (ctrl << CM_SDCCTL_CTRL_LSB) | (*REG32(CM_SDCCTL) & CM_SDCCTL_CTRL_CLR); + clkman_update_end(); +} + +#define CALL_INIT_CLKMAN init_clkman(); + + +/***************************************************************************** + * Calibration + *****************************************************************************/ + +static void calibrate_pvt_early(void) { + /* some hw revisions require different slews */ + uint32_t cpuid; + __asm__ ("version %0" : "=r"(cpuid)); + // tests for a cpuid ending in 0x___14_ + bool st = ((cpuid >> 4) & 0xFFF) == 0x14; + uint32_t dq_slew = (st ? 2 : 3); + logf("cpuid 0x%x and dq_slew %d\n", cpuid, dq_slew); + + /* i don't get it, the spec says do not use this register */ + write_mr(0xFF, 0, true); + /* RL = 6 / WL = 3 */ + write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, true); + + *REG32(APHY_CSR_ADDR_PAD_DRV_SLEW_CTRL) = 0x333; + *REG32(DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL) = (dq_slew << 8) | (dq_slew << 4) | 3; + + logf("DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL = 0x%X\n", *REG32(DPHY_CSR_DQ_PAD_DRV_SLEW_CTRL)); + + /* tell sdc we want to calibrate */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = BIST_pvt; + + /* pvt compensation */ + *REG32(APHY_CSR_ADDR_PVT_COMP_CTRL) = PVT_calibrate_request; + logf("waiting for address PVT calibration ...\n"); + for (;;) if (*REG32(APHY_CSR_ADDR_PVT_COMP_STATUS) & 2) break; + + *REG32(DPHY_CSR_DQ_PVT_COMP_CTRL) = PVT_calibrate_request; + logf("waiting for data PVT calibration ...\n"); + for (;;) if (*REG32(DPHY_CSR_DQ_PVT_COMP_STATUS) & 2) break; + + /* tell sdc we're done calibrating */ + *REG32(APHY_CSR_PHY_BIST_CNTRL_SPR) = 0x0; + + /* send calibration command */ + uint32_t old_mrt = *REG32(SD_MRT); + *REG32(SD_MRT) = 20; + logf("waiting for SDRAM calibration command ...\n"); + *REG32(SD_MR) = LPDDR2_MR_CALIBRATION | (0xFF << 8) | SD_MR_RW_SET | SD_MR_HI_Z_SET; + while ((*REG32(SD_MR) & SD_MR_DONE_SET) != SD_MR_DONE_SET) {} + *REG32(SD_MRT) = old_mrt; + + write_mr(LPDDR2_MR_IO_CONFIG, st ? 3 : 2, false); +} + + +/***************************************************************************** + * Late init + *****************************************************************************/ + +static void init_late(void) { +} + +/***************************************************************************** + * Self-test + *****************************************************************************/ + +#define RT_BASE 0xC0000000 + +#define RT_PAT0 0xAAAAAAAA +#define RT_PAT1 0xFF00AA00 +#define RT_PAT2 0x99999999 + +#define RT_ASSERT(i_, expected) \ + if (ram[(i_)] != expected) { \ + logf("ERROR: At 0x%p, was expecting 0x%X from read, got 0x%X instead!\n", \ + &ram[(i_)], \ + expected, \ + ram[(i_)]); \ + panic("SDRAM self test failed!"); \ + } + +// tests a 16kb chunk of ram, starting at addr +static void selftest_at(uint32_t addr) { + logf("Testing region at 0x%X ...\n", addr); + + // do all acceess via the uncached alias, otherwise it would be an L2 cache hit + volatile uint32_t* ram = (volatile uint32_t*)(addr | RT_BASE); + + for (int i = 0; i < 0x1000; i += 4) { + ram[i] = RT_PAT0; + ram[i + 1] = RT_PAT1; + ram[i + 2] = RT_PAT2; + ram[i + 3] = RT_PAT0; + } + + for (int i = 0; i < 0x1000; i += 4) { + RT_ASSERT(i, RT_PAT0); + RT_ASSERT(i + 1, RT_PAT1); + RT_ASSERT(i + 2, RT_PAT2); + RT_ASSERT(i + 3, RT_PAT0); + } +} + +static void selftest(void) { + logf("Starting self test ...\n"); + + switch (g_RAMSize) { + case kRamSize1GB: + selftest_at(0x3FF00000); // 1023mb + selftest_at(0x2FF00000); // 767mb + case kRamSize512MB: + selftest_at(0x1FF00000); // 511mb + case kRamSize256MB: + selftest_at(0xFF00000); // 255mb + default: + selftest_at(0x0); + } + + logf("Self test successful!\n"); +} + +#undef RT_ASSERT + +void sdram_init() { + uint32_t vendor_id, bc; + + logf("(0) SD_CS = 0x%X\n", *REG32(SD_CS)); + + *REG32(PM_SMPS) = PM_PASSWORD | 0x1; + *REG32(A2W_SMPS_LDO1) = A2W_PASSWORD | 0x40000; + *REG32(A2W_SMPS_LDO0) = A2W_PASSWORD | 0x0; + + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_DDREN_SET; + + /* + * STEP 1: + * configure the low-frequency PLL and enable SDC and perform + * the calibration sequence. + */ + + switch_to_cprman_clock(CM_SRC_OSC, 1); + + CALL_INIT_CLKMAN; + + reset_phy(); + + /* magic values */ + *REG32(SD_SA) = 0x006E3395; + *REG32(SD_SB) = 0x0F9; + *REG32(SD_SC) = 0x6000431; + *REG32(SD_SD) = 0x10000011; + *REG32(SD_SE) = 0x10106000; + *REG32(SD_PT1) = 0x0AF002; + *REG32(SD_PT2) = 0x8C; + *REG32(SD_MRT) = 0x3; + *REG32(SD_CS) = 0x200042; + + /* wait for SDRAM controller */ + logf("waiting for SDUP (%X) ...\n", *REG32(SD_CS)); + for (;;) if (*REG32(SD_CS) & SD_CS_SDUP_SET) break; + logf("SDRAM controller has arrived! (%X)\n", *REG32(SD_CS)); + + /* RL = 6 / WL = 3 */ + write_mr(LPDDR2_MR_DEVICE_FEATURE_2, 4, false); + calibrate_pvt_early(); + + /* identify installed memory */ + vendor_id = read_mr(LPDDR2_MR_MANUFACTURER_ID); + if (!MR_REQUEST_SUCCESS(vendor_id)) { + panic("vendor id memory register read timed out"); + } + vendor_id = MR_GET_RDATA(vendor_id); + + bc = read_mr(LPDDR2_MR_METRICS); + if (!MR_REQUEST_SUCCESS(bc)) { + panic("basic configuration memory register read timed out"); + } + bc = MR_GET_RDATA(bc); + + g_RAMSize = lpddr2_size(bc); + + logf("SDRAM Type: %s %s LPDDR2 (BC=0x%X)\n", + lpddr2_manufacturer_name(vendor_id), + size_to_string[g_RAMSize], + bc); + + if (g_RAMSize == kRamSizeUnknown) + panic("unknown ram size (MR8 response was 0x%X)", bc); + + /* + * STEP 2: + * after calibration, enable high-freq SDRAM PLL. because we're + * running from cache, we can freely mess with SDRAM clock without + * any issues, removing the need to copy the SDRAM late init stuff + * to bootrom ram. if later code that's running from SDRAM wants to + * mess with SDRAM clock it would need to do that. + */ + + if (g_RAMSize == kRamSize1GB) { + g_InitSdramParameters.colbits = 3; + g_InitSdramParameters.rowbits = 3; + g_InitSdramParameters.banklow = 3; + } else if (g_RAMSize == kRamSize512MB) { + g_InitSdramParameters.colbits = 2; + } + + reset_with_timing(&g_InitSdramParameters); + init_late(); + selftest(); +} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 181dcca410..82157b184b 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -23,6 +23,7 @@ endif ifeq ($(ARCH),arm) +MEMBASE := 0x00000000 MODULE_DEPS += \ dev/timer/arm_generic \ lib/cbuf @@ -34,8 +35,12 @@ LINKER_SCRIPT += \ $(BUILDDIR)/system-onesegment.ld else # VPU ifeq ($(BOOTCODE),1) + MEMBASE := 0x80000000 # in the 8 alias + MEMSIZE := 0x20000 # 128kb LINKER_SCRIPT += $(LOCAL_DIR)/bootcode.ld else + MEMBASE := 0xc0000000 + MEMSIZE ?= 0x01400000 # 20MB LINKER_SCRIPT += $(LOCAL_DIR)/start.ld endif endif @@ -53,7 +58,6 @@ MODULE_SRCS += \ $(LOCAL_DIR)/pll_read.c \ -MEMBASE := 0x00000000 GLOBAL_DEFINES += \ ARM_ARCH_WAIT_FOR_SECONDARIES=1 @@ -89,8 +93,6 @@ MODULE_DEPS += \ app/tests \ lib/fdt else ifeq ($(TARGET),rpi3-vpu) - MEMSIZE := 0x20000 # 128kb - MEMBASE := 0x80000000 # in the 8 alias GLOBAL_DEFINES += \ MEMSIZE=$(MEMSIZE) \ MEMBASE=$(MEMBASE) \ @@ -101,10 +103,13 @@ else ifeq ($(TARGET),rpi3-vpu) MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ $(LOCAL_DIR)/udelay.c \ + $(LOCAL_DIR)/sdhost_impl.cpp \ + $(LOCAL_DIR)/print_timestamp.c \ + + MODULES += \ + lib/bio \ else ifeq ($(TARGET),rpi4-vpu) -MEMSIZE ?= 0x01400000 # 20MB -MEMBASE := 0xc0000000 GLOBAL_DEFINES += \ BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ MEMSIZE=$(MEMSIZE) \ diff --git a/platform/bcm28xx/sd_proto.hpp b/platform/bcm28xx/sd_proto.hpp new file mode 100644 index 0000000000..ac43cef5c8 --- /dev/null +++ b/platform/bcm28xx/sd_proto.hpp @@ -0,0 +1,370 @@ +/* $NetBSD: sdmmcreg.h,v 1.21 2015/10/29 22:37:15 jmcneill Exp $ */ +/* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */ + +/* + * Copyright (c) 2006 Uwe Stuehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#pragma once + +#include + +/* MMC commands */ /* response type */ +#define MMC_GO_IDLE_STATE 0 /* R0 */ +#define MMC_SEND_OP_COND 1 /* R3 */ +#define MMC_ALL_SEND_CID 2 /* R2 */ +#define MMC_SET_RELATIVE_ADDR 3 /* R1 */ +#define MMC_SWITCH 6 /* R1b */ +#define MMC_SELECT_CARD 7 /* R1 */ +#define MMC_SEND_EXT_CSD 8 /* R1 */ +#define MMC_SEND_CSD 9 /* R2 */ +#define MMC_SEND_CID 10 /* R2 */ +#define MMC_STOP_TRANSMISSION 12 /* R1b */ +#define MMC_SEND_STATUS 13 /* R1 */ +#define MMC_INACTIVE_STATE 15 /* R0 */ +#define MMC_SET_BLOCKLEN 16 /* R1 */ +#define MMC_READ_BLOCK_SINGLE 17 /* R1 */ +#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */ +#define MMC_SEND_TUNING_BLOCK 19 /* R1 */ +#define MMC_SEND_TUNING_BLOCK_HS200 21 /* R1 */ +#define MMC_SET_BLOCK_COUNT 23 /* R1 */ +#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */ +#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */ +#define MMC_PROGRAM_CSD 27 /* R1 */ +#define MMC_SET_WRITE_PROT 28 /* R1b */ +#define MMC_SET_CLR_WRITE_PROT 29 /* R1b */ +#define MMC_SET_SEND_WRITE_PROT 30 /* R1 */ +#define MMC_TAG_SECTOR_START 32 /* R1 */ +#define MMC_TAG_SECTOR_END 33 /* R1 */ +#define MMC_UNTAG_SECTOR 34 /* R1 */ +#define MMC_TAG_ERASE_GROUP_START 35 /* R1 */ +#define MMC_TAG_ERASE_GROUP_END 36 /* R1 */ +#define MMC_UNTAG_ERASE_GROUP 37 /* R1 */ +#define MMC_ERASE 38 /* R1b */ +#define MMC_LOCK_UNLOCK 42 /* R1b */ +#define MMC_APP_CMD 55 /* R1 */ +#define MMC_READ_OCR 58 /* R3 */ + +/* SD commands */ /* response type */ +#define SD_SEND_RELATIVE_ADDR 3 /* R6 */ +#define SD_SEND_SWITCH_FUNC 6 /* R1 */ +#define SD_SEND_IF_COND 8 /* R7 */ +#define SD_VOLTAGE_SWITCH 11 /* R1 */ + +/* SD application commands */ /* response type */ +#define SD_APP_SET_BUS_WIDTH 6 /* R1 */ +#define SD_APP_SD_STATUS 13 /* R1 */ +#define SD_APP_OP_COND 41 /* R3 */ +#define SD_APP_SEND_SCR 51 /* R1 */ + +/* OCR bits */ +#define MMC_OCR_MEM_READY (1U<<31)/* memory power-up status bit */ +#define MMC_OCR_HCS (1<<30) /* SD only */ +#define MMC_OCR_ACCESS_MODE_MASK (3<<29) /* MMC only */ +#define MMC_OCR_ACCESS_MODE_BYTE (0<<29) /* MMC only */ +#define MMC_OCR_ACCESS_MODE_SECTOR (2<<29) /* MMC only */ +#define MMC_OCR_S18A (1<<24) +#define MMC_OCR_3_5V_3_6V (1<<23) +#define MMC_OCR_3_4V_3_5V (1<<22) +#define MMC_OCR_3_3V_3_4V (1<<21) +#define MMC_OCR_3_2V_3_3V (1<<20) +#define MMC_OCR_3_1V_3_2V (1<<19) +#define MMC_OCR_3_0V_3_1V (1<<18) +#define MMC_OCR_2_9V_3_0V (1<<17) +#define MMC_OCR_2_8V_2_9V (1<<16) +#define MMC_OCR_2_7V_2_8V (1<<15) +#define MMC_OCR_2_6V_2_7V (1<<14) +#define MMC_OCR_2_5V_2_6V (1<<13) +#define MMC_OCR_2_4V_2_5V (1<<12) +#define MMC_OCR_2_3V_2_4V (1<<11) +#define MMC_OCR_2_2V_2_3V (1<<10) +#define MMC_OCR_2_1V_2_2V (1<<9) +#define MMC_OCR_2_0V_2_1V (1<<8) +#define MMC_OCR_1_9V_2_0V (1<<7) +#define MMC_OCR_1_8V_1_9V (1<<6) +#define MMC_OCR_1_7V_1_8V (1<<5) +#define MMC_OCR_1_6V_1_7V (1<<4) + +/* R1 response type bits */ +#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */ +#define MMC_R1_SWITCH_ERROR (1<<7) /* switch command failed */ +#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */ + +/* 48-bit response decoding (32 bits w/o CRC) */ +#define MMC_R1(resp) ((resp)[0]) +#define MMC_R3(resp) ((resp)[0]) +#define SD_R6(resp) ((resp)[0]) +#define MMC_R7(resp) ((resp)[0]) +#define MMC_SPI_R1(resp) ((resp)[0]) +#define MMC_SPI_R7(resp) ((resp)[1]) + +/* RCA argument and response */ +#define MMC_ARG_RCA(rca) ((rca) << 16) +#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16) + +/* bus width argument */ +#define SD_ARG_BUS_WIDTH_1 0 +#define SD_ARG_BUS_WIDTH_4 2 + +/* EXT_CSD fields */ +#define EXT_CSD_BUS_WIDTH 183 /* WO */ +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_REV 192 /* RO */ +#define EXT_CSD_STRUCTURE 194 /* RO */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ +#define EXT_CSD_SEC_COUNT 212 /* RO */ + +/* EXT_CSD field definitions */ +#define EXT_CSD_CMD_SET_NORMAL (1U << 0) +#define EXT_CSD_CMD_SET_SECURE (1U << 1) +#define EXT_CSD_CMD_SET_CPSECURE (1U << 2) + +/* EXT_CSD_BUS_WIDTH */ +#define EXT_CSD_BUS_WIDTH_1 0 /* 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4 1 /* 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8 2 /* 8 bit mode */ + +/* EXT_CSD_STRUCTURE */ +#define EXT_CSD_STRUCTURE_VER_1_0 0 /* CSD Version No.1.0 */ +#define EXT_CSD_STRUCTURE_VER_1_1 1 /* CSD Version No.1.1 */ +#define EXT_CSD_STRUCTURE_VER_1_2 2 /* Version 4.1-4.2-4.3 */ + +/* EXT_CSD_CARD_TYPE */ +#define EXT_CSD_CARD_TYPE_F_26M (1 << 0) +#define EXT_CSD_CARD_TYPE_F_52M (1 << 1) +#define EXT_CSD_CARD_TYPE_F_52M_1_8V (1 << 2) +#define EXT_CSD_CARD_TYPE_F_52M_1_2V (1 << 3) +#define EXT_CSD_CARD_TYPE_F_HS200_1_8V (1 << 4) +#define EXT_CSD_CARD_TYPE_F_HS200_1_2V (1 << 5) +#define EXT_CSD_CARD_TYPE_F_HS400_1_8V (1 << 6) +#define EXT_CSD_CARD_TYPE_F_HS400_1_2V (1 << 7) +#define EXT_CSD_CARD_TYPE_26M 0x01 +#define EXT_CSD_CARD_TYPE_52M 0x03 +#define EXT_CSD_CARD_TYPE_52M_V18 0x07 +#define EXT_CSD_CARD_TYPE_52M_V12 0x0b +#define EXT_CSD_CARD_TYPE_52M_V12_18 0x0f + +/* MMC_SWITCH access mode */ +#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ +#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */ +#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in value */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ + +/* SPI mode reports R1/R2(SEND_STATUS) status. */ +#define R1_SPI_IDLE (1 << 0) +#define R1_SPI_ERASE_RESET (1 << 1) +#define R1_SPI_ILLEGAL_COMMAND (1 << 2) +#define R1_SPI_COM_CRC (1 << 3) +#define R1_SPI_ERASE_SEQ (1 << 4) +#define R1_SPI_ADDRESS (1 << 5) +#define R1_SPI_PARAMETER (1 << 6) +/* R1 bit 7 is always zero */ +#define R2_SPI_CARD_LOCKED (1 << 8) +#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */ +#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP +#define R2_SPI_ERROR (1 << 10) +#define R2_SPI_CC_ERROR (1 << 11) +#define R2_SPI_CARD_ECC_ERROR (1 << 12) +#define R2_SPI_WP_VIOLATION (1 << 13) +#define R2_SPI_ERASE_PARAM (1 << 14) +#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */ +#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE + +/* MMC R2 response (CSD) */ +#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2) +#define MMC_CSD_CSDVER_1_0 0 +#define MMC_CSD_CSDVER_1_1 1 +#define MMC_CSD_CSDVER_1_2 2 /* MMC 4.1 - 4.2 - 4.3 */ +#define MMC_CSD_CSDVER_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ +#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4) +#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */ +#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */ +#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */ +#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */ +#define MMC_CSD_MMCVER_4_0 4 /* MMC 4.1 - 4.2 - 4.3 */ +#define MMC_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8) +#define MMC_CSD_TAAC_MANT(resp) MMC_RSP_BITS((resp), 115, 4) +#define MMC_CSD_TAAC_EXP(resp) MMC_RSP_BITS((resp), 112, 3) +#define MMC_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8) +#define MMC_CSD_TRAN_SPEED(resp) MMC_RSP_BITS((resp), 96, 8) +#define MMC_CSD_TRAN_SPEED_MANT(resp) MMC_RSP_BITS((resp), 99, 4) +#define MMC_CSD_TRAN_SPEED_EXP(resp) MMC_RSP_BITS((resp), 96, 3) +#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4) +#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12) +#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \ + (MMC_CSD_C_SIZE_MULT((resp))+2)) +#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3) +#define MMC_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3) +#define MMC_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4) + +/* MMC v1 R2 response (CID) */ +#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24) +#define MMC_CID_PNM_V1_CPY(resp, pnm) \ + do { \ + (pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \ + (pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \ + (pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \ + (pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \ + (pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \ + (pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \ + (pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \ + (pnm)[7] = '\0'; \ + } while (/*CONSTCOND*/0) +#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8) +#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24) +#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8) + +/* MMC v2 R2 response (CID) */ +#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8) +#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16) +#define MMC_CID_PNM_V2_CPY(resp, pnm) \ + do { \ + (pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \ + (pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \ + (pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \ + (pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \ + (pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \ + (pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \ + (pnm)[6] = '\0'; \ + } while (/*CONSTCOND*/0) +#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32) + +/* SD R2 response (CSD) */ +#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2) +#define SD_CSD_CSDVER_1_0 0 +#define SD_CSD_CSDVER_2_0 1 +#define SD_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4) +#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8) +#define SD_CSD_TAAC_EXP(resp) MMC_RSP_BITS((resp), 115, 4) +#define SD_CSD_TAAC_MANT(resp) MMC_RSP_BITS((resp), 112, 3) +#define SD_CSD_TAAC_1_5_MSEC 0x26 +#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8) +#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8) +#define SD_CSD_SPEED_MANT(resp) MMC_RSP_BITS((resp), 99, 4) +#define SD_CSD_SPEED_EXP(resp) MMC_RSP_BITS((resp), 96, 3) +#define SD_CSD_SPEED_25_MHZ 0x32 +#define SD_CSD_SPEED_50_MHZ 0x5a +#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12) +#define SD_CSD_CCC_BASIC (1 << 0) /* basic */ +#define SD_CSD_CCC_BR (1 << 2) /* block read */ +#define SD_CSD_CCC_BW (1 << 4) /* block write */ +#define SD_CSD_CCC_ERACE (1 << 5) /* erase */ +#define SD_CSD_CCC_WP (1 << 6) /* write protection */ +#define SD_CSD_CCC_LC (1 << 7) /* lock card */ +#define SD_CSD_CCC_AS (1 << 8) /*application specific*/ +#define SD_CSD_CCC_IOM (1 << 9) /* I/O mode */ +#define SD_CSD_CCC_SWITCH (1 << 10) /* switch */ +#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4) +#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1) +#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1) +#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1) +#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1) +#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12) +#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \ + (SD_CSD_C_SIZE_MULT((resp))+2)) +#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3) +#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3) +#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3) +#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3) +#define SD_CSD_VDD_RW_CURR_100mA 0x7 +#define SD_CSD_VDD_RW_CURR_80mA 0x6 +#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22) +#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10) +#define SD_CSD_V2_BL_LEN 0x9 /* 512 */ +#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3) +#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1) +#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */ +#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */ +#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1) +#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3) +#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4) +#define SD_CSD_RW_BL_LEN_2G 0xa +#define SD_CSD_RW_BL_LEN_1G 0x9 +#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1) +#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1) +#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1) +#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1) +#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1) +#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2) + +/* SD R2 response (CID) */ +#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8) +#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16) +#define SD_CID_PNM_CPY(resp, pnm) \ + do { \ + (pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \ + (pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \ + (pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \ + (pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \ + (pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \ + (pnm)[5] = '\0'; \ + } while (/*CONSTCOND*/0) +#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8) +#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32) +#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12) + +/* SCR (SD Configuration Register) */ +#define SCR_STRUCTURE(scr) MMC_RSP_BITS((scr), 60, 4) +#define SCR_STRUCTURE_VER_1_0 0 /* Version 1.0 */ +#define SCR_SD_SPEC(scr) MMC_RSP_BITS((scr), 56, 4) +#define SCR_SD_SPEC_VER_1_0 0 /* Version 1.0 and 1.01 */ +#define SCR_SD_SPEC_VER_1_10 1 /* Version 1.10 */ +#define SCR_SD_SPEC_VER_2 2 /* Version 2.00 or Version 3.0X */ +#define SCR_DATA_STAT_AFTER_ERASE(scr) MMC_RSP_BITS((scr), 55, 1) +#define SCR_SD_SECURITY(scr) MMC_RSP_BITS((scr), 52, 3) +#define SCR_SD_SECURITY_NONE 0 /* no security */ +#define SCR_SD_SECURITY_1_0 1 /* security protocol 1.0 */ +#define SCR_SD_SECURITY_1_0_2 2 /* security protocol 1.0 */ +#define SCR_SD_BUS_WIDTHS(scr) MMC_RSP_BITS((scr), 48, 4) +#define SCR_SD_BUS_WIDTHS_1BIT (1 << 0) /* 1bit (DAT0) */ +#define SCR_SD_BUS_WIDTHS_4BIT (1 << 2) /* 4bit (DAT0-3) */ +#define SCR_SD_SPEC3(scr) MMC_RSP_BITS((scr), 47, 1) +#define SCR_EX_SECURITY(scr) MMC_RSP_BITS((scr), 43, 4) +#define SCR_RESERVED(scr) MMC_RSP_BITS((scr), 34, 9) +#define SCR_CMD_SUPPORT_CMD23(scr) MMC_RSP_BITS((scr), 33, 1) +#define SCR_CMD_SUPPORT_CMD20(scr) MMC_RSP_BITS((scr), 32, 1) +#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32) + +#define MMC_RSP_BITS(resp, start, len) __bitfield((resp), (start), (len)) +static inline int +__bitfield(uint32_t *src, int start, int len) { + uint8_t *sp; + uint32_t dst, mask; + int shift, bs, bc; + + if (start < 0 || len < 0 || len > 32) + return 0; + + dst = 0; + mask = len % 32 ? UINT_MAX >> (32 - (len % 32)) : UINT_MAX; + shift = 0; + + while (len > 0) { + sp = (uint8_t *)src + start / 8; + bs = start % 8; + bc = 8 - bs; + if (bc > len) + bc = len; + dst |= (*sp >> bs) << shift; + shift += bc; + start += bc; + len -= bc; + } + + dst &= mask; + return (int)dst; +} diff --git a/platform/bcm28xx/sdhost_impl.cpp b/platform/bcm28xx/sdhost_impl.cpp new file mode 100644 index 0000000000..214296bf05 --- /dev/null +++ b/platform/bcm28xx/sdhost_impl.cpp @@ -0,0 +1,613 @@ +/*============================================================================= +Copyright (C) 2016-2017 Authors of rpi-open-firmware +All rights reserved. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +FILE DESCRIPTION +SDHOST driver. This used to be known as ALTMMC. + +=============================================================================*/ + +#include "sd_proto.hpp" +#include "block_device.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + #include +} + +#define SDEDM_WRITE_THRESHOLD_SHIFT 9 +#define SDEDM_READ_THRESHOLD_SHIFT 14 +#define SDEDM_THRESHOLD_MASK 0x1f + +#define SAFE_READ_THRESHOLD 4 +#define SAFE_WRITE_THRESHOLD 4 + +#define VOLTAGE_SUPPLY_RANGE 0x100 +#define CHECK_PATTERN 0x55 + +#define SDHSTS_BUSY_IRPT 0x400 +#define SDHSTS_BLOCK_IRPT 0x200 +#define SDHSTS_SDIO_IRPT 0x100 +#define SDHSTS_REW_TIME_OUT 0x80 +#define SDHSTS_CMD_TIME_OUT 0x40 +#define SDHSTS_CRC16_ERROR 0x20 +#define SDHSTS_CRC7_ERROR 0x10 +#define SDHSTS_FIFO_ERROR 0x08 + +#define SDEDM_FSM_MASK 0xf +#define SDEDM_FSM_IDENTMODE 0x0 +#define SDEDM_FSM_DATAMODE 0x1 +#define SDEDM_FSM_READDATA 0x2 +#define SDEDM_FSM_WRITEDATA 0x3 +#define SDEDM_FSM_READWAIT 0x4 +#define SDEDM_FSM_READCRC 0x5 +#define SDEDM_FSM_WRITECRC 0x6 +#define SDEDM_FSM_WRITEWAIT1 0x7 +#define SDEDM_FSM_POWERDOWN 0x8 +#define SDEDM_FSM_POWERUP 0x9 +#define SDEDM_FSM_WRITESTART1 0xa +#define SDEDM_FSM_WRITESTART2 0xb +#define SDEDM_FSM_GENPULSES 0xc +#define SDEDM_FSM_WRITEWAIT2 0xd +#define SDEDM_FSM_STARTPOWDOWN 0xf + +#define SDHSTS_TRANSFER_ERROR_MASK (SDHSTS_CRC7_ERROR|SDHSTS_CRC16_ERROR|SDHSTS_REW_TIME_OUT|SDHSTS_FIFO_ERROR) +#define SDHSTS_ERROR_MASK (SDHSTS_CMD_TIME_OUT|SDHSTS_TRANSFER_ERROR_MASK) + +#define logf(fmt, ...) { print_timestamp(); printf("[EMMC:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); } +#define mfence() __sync_synchronize() + +#define kIdentSafeClockRate 0x148 + +static int cmd_sdhost_init(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("sdhost_init", "initialize the sdhost driver", &cmd_sdhost_init) +STATIC_COMMAND_END(sdhost); + +struct BCM2708SDHost : BlockDevice { + bool is_sdhc; + bool is_high_capacity; + bool card_ready; + + uint32_t ocr; + uint32_t rca; + + uint32_t cid[4]; + uint32_t csd[4]; + + uint32_t capacity_bytes; + + uint32_t r[4]; + + uint32_t current_cmd; + + void set_power(bool on) { + *REG32(SH_VDD) = on ? SH_VDD_POWER_ON_SET : 0x0; + } + + bool wait(uint32_t timeout = 100000) { + uint32_t t = timeout; + + while(*REG32(SH_CMD) & SH_CMD_NEW_FLAG_SET) { + if (t == 0) { + logf("timed out after %dus!\n", timeout) + return false; + } + t--; + udelay(10); + } + + return true; + } + + bool send_raw(uint32_t command, uint32_t arg = 0) { + uint32_t sts; + + wait(); + + sts = *REG32(SH_HSTS); + if (sts & SDHSTS_ERROR_MASK) + *REG32(SH_HSTS) = sts; + + current_cmd = command & SH_CMD_COMMAND_SET; + + *REG32(SH_ARG) = arg; + *REG32(SH_CMD) = command | SH_CMD_NEW_FLAG_SET; + + mfence(); + + return true; + } + + bool send(uint32_t command, uint32_t arg = 0) { + return send_raw(command & SH_CMD_COMMAND_SET, arg); + } + + bool send_136_resp(uint32_t command, uint32_t arg = 0) { + return send_raw((command & SH_CMD_COMMAND_SET) | SH_CMD_LONG_RESPONSE_SET, arg); + } + + bool send_no_resp(uint32_t command, uint32_t arg = 0) { + return send_raw((command & SH_CMD_COMMAND_SET) | SH_CMD_NO_RESPONSE_SET, arg); + } + + void configure_pinmux() { + gpio_config(48, kBCM2708Pinmux_ALT0); + gpio_config(49, kBCM2708Pinmux_ALT0); + gpio_config(50, kBCM2708Pinmux_ALT0); + gpio_config(51, kBCM2708Pinmux_ALT0); + gpio_config(52, kBCM2708Pinmux_ALT0); + gpio_config(53, kBCM2708Pinmux_ALT0); + + struct gpio_pull_batch pullBatch; + GPIO_PULL_CLEAR(pullBatch); + GPIO_PULL_SET(pullBatch, 48, kPullUp); + GPIO_PULL_SET(pullBatch, 49, kPullUp); + GPIO_PULL_SET(pullBatch, 50, kPullUp); + GPIO_PULL_SET(pullBatch, 51, kPullUp); + GPIO_PULL_SET(pullBatch, 52, kPullUp); + GPIO_PULL_SET(pullBatch, 53, kPullUp); + gpio_apply_batch(&pullBatch); + + logf("pinmux configured for aux0\n"); + } + + void reset() { + logf("resetting controller ...\n"); + set_power(false); + + *REG32(SH_CMD) = 0; + *REG32(SH_ARG) = 0; + *REG32(SH_TOUT) = 0xF00000; + *REG32(SH_CDIV) = 0; + *REG32(SH_HSTS) = 0x7f8; + *REG32(SH_HCFG) = 0; + *REG32(SH_HBCT) = 0; + *REG32(SH_HBLC) = 0; + + uint32_t temp = *REG32(SH_EDM); + + temp &= ~((SDEDM_THRESHOLD_MASK< /dev/null ...\n", block_size, sector); + } +#endif + + /* drain junk from FIFO */ + drain_fifo(); + + /* enter READ mode */ + send_raw(MMC_READ_BLOCK_MULTIPLE | SH_CMD_READ_CMD_SET, sector); + + int i; + uint32_t hsts_err = 0; + + +#ifdef DUMP_READ + if (buf) + printf("----------------------------------------------------\n"); +#endif + + /* drain useful data from FIFO */ + for (i = 0; i < 128; i++) { + /* wait for FIFO */ + if (!wait_for_fifo_data()) { + break; + } + + uint32_t hsts_err = *REG32(SH_HSTS) & SDHSTS_ERROR_MASK; + if (hsts_err) { + logf("ERROR: transfer error on FIFO word %d: 0x%x\n", i, *REG32(SH_HSTS)); + break; + } + + + volatile uint32_t data = *REG32(SH_DATA); + +#ifdef DUMP_READ + printf("%08x ", data); +#endif + if (buf) + *(buf++) = data; + } + + send_raw(MMC_STOP_TRANSMISSION | SH_CMD_BUSY_CMD_SET); + +#ifdef DUMP_READ + printf("\n"); + if (buf) + printf("----------------------------------------------------\n"); +#endif + + if (hsts_err) { + logf("ERROR: Transfer error, status: 0x%x\n", *REG32(SH_HSTS)); + return false; + } + +#ifdef DUMP_READ + if (buf) + logf("Completed read for %d\n", sector); +#endif + return true; + } + + + + bool select_card() { + send(MMC_SELECT_CARD, MMC_ARG_RCA(rca)); + + if (!wait()) + return false; + + return true; + } + + bool init_card() { + char pnm[8]; + uint32_t block_length; + uint32_t clock_div = 0; + + send_no_resp(MMC_GO_IDLE_STATE); + + if (!query_voltage_and_type()) { + logf("ERROR: Failed to query card voltage!\n"); + return false; + } + + if (!identify_card()) { + logf("ERROR: Failed to identify card!\n"); + return false; + } + + SD_CID_PNM_CPY(cid, pnm); + + logf("Detected SD card:\n"); + printf(" Product : %s\n", pnm); + + if (SD_CSD_CSDVER(csd) == SD_CSD_CSDVER_2_0) { + printf(" CSD : Ver 2.0\n"); + printf(" Capacity: %d\n", SD_CSD_V2_CAPACITY(csd)); + printf(" Size : %d\n", SD_CSD_V2_C_SIZE(csd)); + + block_length = 1 << SD_CSD_V2_BL_LEN; + + /* work out the capacity of the card in bytes */ + capacity_bytes = (SD_CSD_V2_CAPACITY(csd) * block_length); + + clock_div = 5; + } else if (SD_CSD_CSDVER(csd) == SD_CSD_CSDVER_1_0) { + printf(" CSD : Ver 1.0\n"); + printf(" Capacity: %d\n", SD_CSD_CAPACITY(csd)); + printf(" Size : %d\n", SD_CSD_C_SIZE(csd)); + + block_length = 1 << SD_CSD_READ_BL_LEN(csd); + + /* work out the capacity of the card in bytes */ + capacity_bytes = (SD_CSD_CAPACITY(csd) * block_length); + + clock_div = 10; + } else { + printf("ERROR: Unknown CSD version 0x%x!\n", SD_CSD_CSDVER(csd)); + return false; + } + + printf(" BlockLen: 0x%x\n", block_length); + + if (!select_card()) { + logf("ERROR: Failed to select card!\n"); + return false; + } + + if (SD_CSD_CSDVER(csd) == SD_CSD_CSDVER_1_0) { + /* + * only needed for 1.0 ones, the 2.0 ones have this + * fixed at 512. + */ + logf("Setting block length to 512 ...\n"); + send(MMC_SET_BLOCKLEN, 512); + if (!wait()) { + logf("ERROR: Failed to set block length!\n"); + return false; + } + } + + block_size = 512; + + logf("Card initialization complete: %s %dMB SD%s Card\n", pnm, capacity_bytes >> 20, is_high_capacity ? "HC" : ""); + + /* + * this makes some dangerous assumptions that the all csd2 cards are sdio cards + * and all csd1 cards are sd cards and that mmc cards won't be used. this also assumes + * PLLC.CORE0 is at 250MHz which is probably a safe assumption since we set it. + */ + if (clock_div) { + logf("Identification complete, changing clock to %dMHz for data mode ...\n", 250 / clock_div); + *REG32(SH_CDIV) = clock_div - 2; + } + + return true; + } + + void restart_controller() { + is_sdhc = false; + + logf("hcfg 0x%X, cdiv 0x%X, edm 0x%X, hsts 0x%X\n", + *REG32(SH_HCFG), + *REG32(SH_CDIV), + *REG32(SH_EDM), + *REG32(SH_HSTS)); + + logf("Restarting the eMMC controller ...\n"); + + configure_pinmux(); + reset(); + + *REG32(SH_HCFG) &= ~SH_HCFG_WIDE_EXT_BUS_SET; + *REG32(SH_HCFG) = SH_HCFG_SLOW_CARD_SET | SH_HCFG_WIDE_INT_BUS_SET; + *REG32(SH_CDIV) = kIdentSafeClockRate; + + udelay(300); + mfence(); + + if (init_card()) { + card_ready = true; + + /* + * looks like a silicon bug to me or a quirk of csd2, who knows + */ + for (int i = 0; i < 3; i++) { + if (!read_block(0, nullptr)) { + panic("fifo flush cycle %d failed", i); + } + } + } else { + panic("failed to reinitialize the eMMC controller"); + } + } + + virtual void stop() override { + if (card_ready) { + logf("flushing fifo ...\n"); + drain_fifo_nowait(); + + logf("asking card to enter idle state ...\n"); + *REG32(SH_CDIV) = kIdentSafeClockRate; + udelay(150); + + send_no_resp(MMC_GO_IDLE_STATE); + udelay(500); + } + + logf("stopping sdhost controller driver ...\n"); + + *REG32(SH_CMD) = 0; + *REG32(SH_ARG) = 0; + *REG32(SH_TOUT) = 0xA00000; + *REG32(SH_CDIV) = 0x1FB; + + logf("powering down controller ...\n"); + *REG32(SH_VDD) = 0; + *REG32(SH_HCFG) = 0; + *REG32(SH_HBCT) = 0x400; + *REG32(SH_HBLC) = 0; + *REG32(SH_HSTS) = 0x7F8; + + logf("resetting state machine ...\n"); + + *REG32(SH_CMD) = 0; + *REG32(SH_ARG) = 0; + } + + BCM2708SDHost() { + restart_controller(); + logf("eMMC driver sucessfully started!\n"); + } +}; + +extern "C" { + void rpi_sdhost_init(void); +}; + +struct BCM2708SDHost *sdhost = 0; + +void rpi_sdhost_init() { + sdhost = new BCM2708SDHost; + bdev_t *bdev = new bdev_t; + auto blocksize = sdhost->get_block_size(); + auto blocks = sdhost->capacity_bytes / blocksize; + //bio_initialize_bdev(bdev, "sdhost", blocksize, blocks, 0, 0, 0); +} + +static int cmd_sdhost_init(int argc, const cmd_args *argv) { + rpi_sdhost_init(); + return 0; +} diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk index b359d1ea92..ef4c4750ff 100644 --- a/project/rpi3-bootcode.mk +++ b/project/rpi3-bootcode.mk @@ -4,12 +4,13 @@ TARGET := rpi3-vpu ARCH := vc4 MODULES += \ - app/stringtests \ - app/rpi-vpu-bootload \ - lib/cksum \ lib/debugcommands \ + app/shell \ #app/shell \ #app/tests \ + #app/stringtests \ + #app/rpi-vpu-bootload \ + #lib/cksum \ GLOBAL_DEFINES += BOOTCODE=1 diff --git a/project/rpi4-recovery.mk b/project/rpi4-recovery.mk new file mode 100644 index 0000000000..10bb692d37 --- /dev/null +++ b/project/rpi4-recovery.mk @@ -0,0 +1,11 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi4-vpu +ARCH := vc4 +BOOTCODE := 1 + +MODULES += \ + app/shell \ + lib/cksum \ + platform/bcm28xx/otp \ + lib/debugcommands \ diff --git a/project/rpi4-start4.mk b/project/rpi4-start4.mk index 06bae65486..8ae4b41e2a 100644 --- a/project/rpi4-start4.mk +++ b/project/rpi4-start4.mk @@ -5,12 +5,9 @@ ARCH := vc4 MODULES += \ app/shell \ + lib/cksum \ + platform/bcm28xx/otp \ + #lib/debugcommands \ app/stringtests \ app/tests \ - lib/cksum \ - lib/debugcommands \ - - - - From 2a56c6febf9bcfa5489ae3130836702765a86544 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sat, 22 Feb 2020 13:26:43 -0400 Subject: [PATCH 015/100] clean up unused things in linker script --- platform/bcm28xx/start.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/bcm28xx/start.ld b/platform/bcm28xx/start.ld index 5a00a8271a..59eef170c4 100644 --- a/platform/bcm28xx/start.ld +++ b/platform/bcm28xx/start.ld @@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf32-vc4", "elf32-vc4", "elf32-vc4") OUTPUT_ARCH(vc4) ENTRY(_start) -GROUP(-lgloss -lc -lteststub -lgcc) +GROUP(-lgcc) MEMORY { /* in the C alias, direct uncached From b5f15ad893ef6bb8cfa1b12774fa35c9ae6240b2 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sat, 22 Feb 2020 20:43:01 +0100 Subject: [PATCH 016/100] Re-implement OTP access This is a clean rewrite of the OTP routines using new findings. --- platform/bcm28xx/include/platform/bcm28xx.h | 12 +++ platform/bcm28xx/otp/otp.c | 73 ++++++++++++- platform/bcm28xx/otp/otp_asm.S | 112 -------------------- platform/bcm28xx/otp/rules.mk | 1 - 4 files changed, 83 insertions(+), 115 deletions(-) delete mode 100644 platform/bcm28xx/otp/otp_asm.S diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 48d5e96985..850bae461b 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -58,6 +58,7 @@ void print_timestamp(void); #define I2S_BASE (BCM_PERIPH_BASE_VIRT + 0x203000) #define SPI0_BASE (BCM_PERIPH_BASE_VIRT + 0x204000) #define BSC0_BASE (BCM_PERIPH_BASE_VIRT + 0x205000) +#define OTP_BASE (BCM_PERIPH_BASE_VIRT + 0x20f000) #define AUX_BASE (BCM_PERIPH_BASE_VIRT + 0x215000) #define MINIUART_BASE (BCM_PERIPH_BASE_VIRT + 0x215040) #define EMMC_BASE (BCM_PERIPH_BASE_VIRT + 0x300000) @@ -282,3 +283,14 @@ void print_timestamp(void); #define GPIO_2711_PULL (GPIO_BASE + 0xe4) // 2 bits per reg, 16 pins per reg, 4 regs total // 0=none, 1=up, 2=down + +#define OTP_BOOTMODE (OTP_BASE + 0x00) +#define OTP_CONFIG (OTP_BASE + 0x04) +#define OTP_CTRL_LO (OTP_BASE + 0x08) +#define OTP_CTRL_HI (OTP_BASE + 0x0c) +#define OTP_STATUS (OTP_BASE + 0x10) +#define OTP_BITSEL (OTP_BASE + 0x14) +#define OTP_DATA (OTP_BASE + 0x18) +#define OTP_ADDR (OTP_BASE + 0x1c) +#define OTP_WRITE_DATA_READ (OTP_BASE + 0x20) +#define OTP_INIT_STATUS (OTP_BASE + 0x24) diff --git a/platform/bcm28xx/otp/otp.c b/platform/bcm28xx/otp/otp.c index 01f6ff2e9e..d5fc5c4597 100644 --- a/platform/bcm28xx/otp/otp.c +++ b/platform/bcm28xx/otp/otp.c @@ -1,19 +1,88 @@ #include +#include +#include #include +#include #include #include +#define OTP_MAX_CMD_WAIT 1000 + +enum otp_command { + OTP_CMD_READ = 0, +}; + +/* OTP_CTRL_LO Bits */ +#define OTP_CMD_START 1 + +/* OTP Status Bits */ +#ifdef RPI4 +# define OTP_STAT_CMD_DONE 2 +#else +# define OTP_STAT_CMD_DONE 1 +#endif + static int cmd_otp_pretty(int argc, const cmd_args *argv); static int cmd_otp_full(int argc, const cmd_args *argv); -uint32_t otp_read_internal(uint32_t addr); STATIC_COMMAND_START STATIC_COMMAND("otp_pretty_print", "pretty-print all known otp values", &cmd_otp_pretty) STATIC_COMMAND("otp_dump_all","dump all OTP values", &cmd_otp_full) STATIC_COMMAND_END(otp); +static inline void otp_delay(void) { + udelay(1); +} + +static void otp_open(void) { + // TODO: Is this really needed? The code seems to work + // without this block, at least on BCM2711 B0 silicon. + *REG32(OTP_CONFIG) = 3; + otp_delay(); + + *REG32(OTP_CTRL_HI) = 0; + *REG32(OTP_CTRL_LO) = 0; + *REG32(OTP_ADDR) = 0; + *REG32(OTP_DATA) = 0; + *REG32(OTP_CONFIG) = 2; +} + +static void otp_close(void) { + *REG32(OTP_CTRL_HI) = 0; + *REG32(OTP_CTRL_LO) = 0; + *REG32(OTP_CONFIG) = 0; +} + +static int otp_wait_status(uint32_t mask, int retry) { + int i = retry; + do { + otp_delay(); + if (*REG32(OTP_STATUS) & mask) + return 0; + } while (--i); + return -1; +} + +static int otp_set_command(enum otp_command cmd) { + *REG32(OTP_CTRL_HI) = 0; + *REG32(OTP_CTRL_LO) = cmd << 1; + if (otp_wait_status(OTP_STAT_CMD_DONE, OTP_MAX_CMD_WAIT)) + return -1; + *REG32(OTP_CTRL_LO) = (cmd << 1) | OTP_CMD_START; + return otp_wait_status(OTP_STAT_CMD_DONE, OTP_MAX_CMD_WAIT); +} + +static uint32_t otp_read_open(uint8_t addr) { + *REG32(OTP_ADDR) = addr; + return (uint32_t) otp_set_command(OTP_CMD_READ) ?: *REG32(OTP_DATA); +} + uint32_t otp_read(uint8_t addr) { - return otp_read_internal(addr); + uint32_t val; + otp_open(); + val = otp_read_open(addr); + otp_close(); + return val; } void dump_all_otp(void) { diff --git a/platform/bcm28xx/otp/otp_asm.S b/platform/bcm28xx/otp/otp_asm.S deleted file mode 100644 index 6479797616..0000000000 --- a/platform/bcm28xx/otp/otp_asm.S +++ /dev/null @@ -1,112 +0,0 @@ -// copied from https://github.com/ptesarik/vc4boot - -A2W_BASE = 0x7e102000 -A2W_XOSC0 = 0x090 - -OTP_BASE = 0x7e20f000 -OTP_CONFIG_REG = 0x04 -OTP_CTRL_LO_REG = 0x08 -OTP_CTRL_HI_REG = 0x0c -OTP_STATUS_REG = 0x10 -OTP_DATA_REG = 0x18 -OTP_ADDR_REG = 0x1c - -#if RPI4 - OTP_READY_BIT = 1 -#else - OTP_READY_BIT = 0 -#endif - -.text -.global otp_read_internal -otp_read_internal: - stm r6-r7,lr,(--sp) - - mov r6, r0 // save arg0 in r6 - bl otp_open - mov r0, r6 - bl otp_read_reg - mov r7, r0 // set the result asside so close wont clobber - bl otp_close - mov r0, r7 - - ldm r6-r7,pc,(sp++) - -otp_open: - stm lr, (--sp) - mov r2, 0x03 - mov r1, OTP_BASE - mov r3, A2W_BASE + A2W_XOSC0 - st r2, (r1 + OTP_CONFIG_REG) // OTP_CONFIG_REG = 0x3 - - mov r0, 2 -1: - ld r2, (r3) // read A2W_XOSC0 - addcmpbge r0, -1, 0, 1b // repeat 2 times total - - mov r2, 0 - st r2, (r1 + OTP_CTRL_HI_REG) // OTP_CTRL_HI_REG = 0 - st r2, (r1 + OTP_CTRL_LO_REG) // OTP_CTRL_LO_REG = 0 - - mov r0, 2 -1: - ld r2, (r3) // read A2W_XOSC0 - addcmpbge r0, -1, 0, 1b // repeat 2 times total - - mov r2, 0x2 - st r2, (r1 + OTP_CONFIG_REG) // OTP_CONFIG_REG = 2 - ldm pc, (sp++) - -otp_read_reg: - stm lr, (--sp) - mov r1, OTP_BASE - mov r3, A2W_BASE + A2W_XOSC0 - st r0, (r1 + OTP_ADDR_REG) // OTP_ADDR_REG = arg0 - - mov r0, 2 -1: - ld r2, (r3) - addcmpbge r0, -1, 0, 1b // repeat 2 times total - - mov r2, 0 - ld r0, (r1 + OTP_ADDR_REG) // r0 = OTP_ADDR_REG - st r2, (r1 + OTP_CTRL_HI_REG) // OTP_CTRL_HI_REG = 0 - st r2, (r1 + OTP_CTRL_LO_REG) // OTP_CTRL_LO_REG = 0 - - mov r0, 2 -1: - ld r2, (r3) - addcmpbge r0, -1, 0, 1b // repeat 2 times total - - mov r2, 1 - ld r0, (r1 + OTP_CTRL_LO_REG) // read ctrl low - st r2, (r1 + OTP_CTRL_LO_REG) // ctrl low = 1 - ld r0, (r1 + OTP_CTRL_LO_REG) // read ctrl low again -1: - mov r0, 2 -2: - ld r2, (r3) - addcmpbge r0, -1, 0, 2b // repeat 2 times total - - ld r0, (r1 + OTP_STATUS_REG) // read status reg - btest r0, OTP_READY_BIT // check if its ready - beq 1b // if not ready, stall some more and try again - ld r0, (r1 + OTP_DATA_REG) // read final answer - ldm pc, (sp++) - -otp_close: - stm lr, (--sp) - mov r2, 0 - mov r1, OTP_BASE - mov r3, A2W_BASE + A2W_XOSC0 - st r2, (r1 + OTP_CTRL_HI_REG) // OTP_CTRL_HI_REG = 0 - st r2, (r1 + OTP_CTRL_LO_REG) // OTP_CTRL_LO_REG = 0 - - mov r0, 2 -1: - ld r2, (r3) - addcmpbge r0, -1, 0, 1b // repeat 2 times total - - mov r2, 0 - st r2, (r1 + OTP_CONFIG_REG) - ldm pc, (sp++) diff --git a/platform/bcm28xx/otp/rules.mk b/platform/bcm28xx/otp/rules.mk index 378fc01fd9..ba263f4e1b 100644 --- a/platform/bcm28xx/otp/rules.mk +++ b/platform/bcm28xx/otp/rules.mk @@ -4,7 +4,6 @@ MODULE := $(LOCAL_DIR) MODULE_SRCS += \ $(LOCAL_DIR)/otp.c \ - $(LOCAL_DIR)/otp_asm.S \ include make/module.mk From a92f697ad1b16794a572fc70222d9f34922a1b18 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sat, 22 Feb 2020 21:31:56 +0100 Subject: [PATCH 017/100] otp_write command Based on previous research, this commit implements a write command. Use with care! What is done cannot be undone. --- .../bcm28xx/include/platform/bcm28xx/otp.h | 10 ++ platform/bcm28xx/otp/otp.c | 92 +++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/platform/bcm28xx/include/platform/bcm28xx/otp.h b/platform/bcm28xx/include/platform/bcm28xx/otp.h index 92d0af41ce..8c3a457a3e 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/otp.h +++ b/platform/bcm28xx/include/platform/bcm28xx/otp.h @@ -2,3 +2,13 @@ uint32_t otp_read(uint8_t addr); void otp_pretty_print(void); + +#ifdef RPI4 + +#define OTP_ERR_PROGRAM -1 +#define OTP_ERR_ENABLE -2 +#define OTP_ERR_DISABLE -3 + +int otp_write(uint8_t addr, uint32_t val); + +#endif /* RPI4 */ diff --git a/platform/bcm28xx/otp/otp.c b/platform/bcm28xx/otp/otp.c index d5fc5c4597..7938afddad 100644 --- a/platform/bcm28xx/otp/otp.c +++ b/platform/bcm28xx/otp/otp.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -7,13 +8,18 @@ #include #define OTP_MAX_CMD_WAIT 1000 +#define OTP_MAX_PROG_WAIT 32000 enum otp_command { OTP_CMD_READ = 0, + OTP_CMD_PROG_ENABLE = 0x2, + OTP_CMD_PROG_DISABLE = 0x3, + OTP_CMD_PROGRAM_WORD = 0xa, }; /* OTP_CTRL_LO Bits */ #define OTP_CMD_START 1 +#define OTP_STAT_PROG_OK 4 /* OTP Status Bits */ #ifdef RPI4 @@ -22,12 +28,16 @@ enum otp_command { # define OTP_STAT_CMD_DONE 1 #endif +#define OTP_PROG_EN_SEQ { 0xf, 0x4, 0x8, 0xd }; + static int cmd_otp_pretty(int argc, const cmd_args *argv); static int cmd_otp_full(int argc, const cmd_args *argv); +static int cmd_otp_write(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("otp_pretty_print", "pretty-print all known otp values", &cmd_otp_pretty) STATIC_COMMAND("otp_dump_all","dump all OTP values", &cmd_otp_full) +STATIC_COMMAND("otp_write","write new OTP value", &cmd_otp_write) STATIC_COMMAND_END(otp); static inline void otp_delay(void) { @@ -85,6 +95,62 @@ uint32_t otp_read(uint8_t addr) { return val; } +#ifdef RPI4 + +static int otp_enable_program(void) +{ + static const uint32_t seq[] = OTP_PROG_EN_SEQ; + unsigned i; + + for (i = 0; i < countof(seq); ++i) { + *REG32(OTP_DATA) = seq[i]; + if (otp_set_command(OTP_CMD_PROG_ENABLE)) + return -1; + } + return otp_wait_status(OTP_STAT_PROG_OK, OTP_MAX_PROG_WAIT); +} + +static int otp_disable_program(void) +{ + return otp_set_command(OTP_CMD_PROG_DISABLE); +} + +static int otp_write_enabled(uint8_t addr, uint32_t newval) +{ + uint32_t oldval = otp_read_open(addr); + if (oldval == 0xffffffffL) // This check guards against read failures + return 0; + *REG32(OTP_DATA) = newval | oldval; + otp_delay(); + *REG32(OTP_ADDR) = addr; + otp_delay(); + return otp_set_command(OTP_CMD_PROGRAM_WORD); +} + +static int otp_write_open(uint8_t addr, uint32_t val) +{ + int err; + if (otp_enable_program()) + return OTP_ERR_ENABLE; + err = otp_write_enabled(addr, val); + if (err) + err = OTP_ERR_PROGRAM; + if (otp_disable_program()) + err = err ?: OTP_ERR_DISABLE; + return err; +} + +int otp_write(uint8_t addr, uint32_t val) +{ + int err; + otp_open(); + err = otp_write_open(addr, val); + otp_close(); + return err; +} + +#endif /* RPI4 */ + void dump_all_otp(void) { printf("full otp dump\n"); for (uint8_t addr=0; addr < 67; addr++) { @@ -146,3 +212,29 @@ int cmd_otp_pretty(int argc, const cmd_args *argv) { otp_pretty_print(); return 0; } + +static int cmd_otp_write(int argc, const cmd_args *argv) { + uint32_t addr, val; + if (argc != 3) { + printf("usage: otp_write 36 0x20\n"); + return -1; + } + addr = argv[1].u; + val = argv[2].u; + otp_open(); + printf("old value: 0x%08"PRIx32"\n", otp_read_open(addr)); + switch (otp_write_open(addr, val)) { + case OTP_ERR_ENABLE: + printf("cannot %s OTP programming\n", "enable"); + break; + case OTP_ERR_PROGRAM: + printf("programming command failed\n"); + break; + case OTP_ERR_DISABLE: + printf("cannot %s OTP programming\n", "disable"); + break; + } + printf("new value: 0x%08"PRIx32"\n", otp_read_open(addr)); + otp_close(); + return 0; +} From 37a056cf0abfb8a0611a4c4b589dbd266bf17b10 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sun, 23 Feb 2020 00:08:43 +0100 Subject: [PATCH 018/100] Rename OTP_STAT_PROG_OK to OTP_STAT_PROG_ENABLE This bit does not tell whether programming was OK, but whether programming is enabled. Renaming should prevent confusion when BCM283x support is added. --- platform/bcm28xx/otp/otp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/bcm28xx/otp/otp.c b/platform/bcm28xx/otp/otp.c index 7938afddad..2def8be75d 100644 --- a/platform/bcm28xx/otp/otp.c +++ b/platform/bcm28xx/otp/otp.c @@ -19,7 +19,7 @@ enum otp_command { /* OTP_CTRL_LO Bits */ #define OTP_CMD_START 1 -#define OTP_STAT_PROG_OK 4 +#define OTP_STAT_PROG_ENABLE 4 /* OTP Status Bits */ #ifdef RPI4 @@ -107,7 +107,7 @@ static int otp_enable_program(void) if (otp_set_command(OTP_CMD_PROG_ENABLE)) return -1; } - return otp_wait_status(OTP_STAT_PROG_OK, OTP_MAX_PROG_WAIT); + return otp_wait_status(OTP_STAT_PROG_ENABLE, OTP_MAX_PROG_WAIT); } static int otp_disable_program(void) From e07d1f8b93af8c1a37bc0a2643f02a9d6d8687c9 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sun, 23 Feb 2020 00:13:15 +0100 Subject: [PATCH 019/100] OTP write support for BCM283x The OTP chip in BCM283x cannot program a full word in a single command. Instead, individual bits must be programmed one by one. There is also a subtle difference in program enable. The magic sequence must be written to OTP_BITSEL, not OTP_DATA. Tested on a RPi3 B (no plus). --- .../bcm28xx/include/platform/bcm28xx/otp.h | 4 - platform/bcm28xx/otp/otp.c | 102 +++++++++++++++--- 2 files changed, 90 insertions(+), 16 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/otp.h b/platform/bcm28xx/include/platform/bcm28xx/otp.h index 8c3a457a3e..fb2d809abd 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/otp.h +++ b/platform/bcm28xx/include/platform/bcm28xx/otp.h @@ -3,12 +3,8 @@ uint32_t otp_read(uint8_t addr); void otp_pretty_print(void); -#ifdef RPI4 - #define OTP_ERR_PROGRAM -1 #define OTP_ERR_ENABLE -2 #define OTP_ERR_DISABLE -3 int otp_write(uint8_t addr, uint32_t val); - -#endif /* RPI4 */ diff --git a/platform/bcm28xx/otp/otp.c b/platform/bcm28xx/otp/otp.c index 2def8be75d..9171989ec4 100644 --- a/platform/bcm28xx/otp/otp.c +++ b/platform/bcm28xx/otp/otp.c @@ -9,17 +9,28 @@ #define OTP_MAX_CMD_WAIT 1000 #define OTP_MAX_PROG_WAIT 32000 +#define OTP_MAX_WRITE_RETRIES 16 enum otp_command { OTP_CMD_READ = 0, +#ifndef RPI4 + OTP_CMD_PROG_ENABLE = 0x1, + OTP_CMD_PROG_DISABLE = 0x2, +#else OTP_CMD_PROG_ENABLE = 0x2, OTP_CMD_PROG_DISABLE = 0x3, +#endif OTP_CMD_PROGRAM_WORD = 0xa, }; /* OTP_CTRL_LO Bits */ #define OTP_CMD_START 1 -#define OTP_STAT_PROG_ENABLE 4 +#ifndef RPI4 +# define OTP_STAT_PROG_OK 4 +# define OTP_STAT_PROG_ENABLE 0x1000 +#else +# define OTP_STAT_PROG_ENABLE 4 +#endif /* OTP Status Bits */ #ifdef RPI4 @@ -73,8 +84,8 @@ static int otp_wait_status(uint32_t mask, int retry) { return -1; } -static int otp_set_command(enum otp_command cmd) { - *REG32(OTP_CTRL_HI) = 0; +static int otp_set_command(uint32_t ctrlhi, uint32_t cmd) { + *REG32(OTP_CTRL_HI) = ctrlhi; *REG32(OTP_CTRL_LO) = cmd << 1; if (otp_wait_status(OTP_STAT_CMD_DONE, OTP_MAX_CMD_WAIT)) return -1; @@ -84,7 +95,7 @@ static int otp_set_command(enum otp_command cmd) { static uint32_t otp_read_open(uint8_t addr) { *REG32(OTP_ADDR) = addr; - return (uint32_t) otp_set_command(OTP_CMD_READ) ?: *REG32(OTP_DATA); + return (uint32_t) otp_set_command(0, OTP_CMD_READ) ?: *REG32(OTP_DATA); } uint32_t otp_read(uint8_t addr) { @@ -95,16 +106,18 @@ uint32_t otp_read(uint8_t addr) { return val; } -#ifdef RPI4 - static int otp_enable_program(void) { static const uint32_t seq[] = OTP_PROG_EN_SEQ; unsigned i; for (i = 0; i < countof(seq); ++i) { +#ifndef RPI4 + *REG32(OTP_BITSEL) = seq[i]; +#else *REG32(OTP_DATA) = seq[i]; - if (otp_set_command(OTP_CMD_PROG_ENABLE)) +#endif + if (otp_set_command(0, OTP_CMD_PROG_ENABLE)) return -1; } return otp_wait_status(OTP_STAT_PROG_ENABLE, OTP_MAX_PROG_WAIT); @@ -112,9 +125,66 @@ static int otp_enable_program(void) static int otp_disable_program(void) { - return otp_set_command(OTP_CMD_PROG_DISABLE); + return otp_set_command(0, OTP_CMD_PROG_DISABLE); } +#ifndef RPI4 + +static int otp_program_bit(uint8_t addr, uint8_t bit) +{ + uint32_t cmd; + int err; + int i; + + *REG32(OTP_ADDR) = addr; + *REG32(OTP_BITSEL) = bit; + + if (addr < 8) + cmd = 0x38000a; + else if (addr < 77) + cmd = 0x58000a; + else + cmd = 0x78000a; + err = -1; + for (i = 0; i < OTP_MAX_WRITE_RETRIES; ++i) { + otp_set_command(0x1420000, cmd); + if (!otp_set_command(0x1484, 0x88003) && + (*REG32(OTP_STATUS) & OTP_STAT_PROG_OK)) { + err = 0; + break; + } + } + for (i = 0; i < OTP_MAX_WRITE_RETRIES; ++i) { + otp_set_command(0x9420000, cmd); + if (!otp_set_command(0x8001484, 0x88003) && + (*REG32(OTP_STATUS) & OTP_STAT_PROG_OK)) { + err = 0; + break; + } + } + return err; +} + +static int otp_write_enabled(uint8_t addr, uint32_t newval) +{ + int bitnum, err; + uint32_t oldval = otp_read_open(addr); + if (oldval == 0xffffffffL) // This check guards against read failures + return 0; + + err = 0; + for (bitnum = 0; bitnum < 32; ++bitnum) { + uint32_t bitmask = (uint32_t)1 << bitnum; + if ((oldval & bitmask) != 0 || (newval & bitmask) == 0) + continue; + if (otp_program_bit(addr, bitnum) < 0) + ++err; + } + return err; +} + +#else /* RPI4 */ + static int otp_write_enabled(uint8_t addr, uint32_t newval) { uint32_t oldval = otp_read_open(addr); @@ -124,9 +194,11 @@ static int otp_write_enabled(uint8_t addr, uint32_t newval) otp_delay(); *REG32(OTP_ADDR) = addr; otp_delay(); - return otp_set_command(OTP_CMD_PROGRAM_WORD); + return otp_set_command(0, OTP_CMD_PROGRAM_WORD); } +#endif /* RPI4 */ + static int otp_write_open(uint8_t addr, uint32_t val) { int err; @@ -149,8 +221,6 @@ int otp_write(uint8_t addr, uint32_t val) return err; } -#endif /* RPI4 */ - void dump_all_otp(void) { printf("full otp dump\n"); for (uint8_t addr=0; addr < 67; addr++) { @@ -215,6 +285,7 @@ int cmd_otp_pretty(int argc, const cmd_args *argv) { static int cmd_otp_write(int argc, const cmd_args *argv) { uint32_t addr, val; + int err; if (argc != 3) { printf("usage: otp_write 36 0x20\n"); return -1; @@ -223,7 +294,8 @@ static int cmd_otp_write(int argc, const cmd_args *argv) { val = argv[2].u; otp_open(); printf("old value: 0x%08"PRIx32"\n", otp_read_open(addr)); - switch (otp_write_open(addr, val)) { + err = otp_write_open(addr, val); + switch (err) { case OTP_ERR_ENABLE: printf("cannot %s OTP programming\n", "enable"); break; @@ -233,6 +305,12 @@ static int cmd_otp_write(int argc, const cmd_args *argv) { case OTP_ERR_DISABLE: printf("cannot %s OTP programming\n", "disable"); break; +#ifndef RPI4 + case 0: + break; + default: + printf("%d bits failed\n", err); +#endif } printf("new value: 0x%08"PRIx32"\n", otp_read_open(addr)); otp_close(); From b31029521f2e7bf1e8e31b5447753799db5ad66d Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 25 Feb 2020 19:33:27 -0400 Subject: [PATCH 020/100] commit the current arm and pll stuff --- arch/vc4/arch.c | 1 + notes.txt | 18 ++++++ platform/bcm28xx/arm_control/arm.c | 60 +++++++++++++++++++ platform/bcm28xx/arm_control/rules.mk | 8 +++ platform/bcm28xx/include/platform/bcm28xx.h | 24 -------- .../bcm28xx/include/platform/bcm28xx/pll.h | 40 +++++++++++++ platform/bcm28xx/pll_control.c | 48 +++++++++++++++ platform/bcm28xx/pll_read.c | 1 + platform/bcm28xx/rpi-ddr2/ddr2.h | 2 - platform/bcm28xx/rules.mk | 1 + project/rpi4-start4.mk | 3 +- 11 files changed, 179 insertions(+), 27 deletions(-) create mode 100644 notes.txt create mode 100644 platform/bcm28xx/arm_control/arm.c create mode 100644 platform/bcm28xx/arm_control/rules.mk create mode 100644 platform/bcm28xx/include/platform/bcm28xx/pll.h create mode 100644 platform/bcm28xx/pll_control.c diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index db65395eb0..4df9504a86 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -6,6 +6,7 @@ #include #include #include +#include static int cmd_boot_other_core(int argc, const cmd_args *argv); static int cmd_testit(int argc, const cmd_args *argv); diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000000..bc33fab04b --- /dev/null +++ b/notes.txt @@ -0,0 +1,18 @@ +0xc0261e40 bootstrap2 stack +0xc0263820 shell stack +0xc15ffe8e stray pc +0xc15fffcc primary stack + + +# build LK +[nix-shell:~/apps/rpi/lk]$ make PROJECT=rpi4-recovery +# sign LK +[nix-shell:~/apps/rpi/rpi-eeprom/firmware/beta]$ node ~/apps/rpi-open-firmware/sign.js ~/apps/rpi/lk/build-rpi4-recovery/lk.bin recovery.bin +# transfer to other pc +[clever@amd-nixos:~/apps/rpi/usbboot]$ scp system76:/home/clever/apps/rpi/rpi-eeprom/firmware/beta/recovery.bin lk/bootcode.bin +# host over usb +[clever@amd-nixos:~/apps/rpi/usbboot]$ sudo ./rpiboot -v -d ./lk/ +# launch everything +[nix-shell:~/apps/rpi/lk]$ uart-manager +Uuart early init done + diff --git a/platform/bcm28xx/arm_control/arm.c b/platform/bcm28xx/arm_control/arm.c new file mode 100644 index 0000000000..792a9e3a6f --- /dev/null +++ b/platform/bcm28xx/arm_control/arm.c @@ -0,0 +1,60 @@ +#include +#include +#include + +#define ARM_MEMORY_BASE 0xC0000000 +#define VC4_PERIPH_BASE 0x7E000000 +#define ARM_PERIPH_BASE 0x3F000000 + +#define ARM_BASE 0x7E00B000 +#define ARM_CONTROL0 ARM_BASE+0x000 +#define ARM_C0_SIZ1G 0x00000003 +#define ARM_C0_FULLPERI 0x00000040 +#define ARM_C0_APROTPASS 0x0000A000 // Translate 1:1 +#define ARM_IRQ_ENBL3 ARM_BASE+0x218 // ARM irqs enable bits +#define ARM_IE_MAIL 0x00000002 // Mail IRQ +#define ARM_CONTROL1 ARM_BASE+0x440 +#define ARM_C1_PERSON 0x00000100 // peripherals on +#define ARM_TRANSLATE ARM_BASE+0x100 +#define ARM_ID ARM_BASE+0x44C + +static int cmd_test_arm(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("arm", "arm the arm!", &cmd_test_arm) +STATIC_COMMAND_END(arm); + +// maps a 16mb chunk of ram +// the bus address has a resolution of 2mb +// the arm addr has a resolution of 16mb +// the entire mapping is 16mb long +// comments say there are 32 slots in the list (512mb mapped) an another 32 spare (1gig mapped) +void mapBusToArm(uint32_t busAddr, uint32_t armAddr) { + volatile uint32_t* tte = REG32(ARM_TRANSLATE); + + uint32_t index = armAddr >> 24; // div by 16mb + uint32_t pte = busAddr >> 21; // div by 2mb + //printf("mapBusToArm index:%x, pte:%x\n", index, pte); + + tte[index] = pte; +} + +static int cmd_test_arm(int argc, const cmd_args *argv) { + for (uint32_t i = 0; i < 62; i++) { + uint32_t offset = i * 0x1000000; + mapBusToArm(ARM_MEMORY_BASE + offset, 0x0 + offset); + } + mapBusToArm(VC4_PERIPH_BASE, ARM_PERIPH_BASE); + + printf("ARM ID: 0x%X C0: 0x%X\n", *REG32(ARM_ID), *REG32(ARM_CONTROL0)); + + /* + * enable peripheral access, map arm secure bits to axi secure bits 1:1 and + * set the mem size for who knows what reason. + */ + *REG32(ARM_CONTROL0) |= 0x008 | ARM_C0_APROTPASS | ARM_C0_SIZ1G | ARM_C0_FULLPERI; // | ARM_C0_AARCH64; + *REG32(ARM_CONTROL1) |= ARM_C1_PERSON; + + *REG32(ARM_IRQ_ENBL3) |= ARM_IE_MAIL; + return 0; +} diff --git a/platform/bcm28xx/arm_control/rules.mk b/platform/bcm28xx/arm_control/rules.mk new file mode 100644 index 0000000000..29a24a6c23 --- /dev/null +++ b/platform/bcm28xx/arm_control/rules.mk @@ -0,0 +1,8 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/arm.c \ + + +include make/module.mk diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 48d5e96985..6036f64819 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -49,7 +49,6 @@ void print_timestamp(void); #define ARM_BASE (BCM_PERIPH_BASE_VIRT + 0xB000) #define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) #define CM_BASE (BCM_PERIPH_BASE_VIRT + 0x101000) -#define A2W_BASE (BCM_PERIPH_BASE_VIRT + 0x102000) #define PCM_CLOCK_BASE (BCM_PERIPH_BASE_VIRT + 0x101098) #define RNG_BASE (BCM_PERIPH_BASE_VIRT + 0x104000) #define GPIO_BASE (BCM_PERIPH_BASE_VIRT + 0x200000) @@ -101,29 +100,6 @@ void print_timestamp(void); #define PM_WDOG (PM_BASE + 0x24) #define PM_WDOG_MASK 0x00000fff -#define A2W_PASSWORD 0x5a000000 -#define A2W_PLLA_CTRL (A2W_BASE + 0x100) -#define A2W_PLLC_CTRL (A2W_BASE + 0x120) -#define A2W_PLLC_CTRL_PDIV_SET 0x00007000 -#define A2W_PLLC_CTRL_NDIV_SET 0x000003ff -#define A2W_PLLC_CTRL_PDIV_LSB 12 -#define A2W_PLLD_CTRL (A2W_BASE + 0x140) -#define A2W_PLLH_CTRL (A2W_BASE + 0x160) -#define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) -#define A2W_PLLA_FRAC (A2W_BASE + 0x200) -#define A2W_PLLC_FRAC (A2W_BASE + 0x220) -#define A2W_PLLD_FRAC (A2W_BASE + 0x240) -#define A2W_PLLH_FRAC (A2W_BASE + 0x260) -#define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) -#define A2W_PLLC_CORE1 (A2W_BASE + 0x420) -#define A2W_PLLC_CORE0 (A2W_BASE + 0x620) -#define A2W_PLLC_CORE0_DIV_SET 0x000000ff -#define A2W_PLLA_FRAC_MASK 0x000fffff -#define A2W_PLLB_FRAC_MASK 0x000fffff -#define A2W_PLLC_FRAC_MASK 0x000fffff -#define A2W_PLLD_FRAC_MASK 0x000fffff -#define A2W_PLLH_FRAC_MASK 0x000fffff - #define ARMCTRL_BASE (ARM_BASE + 0x000) #define ARMCTRL_INTC_BASE (ARM_BASE + 0x200) #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h new file mode 100644 index 0000000000..20afe501e0 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -0,0 +1,40 @@ +#define CM_PLLB 0x7e101170 +#define CM_PLLB_LOADARM_SET 0x00000001 +#define CM_PLLB_HOLDARM_SET 0x00000002 +#define CM_PLLB_ANARST_SET 0x00000100 +#define CM_PLLB_DIGRST_SET 0x00000200 +#define CM_ARMCTL 0x7e1011b0 +#define CM_ARMCTL_ENAB_SET 0x00000010 + +#define A2W_XOSC_CTRL 0x7e102190 +#define A2W_XOSC_CTRL_DDREN_SET 0x00000010 +#define A2W_XOSC_CTRL_PLLAEN_SET 0x00000040 +#define A2W_XOSC_CTRL_PLLBEN_SET 0x00000080 + +#define A2W_BASE (BCM_PERIPH_BASE_VIRT + 0x102000) + +#define A2W_PASSWORD 0x5a000000 +#define A2W_PLLA_FRAC_MASK 0x000fffff +#define A2W_PLLB_FRAC_MASK 0x000fffff +#define A2W_PLLC_FRAC_MASK 0x000fffff +#define A2W_PLLD_FRAC_MASK 0x000fffff +#define A2W_PLLH_FRAC_MASK 0x000fffff + +#define A2W_PLLA_CTRL (A2W_BASE + 0x100) +#define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) +#define A2W_PLLA_FRAC (A2W_BASE + 0x200) +#define A2W_PLLC_FRAC (A2W_BASE + 0x220) +#define A2W_PLLD_FRAC (A2W_BASE + 0x240) +#define A2W_PLLH_FRAC (A2W_BASE + 0x260) +#define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) +#define A2W_PLLB_ARM 0x7e1023e0 +#define A2W_PLLC_CORE1 (A2W_BASE + 0x420) +#define A2W_PLLC_CORE0 (A2W_BASE + 0x620) +#define A2W_PLLC_CORE0_DIV_SET 0x000000ff + +#define A2W_PLLC_CTRL (A2W_BASE + 0x120) +#define A2W_PLLC_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLC_CTRL_NDIV_SET 0x000003ff +#define A2W_PLLC_CTRL_PDIV_LSB 12 +#define A2W_PLLD_CTRL (A2W_BASE + 0x140) +#define A2W_PLLH_CTRL (A2W_BASE + 0x160) diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c new file mode 100644 index 0000000000..adc598f87a --- /dev/null +++ b/platform/bcm28xx/pll_control.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +struct pll_stage1 { + volatile uint32_t *ana; + uint32_t enable_bit; // the bit to enable it within A2W_XOSC_CTRL + volatile uint32_t *frac; + volatile uint32_t *ctrl; +}; + +static struct pll_stage1 plla = { + .ana = REG32(0x7e102010), + .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, + .frac = REG32(A2W_PLLA_FRAC), + .ctrl = REG32(A2W_PLLA_CTRL) +}; + +static struct pll_stage1 pllb = { + .ana = REG32(0x7e1020f0), + .enable_bit = A2W_XOSC_CTRL_PLLBEN_SET, + .frac = REG32(A2W_PLLB_FRAC), + .ctrl = REG32(A2W_PLLB_CTRL) +}; + +void configure_pll_b(uint32_t freq) { + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | pllb.enable_bit; + *pllb.frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 + *pllb.ctrl = A2W_PASSWORD | 48 | 0x1000; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; + + pllb.ana[3] = A2W_PASSWORD | 0x100; + pllb.ana[2] = A2W_PASSWORD | 0x0; + pllb.ana[1] = A2W_PASSWORD | 0x140000; + pllb.ana[0] = A2W_PASSWORD | 0x0; + + // set dig values + + *REG32(A2W_PLLB_ARM) = A2W_PASSWORD | 2; + + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET | CM_PLLB_LOADARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD; + + *REG32(CM_ARMCTL) = CM_PASSWORD | 4 | CM_ARMCTL_ENAB_SET; +} diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 156b009cf3..a666f56401 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include diff --git a/platform/bcm28xx/rpi-ddr2/ddr2.h b/platform/bcm28xx/rpi-ddr2/ddr2.h index 4856df0e8c..86302eea58 100644 --- a/platform/bcm28xx/rpi-ddr2/ddr2.h +++ b/platform/bcm28xx/rpi-ddr2/ddr2.h @@ -101,8 +101,6 @@ #define A2W_PASSWORD 0x5a000000 -#define A2W_XOSC_CTRL 0x7e102190 -#define A2W_XOSC_CTRL_DDREN_SET 0x00000010 #define A2W_XOSC_CTRLR HW_REGISTER_RW( 0x7e102990 ) #define A2W_SMPS_LDO0 0x7e1020d0 #define A2W_SMPS_LDO1 0x7e1020d4 diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 82157b184b..a2f05d9682 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -56,6 +56,7 @@ MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/pll_read.c \ + $(LOCAL_DIR)/pll_control.c \ diff --git a/project/rpi4-start4.mk b/project/rpi4-start4.mk index 8ae4b41e2a..ce62430aab 100644 --- a/project/rpi4-start4.mk +++ b/project/rpi4-start4.mk @@ -7,7 +7,8 @@ MODULES += \ app/shell \ lib/cksum \ platform/bcm28xx/otp \ - #lib/debugcommands \ + lib/debugcommands \ app/stringtests \ app/tests \ + platform/bcm28xx/arm_control \ From 7b8171a4c357740a797a5b77d8cbda4b7619871c Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 21:46:54 +0100 Subject: [PATCH 021/100] Add missing PLL hw register definitions Get rid of hardcoded values in pll_control.c --- .../bcm28xx/include/platform/bcm28xx/pll.h | 22 +++++++++++++++++-- platform/bcm28xx/pll_control.c | 4 ++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 20afe501e0..b6d1469587 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -20,8 +20,12 @@ #define A2W_PLLD_FRAC_MASK 0x000fffff #define A2W_PLLH_FRAC_MASK 0x000fffff -#define A2W_PLLA_CTRL (A2W_BASE + 0x100) -#define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) +#define A2W_PLLA_ANA0 (A2W_BASE + 0x010) +#define A2W_PLLC_ANA0 (A2W_BASE + 0x030) +#define A2W_PLLD_ANA0 (A2W_BASE + 0x050) +#define A2W_PLLH_ANA0 (A2W_BASE + 0x070) +#define A2W_PLLB_ANA0 (A2W_BASE + 0x0f0) + #define A2W_PLLA_FRAC (A2W_BASE + 0x200) #define A2W_PLLC_FRAC (A2W_BASE + 0x220) #define A2W_PLLD_FRAC (A2W_BASE + 0x240) @@ -32,9 +36,23 @@ #define A2W_PLLC_CORE0 (A2W_BASE + 0x620) #define A2W_PLLC_CORE0_DIV_SET 0x000000ff +#define A2W_PLLA_CTRL (A2W_BASE + 0x100) +#define A2W_PLLA_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLA_CTRL_NDIV_SET 0x000003ff +#define A2W_PLLA_CTRL_PDIV_LSB 12 #define A2W_PLLC_CTRL (A2W_BASE + 0x120) #define A2W_PLLC_CTRL_PDIV_SET 0x00007000 #define A2W_PLLC_CTRL_NDIV_SET 0x000003ff #define A2W_PLLC_CTRL_PDIV_LSB 12 #define A2W_PLLD_CTRL (A2W_BASE + 0x140) +#define A2W_PLLD_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLD_CTRL_NDIV_SET 0x000003ff +#define A2W_PLLD_CTRL_PDIV_LSB 12 #define A2W_PLLH_CTRL (A2W_BASE + 0x160) +#define A2W_PLLH_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLH_CTRL_NDIV_SET 0x000000ff +#define A2W_PLLH_CTRL_PDIV_LSB 12 +#define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) +#define A2W_PLLB_CTRL_PDIV_SET 0x00007000 +#define A2W_PLLB_CTRL_NDIV_SET 0x000003ff +#define A2W_PLLB_CTRL_PDIV_LSB 12 diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index adc598f87a..fb9532c0ee 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -11,14 +11,14 @@ struct pll_stage1 { }; static struct pll_stage1 plla = { - .ana = REG32(0x7e102010), + .ana = REG32(A2W_PLLA_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, .frac = REG32(A2W_PLLA_FRAC), .ctrl = REG32(A2W_PLLA_CTRL) }; static struct pll_stage1 pllb = { - .ana = REG32(0x7e1020f0), + .ana = REG32(A2W_PLLB_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLBEN_SET, .frac = REG32(A2W_PLLB_FRAC), .ctrl = REG32(A2W_PLLB_CTRL) From 84aba011acb3abde6d693ef26f26f90ca9c62f62 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 22:17:41 +0100 Subject: [PATCH 022/100] Define a PLL enum and put all PLLs into a single table --- .../bcm28xx/include/platform/bcm28xx/pll.h | 12 ++++ platform/bcm28xx/pll_control.c | 58 +++++++++++++------ 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index b6d1469587..6018f369d7 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -1,3 +1,13 @@ +#pragma once + +enum pll { + PLL_A, + PLL_B, + PLL_C, + PLL_D, + PLL_H, +}; + #define CM_PLLB 0x7e101170 #define CM_PLLB_LOADARM_SET 0x00000001 #define CM_PLLB_HOLDARM_SET 0x00000002 @@ -10,6 +20,8 @@ #define A2W_XOSC_CTRL_DDREN_SET 0x00000010 #define A2W_XOSC_CTRL_PLLAEN_SET 0x00000040 #define A2W_XOSC_CTRL_PLLBEN_SET 0x00000080 +#define A2W_XOSC_CTRL_PLLCEN_SET 0x00000001 +#define A2W_XOSC_CTRL_PLLDEN_SET 0x00000020 #define A2W_BASE (BCM_PERIPH_BASE_VIRT + 0x102000) diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index fb9532c0ee..427df99093 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -10,31 +10,51 @@ struct pll_stage1 { volatile uint32_t *ctrl; }; -static struct pll_stage1 plla = { - .ana = REG32(A2W_PLLA_ANA0), - .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, - .frac = REG32(A2W_PLLA_FRAC), - .ctrl = REG32(A2W_PLLA_CTRL) -}; - -static struct pll_stage1 pllb = { - .ana = REG32(A2W_PLLB_ANA0), - .enable_bit = A2W_XOSC_CTRL_PLLBEN_SET, - .frac = REG32(A2W_PLLB_FRAC), - .ctrl = REG32(A2W_PLLB_CTRL) +static struct pll_stage1 pll_def[] = { + [PLL_A] = { + .ana = REG32(A2W_PLLA_ANA0), + .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, + .frac = REG32(A2W_PLLA_FRAC), + .ctrl = REG32(A2W_PLLA_CTRL), + }, + [PLL_B] = { + .ana = REG32(A2W_PLLB_ANA0), + .enable_bit = A2W_XOSC_CTRL_PLLBEN_SET, + .frac = REG32(A2W_PLLB_FRAC), + .ctrl = REG32(A2W_PLLB_CTRL), + }, + [PLL_C] = { + .ana = REG32(A2W_PLLC_ANA0), + .enable_bit = A2W_XOSC_CTRL_PLLCEN_SET, + .frac = REG32(A2W_PLLC_FRAC), + .ctrl = REG32(A2W_PLLC_CTRL), + }, + [PLL_D] = { + .ana = REG32(A2W_PLLD_ANA0), + .enable_bit = A2W_XOSC_CTRL_PLLDEN_SET, + .frac = REG32(A2W_PLLD_FRAC), + .ctrl = REG32(A2W_PLLD_CTRL), + }, + [PLL_H] = { + .ana = REG32(A2W_PLLH_ANA0), + .enable_bit = A2W_XOSC_CTRL_PLLCEN_SET, // official firmware does this (?) + .frac = REG32(A2W_PLLH_FRAC), + .ctrl = REG32(A2W_PLLH_CTRL), + }, }; void configure_pll_b(uint32_t freq) { - *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | pllb.enable_bit; - *pllb.frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 - *pllb.ctrl = A2W_PASSWORD | 48 | 0x1000; + struct pll_stage1 *def = &pll_def[PLL_B]; + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; + *def->frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 + *def->ctrl = A2W_PASSWORD | 48 | 0x1000; *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET; *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; - pllb.ana[3] = A2W_PASSWORD | 0x100; - pllb.ana[2] = A2W_PASSWORD | 0x0; - pllb.ana[1] = A2W_PASSWORD | 0x140000; - pllb.ana[0] = A2W_PASSWORD | 0x0; + def->ana[3] = A2W_PASSWORD | 0x100; + def->ana[2] = A2W_PASSWORD | 0x0; + def->ana[1] = A2W_PASSWORD | 0x140000; + def->ana[0] = A2W_PASSWORD | 0x0; // set dig values From 5fa7811679789e85239441f680516da16a1a8f82 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 22:20:13 +0100 Subject: [PATCH 023/100] Constify the PLL definition table It should not be modified, so it may go into read-only data. --- platform/bcm28xx/pll_control.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 427df99093..d45022b7ce 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -10,7 +10,7 @@ struct pll_stage1 { volatile uint32_t *ctrl; }; -static struct pll_stage1 pll_def[] = { +static const struct pll_stage1 pll_def[] = { [PLL_A] = { .ana = REG32(A2W_PLLA_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, @@ -44,7 +44,7 @@ static struct pll_stage1 pll_def[] = { }; void configure_pll_b(uint32_t freq) { - struct pll_stage1 *def = &pll_def[PLL_B]; + const struct pll_stage1 *def = &pll_def[PLL_B]; *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; *def->frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 *def->ctrl = A2W_PASSWORD | 48 | 0x1000; From 30e69290ff53498a809a3b92540e60e2ac4dc35e Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 22:28:36 +0100 Subject: [PATCH 024/100] Make PLL definitions globally available This change allows reusing the data from other modules. --- platform/bcm28xx/include/platform/bcm28xx/pll.h | 11 +++++++++++ platform/bcm28xx/pll_control.c | 11 ++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 6018f369d7..2b2d123ab3 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -6,8 +6,19 @@ enum pll { PLL_C, PLL_D, PLL_H, + + PLL_NUM, +}; + +struct pll_def { + volatile uint32_t *ana; + uint32_t enable_bit; // the bit to enable it within A2W_XOSC_CTRL + volatile uint32_t *frac; + volatile uint32_t *ctrl; }; +extern const struct pll_def pll_def[PLL_NUM]; + #define CM_PLLB 0x7e101170 #define CM_PLLB_LOADARM_SET 0x00000001 #define CM_PLLB_HOLDARM_SET 0x00000002 diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index d45022b7ce..ca62fec379 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -3,14 +3,7 @@ #include #include -struct pll_stage1 { - volatile uint32_t *ana; - uint32_t enable_bit; // the bit to enable it within A2W_XOSC_CTRL - volatile uint32_t *frac; - volatile uint32_t *ctrl; -}; - -static const struct pll_stage1 pll_def[] = { +const struct pll_def pll_def[] = { [PLL_A] = { .ana = REG32(A2W_PLLA_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, @@ -44,7 +37,7 @@ static const struct pll_stage1 pll_def[] = { }; void configure_pll_b(uint32_t freq) { - const struct pll_stage1 *def = &pll_def[PLL_B]; + const struct pll_def *def = &pll_def[PLL_B]; *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; *def->frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 *def->ctrl = A2W_PASSWORD | 48 | 0x1000; From b73f1351680d773dbc4bb1680f415dcd1807b7c8 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 22:35:05 +0100 Subject: [PATCH 025/100] Make a single A2_PLL_FRAC_MASK macro All PLLs have a 12-bit fractional part. There is no need to complicate matters by defining per-PLL masks. --- platform/bcm28xx/include/platform/bcm28xx/pll.h | 7 ++----- platform/bcm28xx/pll_read.c | 10 +++++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 2b2d123ab3..c22219eb5a 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -37,11 +37,6 @@ extern const struct pll_def pll_def[PLL_NUM]; #define A2W_BASE (BCM_PERIPH_BASE_VIRT + 0x102000) #define A2W_PASSWORD 0x5a000000 -#define A2W_PLLA_FRAC_MASK 0x000fffff -#define A2W_PLLB_FRAC_MASK 0x000fffff -#define A2W_PLLC_FRAC_MASK 0x000fffff -#define A2W_PLLD_FRAC_MASK 0x000fffff -#define A2W_PLLH_FRAC_MASK 0x000fffff #define A2W_PLLA_ANA0 (A2W_BASE + 0x010) #define A2W_PLLC_ANA0 (A2W_BASE + 0x030) @@ -54,6 +49,8 @@ extern const struct pll_def pll_def[PLL_NUM]; #define A2W_PLLD_FRAC (A2W_BASE + 0x240) #define A2W_PLLH_FRAC (A2W_BASE + 0x260) #define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) +#define A2W_PLL_FRAC_MASK 0x000fffff + #define A2W_PLLB_ARM 0x7e1023e0 #define A2W_PLLC_CORE1 (A2W_BASE + 0x420) #define A2W_PLLC_CORE0 (A2W_BASE + 0x620) diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index a666f56401..9ef07c0cf4 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -34,26 +34,26 @@ uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { } uint32_t plla() { - return compute_pll_freq(*REG32(A2W_PLLA_CTRL), *REG32(A2W_PLLA_FRAC) & A2W_PLLA_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLA_CTRL), *REG32(A2W_PLLA_FRAC) & A2W_PLL_FRAC_MASK); } uint32_t pllb() { - return compute_pll_freq(*REG32(A2W_PLLB_CTRL), *REG32(A2W_PLLB_FRAC) & A2W_PLLB_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLB_CTRL), *REG32(A2W_PLLB_FRAC) & A2W_PLL_FRAC_MASK); } uint32_t pllc() { //uint32_t ana1 = A2W_PLLC_ANA1; uint32_t ctrl = *REG32(A2W_PLLC_CTRL); - uint32_t frac = *REG32(A2W_PLLC_FRAC) & A2W_PLLC_FRAC_MASK; + uint32_t frac = *REG32(A2W_PLLC_FRAC) & A2W_PLL_FRAC_MASK; return compute_pll_freq(ctrl, frac); } uint32_t plld() { - return compute_pll_freq(*REG32(A2W_PLLD_CTRL), *REG32(A2W_PLLD_FRAC) & A2W_PLLD_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLD_CTRL), *REG32(A2W_PLLD_FRAC) & A2W_PLL_FRAC_MASK); } uint32_t pllh() { - return compute_pll_freq(*REG32(A2W_PLLH_CTRL), *REG32(A2W_PLLH_FRAC) & A2W_PLLH_FRAC_MASK); + return compute_pll_freq(*REG32(A2W_PLLH_CTRL), *REG32(A2W_PLLH_FRAC) & A2W_PLL_FRAC_MASK); } uint32_t pllc_core0(void) { From fb53a2e8490a86009f53be6f5a90ae00c24367d4 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 23:18:00 +0100 Subject: [PATCH 026/100] Enhance PLL definitions and reuse them in pll_read --- .../bcm28xx/include/platform/bcm28xx/pll.h | 4 ++ platform/bcm28xx/pll_control.c | 20 ++++++++ platform/bcm28xx/pll_read.c | 50 +++++++++---------- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index c22219eb5a..ebec5377e3 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -11,10 +11,14 @@ enum pll { }; struct pll_def { + char name[8]; volatile uint32_t *ana; uint32_t enable_bit; // the bit to enable it within A2W_XOSC_CTRL volatile uint32_t *frac; volatile uint32_t *ctrl; + uint32_t ndiv_mask; + uint32_t pdiv_mask; + unsigned short pdiv_shift; }; extern const struct pll_def pll_def[PLL_NUM]; diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index ca62fec379..a2f4b9226f 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -5,34 +5,54 @@ const struct pll_def pll_def[] = { [PLL_A] = { + .name = "PLLA", .ana = REG32(A2W_PLLA_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, .frac = REG32(A2W_PLLA_FRAC), .ctrl = REG32(A2W_PLLA_CTRL), + .ndiv_mask = A2W_PLLA_CTRL_NDIV_SET, + .pdiv_mask = A2W_PLLA_CTRL_PDIV_SET, + .pdiv_shift = A2W_PLLA_CTRL_PDIV_LSB, }, [PLL_B] = { + .name = "PLLB", .ana = REG32(A2W_PLLB_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLBEN_SET, .frac = REG32(A2W_PLLB_FRAC), .ctrl = REG32(A2W_PLLB_CTRL), + .ndiv_mask = A2W_PLLB_CTRL_NDIV_SET, + .pdiv_mask = A2W_PLLB_CTRL_PDIV_SET, + .pdiv_shift = A2W_PLLB_CTRL_PDIV_LSB, }, [PLL_C] = { + .name = "PLLC", .ana = REG32(A2W_PLLC_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLCEN_SET, .frac = REG32(A2W_PLLC_FRAC), .ctrl = REG32(A2W_PLLC_CTRL), + .ndiv_mask = A2W_PLLC_CTRL_NDIV_SET, + .pdiv_mask = A2W_PLLC_CTRL_PDIV_SET, + .pdiv_shift = A2W_PLLC_CTRL_PDIV_LSB, }, [PLL_D] = { + .name = "PLLD", .ana = REG32(A2W_PLLD_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLDEN_SET, .frac = REG32(A2W_PLLD_FRAC), .ctrl = REG32(A2W_PLLD_CTRL), + .ndiv_mask = A2W_PLLD_CTRL_NDIV_SET, + .pdiv_mask = A2W_PLLD_CTRL_PDIV_SET, + .pdiv_shift = A2W_PLLD_CTRL_PDIV_LSB, }, [PLL_H] = { + .name = "PLLH", .ana = REG32(A2W_PLLH_ANA0), .enable_bit = A2W_XOSC_CTRL_PLLCEN_SET, // official firmware does this (?) .frac = REG32(A2W_PLLH_FRAC), .ctrl = REG32(A2W_PLLH_CTRL), + .ndiv_mask = A2W_PLLH_CTRL_NDIV_SET, + .pdiv_mask = A2W_PLLH_CTRL_PDIV_SET, + .pdiv_shift = A2W_PLLH_CTRL_PDIV_LSB, }, }; diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 9ef07c0cf4..bb5097ca7e 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -22,11 +22,13 @@ uint32_t get_uart_base_freq() { return clk_get_freq(CM_UARTDIV, CM_UARTCTL); } -uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { - // FIXME, ignores the addr passed in - uint32_t ndiv = *REG32(ctrl) & A2W_PLLC_CTRL_NDIV_SET; - uint32_t pdiv = (*REG32(ctrl) & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; - uint64_t mult1 = (ndiv << 20) | *REG32(frac); +uint32_t get_pll_freq(enum pll pll) { + const struct pll_def *def = &pll_def[pll]; + uint32_t ctrl = *def->ctrl; + uint32_t ndiv = ctrl & def->ndiv_mask; + uint32_t pdiv = (ctrl & def->pdiv_mask) >> def->pdiv_shift; + uint32_t frac = *def->frac & A2W_PLL_FRAC_MASK; + uint64_t mult1 = (ndiv << 20) | frac; mult1 *= pdiv; // TODO, the optional /2 phase uint32_t freq = (xtal_freq * mult1) >> 20; @@ -34,26 +36,23 @@ uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { } uint32_t plla() { - return compute_pll_freq(*REG32(A2W_PLLA_CTRL), *REG32(A2W_PLLA_FRAC) & A2W_PLL_FRAC_MASK); + return get_pll_freq(PLL_A); } uint32_t pllb() { - return compute_pll_freq(*REG32(A2W_PLLB_CTRL), *REG32(A2W_PLLB_FRAC) & A2W_PLL_FRAC_MASK); + return get_pll_freq(PLL_B); } uint32_t pllc() { - //uint32_t ana1 = A2W_PLLC_ANA1; - uint32_t ctrl = *REG32(A2W_PLLC_CTRL); - uint32_t frac = *REG32(A2W_PLLC_FRAC) & A2W_PLL_FRAC_MASK; - return compute_pll_freq(ctrl, frac); + return get_pll_freq(PLL_C); } uint32_t plld() { - return compute_pll_freq(*REG32(A2W_PLLD_CTRL), *REG32(A2W_PLLD_FRAC) & A2W_PLL_FRAC_MASK); + return get_pll_freq(PLL_D); } uint32_t pllh() { - return compute_pll_freq(*REG32(A2W_PLLH_CTRL), *REG32(A2W_PLLH_FRAC) & A2W_PLL_FRAC_MASK); + return get_pll_freq(PLL_H); } uint32_t pllc_core0(void) { @@ -97,13 +96,14 @@ uint32_t clk_get_input_freq(uint32_t ctlreg) { } } -static uint32_t dump_pll_state(const char *prefix, uint32_t ctrl, uint32_t frac) { - uint32_t ctrl_val = *REG32(ctrl); - uint32_t frac_value = *REG32(frac); - dprintf(INFO, "A2W_%s_CTRL: 0x%x\n", prefix, ctrl_val); - dprintf(INFO, "A2W_%s_FRAC: 0x%x\n", prefix, frac_value); - uint32_t freq = compute_pll_freq(ctrl, frac); - dprintf(INFO, "%s freq: %u\n", prefix, freq); +static uint32_t dump_pll_state(enum pll pll) { + const struct pll_def *def = &pll_def[pll]; + uint32_t ctrl_val = *def->ctrl; + uint32_t frac_value = *def->frac; + dprintf(INFO, "A2W_%s_CTRL: 0x%x\n", def->name, ctrl_val); + dprintf(INFO, "A2W_%s_FRAC: 0x%x\n", def->name, frac_value); + uint32_t freq = get_pll_freq(pll); + dprintf(INFO, "%s freq: %u\n", def->name, freq); return freq; } @@ -124,15 +124,15 @@ static void dump_plldiv2_state(const char *prefix, uint32_t ctrl, uint32_t div) } static int cmd_pll_dump(int argc, const cmd_args *argv) { - dump_pll_state("PLLA", A2W_PLLA_CTRL, A2W_PLLA_FRAC); - dump_pll_state("PLLB", A2W_PLLB_CTRL, A2W_PLLB_FRAC); - uint32_t pllc_freq = dump_pll_state("PLLC", A2W_PLLC_CTRL, A2W_PLLC_FRAC); + dump_pll_state(PLL_A); + dump_pll_state(PLL_B); + uint32_t pllc_freq = dump_pll_state(PLL_C); if (pllc_freq > 0) { dump_plldiv_state("PLLC_CORE0", A2W_PLLC_CORE0, pllc_freq); dump_plldiv_state("PLLC_CORE1", A2W_PLLC_CORE1, pllc_freq); } - dump_pll_state("PLLD", A2W_PLLD_CTRL, A2W_PLLD_FRAC); - dump_pll_state("PLLH", A2W_PLLH_CTRL, A2W_PLLH_FRAC); + dump_pll_state(PLL_D); + dump_pll_state(PLL_H); dump_plldiv2_state("VPU", CM_VPUCTL, CM_VPUDIV); return 0; From 8bc41de569680891dd6a82ef29e24cf06b865732 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 23:24:08 +0100 Subject: [PATCH 027/100] Take the ANA1 pre-divider into account for get_pll_freq() --- platform/bcm28xx/include/platform/bcm28xx/pll.h | 1 + platform/bcm28xx/pll_control.c | 5 +++++ platform/bcm28xx/pll_read.c | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index ebec5377e3..498f65026a 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -19,6 +19,7 @@ struct pll_def { uint32_t ndiv_mask; uint32_t pdiv_mask; unsigned short pdiv_shift; + unsigned short ana1_pdiv_bit; }; extern const struct pll_def pll_def[PLL_NUM]; diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index a2f4b9226f..d78d2621cb 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -13,6 +13,7 @@ const struct pll_def pll_def[] = { .ndiv_mask = A2W_PLLA_CTRL_NDIV_SET, .pdiv_mask = A2W_PLLA_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLA_CTRL_PDIV_LSB, + .ana1_pdiv_bit = 14, }, [PLL_B] = { .name = "PLLB", @@ -23,6 +24,7 @@ const struct pll_def pll_def[] = { .ndiv_mask = A2W_PLLB_CTRL_NDIV_SET, .pdiv_mask = A2W_PLLB_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLB_CTRL_PDIV_LSB, + .ana1_pdiv_bit = 14, }, [PLL_C] = { .name = "PLLC", @@ -33,6 +35,7 @@ const struct pll_def pll_def[] = { .ndiv_mask = A2W_PLLC_CTRL_NDIV_SET, .pdiv_mask = A2W_PLLC_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLC_CTRL_PDIV_LSB, + .ana1_pdiv_bit = 14, }, [PLL_D] = { .name = "PLLD", @@ -43,6 +46,7 @@ const struct pll_def pll_def[] = { .ndiv_mask = A2W_PLLD_CTRL_NDIV_SET, .pdiv_mask = A2W_PLLD_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLD_CTRL_PDIV_LSB, + .ana1_pdiv_bit = 14, }, [PLL_H] = { .name = "PLLH", @@ -53,6 +57,7 @@ const struct pll_def pll_def[] = { .ndiv_mask = A2W_PLLH_CTRL_NDIV_SET, .pdiv_mask = A2W_PLLH_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLH_CTRL_PDIV_LSB, + .ana1_pdiv_bit = 11, }, }; diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index bb5097ca7e..5d0a1078ce 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -30,8 +31,9 @@ uint32_t get_pll_freq(enum pll pll) { uint32_t frac = *def->frac & A2W_PLL_FRAC_MASK; uint64_t mult1 = (ndiv << 20) | frac; mult1 *= pdiv; - // TODO, the optional /2 phase uint32_t freq = (xtal_freq * mult1) >> 20; + if (BIT_SET(def->ana[1], def->ana1_pdiv_bit)) + freq >>= 1; return freq; } From 71a9556b34134976ed32b7d91569474a578640d3 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 23:37:53 +0100 Subject: [PATCH 028/100] Add a PLL channel enum and store existing data in a table --- .../bcm28xx/include/platform/bcm28xx/pll.h | 51 +++++++++++++++++-- platform/bcm28xx/pll_control.c | 17 +++++++ platform/bcm28xx/pll_read.c | 31 ++++++----- 3 files changed, 81 insertions(+), 18 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 498f65026a..c718e11352 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -24,6 +24,44 @@ struct pll_def { extern const struct pll_def pll_def[PLL_NUM]; +enum pll_chan { + PLL_CHAN_ACORE, + PLL_CHAN_APER, + PLL_CHAN_ADSI0, + PLL_CHAN_ACCP2, + + PLL_CHAN_BARM, + PLL_CHAN_BSP0, + PLL_CHAN_BSP1, + PLL_CHAN_BSP2, + + PLL_CHAN_CCORE0, + PLL_CHAN_CCORE1, + PLL_CHAN_CCORE2, + PLL_CHAN_CPER, + + PLL_CHAN_DCORE, + PLL_CHAN_DPER, + PLL_CHAN_DDSI0, + PLL_CHAN_DDSI1, + + PLL_CHAN_HPIX, + PLL_CHAN_HRCAL, + PLL_CHAN_HAUX, + + PLL_CHAN_NUM, +}; + +struct pll_chan_def { + char name[12]; + volatile uint32_t *ctrl; + int chenb_bit; + uint32_t div_mask; + enum pll pll; +}; + +extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; + #define CM_PLLB 0x7e101170 #define CM_PLLB_LOADARM_SET 0x00000001 #define CM_PLLB_HOLDARM_SET 0x00000002 @@ -56,11 +94,6 @@ extern const struct pll_def pll_def[PLL_NUM]; #define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) #define A2W_PLL_FRAC_MASK 0x000fffff -#define A2W_PLLB_ARM 0x7e1023e0 -#define A2W_PLLC_CORE1 (A2W_BASE + 0x420) -#define A2W_PLLC_CORE0 (A2W_BASE + 0x620) -#define A2W_PLLC_CORE0_DIV_SET 0x000000ff - #define A2W_PLLA_CTRL (A2W_BASE + 0x100) #define A2W_PLLA_CTRL_PDIV_SET 0x00007000 #define A2W_PLLA_CTRL_NDIV_SET 0x000003ff @@ -81,3 +114,11 @@ extern const struct pll_def pll_def[PLL_NUM]; #define A2W_PLLB_CTRL_PDIV_SET 0x00007000 #define A2W_PLLB_CTRL_NDIV_SET 0x000003ff #define A2W_PLLB_CTRL_PDIV_LSB 12 + +#define A2W_PLLB_ARM (A2W_BASE + 0x3e0) +#define A2W_PLLC_CORE1 (A2W_BASE + 0x420) +#define A2W_PLLC_CORE1_CHENB_LSB 8 +#define A2W_PLLC_CORE1_DIV_SET 0x000000ff +#define A2W_PLLC_CORE0 (A2W_BASE + 0x620) +#define A2W_PLLC_CORE0_CHENB_LSB 8 +#define A2W_PLLC_CORE0_DIV_SET 0x000000ff diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index d78d2621cb..b449424a59 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -61,6 +61,23 @@ const struct pll_def pll_def[] = { }, }; +const struct pll_chan_def pll_chan_def[] = { + [PLL_CHAN_CCORE0] = { + .name = "PLLC_CORE0", + .ctrl = REG32(A2W_PLLC_CORE0), + .chenb_bit = A2W_PLLC_CORE0_CHENB_LSB, + .div_mask = A2W_PLLC_CORE0_DIV_SET, + .pll = PLL_C, + }, + [PLL_CHAN_CCORE1] = { + .name = "PLLC_CORE1", + .ctrl = REG32(A2W_PLLC_CORE1), + .chenb_bit = A2W_PLLC_CORE1_CHENB_LSB, + .div_mask = A2W_PLLC_CORE1_DIV_SET, + .pll = PLL_C, + }, +}; + void configure_pll_b(uint32_t freq) { const struct pll_def *def = &pll_def[PLL_B]; *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 5d0a1078ce..5428d5762b 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -57,11 +57,17 @@ uint32_t pllh() { return get_pll_freq(PLL_H); } +uint32_t get_pll_chan_freq(enum pll_chan chan) { + const struct pll_chan_def *def = &pll_chan_def[chan]; + uint32_t ctrl_val = *def->ctrl; + uint32_t div = ctrl_val & def->div_mask; + if (BIT_SET(ctrl_val, def->chenb_bit) || div == 0) + return 0; + return get_pll_freq(def->pll) / div; +} + uint32_t pllc_core0(void) { - uint32_t ctrl = *REG32(A2W_PLLC_CORE0); - uint32_t div = ctrl & A2W_PLLC_CORE0_DIV_SET; - uint32_t pllc_freq = pllc(); - return pllc_freq / div; + return get_pll_chan_freq(PLL_CHAN_CCORE0); } uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg) { @@ -109,13 +115,12 @@ static uint32_t dump_pll_state(enum pll pll) { return freq; } -static void dump_plldiv_state(const char *prefix, uint32_t ctrl, uint32_t input) { - uint32_t ctrl_val = *REG32(ctrl); - dprintf(INFO, "\tA2W_%s: 0x%x\n", prefix, ctrl_val); - uint8_t div = ctrl_val & 0xff; - if (div == 0) return; - uint32_t freq = input / div; - dprintf(INFO, "\t%s freq: %u\n", prefix, freq); +static void dump_pll_chan_state(enum pll_chan pll_chan) { + const struct pll_chan_def *def = &pll_chan_def[pll_chan]; + uint32_t ctrl_val = *def->ctrl; + dprintf(INFO, "\tA2W_%s: 0x%x\n", def->name, ctrl_val); + uint32_t freq = get_pll_chan_freq(pll_chan); + dprintf(INFO, "\t%s freq: %u\n", def->name, freq); } static void dump_plldiv2_state(const char *prefix, uint32_t ctrl, uint32_t div) { @@ -130,8 +135,8 @@ static int cmd_pll_dump(int argc, const cmd_args *argv) { dump_pll_state(PLL_B); uint32_t pllc_freq = dump_pll_state(PLL_C); if (pllc_freq > 0) { - dump_plldiv_state("PLLC_CORE0", A2W_PLLC_CORE0, pllc_freq); - dump_plldiv_state("PLLC_CORE1", A2W_PLLC_CORE1, pllc_freq); + dump_pll_chan_state(PLL_CHAN_CCORE0); + dump_pll_chan_state(PLL_CHAN_CCORE1); } dump_pll_state(PLL_D); dump_pll_state(PLL_H); From dd73f4ee1df23eab78ed83034e75f00cc2a41a91 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Wed, 26 Feb 2020 13:54:21 +0100 Subject: [PATCH 029/100] Remove unneeded pllX() functions The definition of these functions is now trivial, so expose the underlying get_pll_freq() and get_pll_chan_freq() instead. --- .../include/platform/bcm28xx/pll_read.h | 9 +++---- platform/bcm28xx/pll_read.c | 26 +------------------ 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h index 3b28cd7fd8..b85c1b6468 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -1,5 +1,7 @@ #pragma once +#include + #ifdef __cplusplus extern "C" { #endif @@ -7,11 +9,8 @@ uint32_t clk_get_input_freq(uint32_t ctlreg); uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg); uint32_t get_vpu_per_freq(void); uint32_t get_uart_base_freq(void); -uint32_t plla(void); -uint32_t pllb(void); -uint32_t pllc(void); -uint32_t plld(void); -uint32_t pllh(void); +uint32_t get_pll_freq(enum pll pll); +uint32_t get_pll_chan_freq(enum pll_chan chan); extern uint32_t xtal_freq; #ifdef __cplusplus } diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 5428d5762b..0c0d2a09f6 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -37,26 +37,6 @@ uint32_t get_pll_freq(enum pll pll) { return freq; } -uint32_t plla() { - return get_pll_freq(PLL_A); -} - -uint32_t pllb() { - return get_pll_freq(PLL_B); -} - -uint32_t pllc() { - return get_pll_freq(PLL_C); -} - -uint32_t plld() { - return get_pll_freq(PLL_D); -} - -uint32_t pllh() { - return get_pll_freq(PLL_H); -} - uint32_t get_pll_chan_freq(enum pll_chan chan) { const struct pll_chan_def *def = &pll_chan_def[chan]; uint32_t ctrl_val = *def->ctrl; @@ -66,10 +46,6 @@ uint32_t get_pll_chan_freq(enum pll_chan chan) { return get_pll_freq(def->pll) / div; } -uint32_t pllc_core0(void) { - return get_pll_chan_freq(PLL_CHAN_CCORE0); -} - uint32_t clk_get_freq(uint32_t divreg, uint32_t ctlreg) { uint32_t div = *REG32(divreg); if (div == 0) return 0; @@ -90,7 +66,7 @@ uint32_t clk_get_input_freq(uint32_t ctlreg) { case 4: // plla return 0; case 5: // pllc_core0 - return pllc_core0(); + return get_pll_chan_freq(PLL_CHAN_CCORE0); case 6: // plld_per return 0; case 7: // pllh_aux From 0420cc6fe9c3e86a96f5e195499c9933fb1587b5 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 27 Feb 2020 23:51:57 +0100 Subject: [PATCH 030/100] Implement missing clock sources --- .../bcm28xx/include/platform/bcm28xx/pll.h | 12 ++++++++ platform/bcm28xx/pll_control.c | 28 +++++++++++++++++++ platform/bcm28xx/pll_read.c | 16 +++++------ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index c718e11352..73c19f4866 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -116,6 +116,18 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLB_CTRL_PDIV_LSB 12 #define A2W_PLLB_ARM (A2W_BASE + 0x3e0) +#define A2W_PLLC_CORE2 (A2W_BASE + 0x320) +#define A2W_PLLC_CORE2_CHENB_LSB 8 +#define A2W_PLLC_CORE2_DIV_SET 0x000000ff +#define A2W_PLLH_AUX (A2W_BASE + 0x360) +#define A2W_PLLH_AUX_CHENB_LSB 8 +#define A2W_PLLH_AUX_DIV_SET 0x000000ff +#define A2W_PLLA_CORE (A2W_BASE + 0x400) +#define A2W_PLLA_CORE_CHENB_LSB 8 +#define A2W_PLLA_CORE_DIV_SET 0x000000ff +#define A2W_PLLD_PER (A2W_BASE + 0x540) +#define A2W_PLLD_PER_CHENB_LSB 8 +#define A2W_PLLD_PER_DIV_SET 0x000000ff #define A2W_PLLC_CORE1 (A2W_BASE + 0x420) #define A2W_PLLC_CORE1_CHENB_LSB 8 #define A2W_PLLC_CORE1_DIV_SET 0x000000ff diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index b449424a59..7f7bae8dac 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -62,6 +62,13 @@ const struct pll_def pll_def[] = { }; const struct pll_chan_def pll_chan_def[] = { + [PLL_CHAN_ACORE] = { + .name = "PLLA_CORE", + .ctrl = REG32(A2W_PLLA_CORE), + .chenb_bit = A2W_PLLA_CORE_CHENB_LSB, + .div_mask = A2W_PLLA_CORE_DIV_SET, + .pll = PLL_A, + }, [PLL_CHAN_CCORE0] = { .name = "PLLC_CORE0", .ctrl = REG32(A2W_PLLC_CORE0), @@ -76,6 +83,27 @@ const struct pll_chan_def pll_chan_def[] = { .div_mask = A2W_PLLC_CORE1_DIV_SET, .pll = PLL_C, }, + [PLL_CHAN_CCORE2] = { + .name = "PLLC_CORE2", + .ctrl = REG32(A2W_PLLC_CORE2), + .chenb_bit = A2W_PLLC_CORE2_CHENB_LSB, + .div_mask = A2W_PLLC_CORE2_DIV_SET, + .pll = PLL_C, + }, + [PLL_CHAN_DPER] = { + .name = "PLLD_PER", + .ctrl = REG32(A2W_PLLD_PER), + .chenb_bit = A2W_PLLD_PER_CHENB_LSB, + .div_mask = A2W_PLLD_PER_DIV_SET, + .pll = PLL_D, + }, + [PLL_CHAN_HAUX] = { + .name = "PLLH_AUX", + .ctrl = REG32(A2W_PLLH_AUX), + .chenb_bit = A2W_PLLH_AUX_CHENB_LSB, + .div_mask = A2W_PLLH_AUX_DIV_SET, + .pll = PLL_H, + }, }; void configure_pll_b(uint32_t freq) { diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 0c0d2a09f6..824da3c955 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -63,18 +63,18 @@ uint32_t clk_get_input_freq(uint32_t ctlreg) { case 2: // test debug 0 case 3: // test debug 1 return 0; - case 4: // plla - return 0; + case 4: // plla_core + return get_pll_chan_freq(PLL_CHAN_ACORE); case 5: // pllc_core0 return get_pll_chan_freq(PLL_CHAN_CCORE0); case 6: // plld_per - return 0; + return get_pll_chan_freq(PLL_CHAN_DPER); case 7: // pllh_aux - return 0; - case 8: // pllc_core1? - return 0; - case 9: // pllc_core2? - return 0; + return get_pll_chan_freq(PLL_CHAN_HAUX); + case 8: // pllc_core1 + return get_pll_chan_freq(PLL_CHAN_CCORE1); + case 9: // pllc_core2 + return get_pll_chan_freq(PLL_CHAN_CCORE2); default: return 0; } From 4580228a5294f3fbc9785d2dd7860e51c8ff9758 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Wed, 26 Feb 2020 14:59:41 +0100 Subject: [PATCH 031/100] Add all remaining PLL definitions --- .../bcm28xx/include/platform/bcm28xx/pll.h | 40 +++++++- platform/bcm28xx/pll_control.c | 91 +++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 73c19f4866..0358dc4400 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -115,22 +115,60 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLB_CTRL_NDIV_SET 0x000003ff #define A2W_PLLB_CTRL_PDIV_LSB 12 -#define A2W_PLLB_ARM (A2W_BASE + 0x3e0) +#define A2W_PLLA_DSI0 (A2W_BASE + 0x300) +#define A2W_PLLA_DSI0_CHENB_LSB 8 +#define A2W_PLLA_DSI0_DIV_SET 0x000000ff #define A2W_PLLC_CORE2 (A2W_BASE + 0x320) #define A2W_PLLC_CORE2_CHENB_LSB 8 #define A2W_PLLC_CORE2_DIV_SET 0x000000ff +#define A2W_PLLD_DSI0 (A2W_BASE + 0x340) +#define A2W_PLLD_DSI0_CHENB_LSB 8 +#define A2W_PLLD_DSI0_DIV_SET 0x000000ff #define A2W_PLLH_AUX (A2W_BASE + 0x360) #define A2W_PLLH_AUX_CHENB_LSB 8 #define A2W_PLLH_AUX_DIV_SET 0x000000ff +#define A2W_PLLB_ARM (A2W_BASE + 0x3e0) +#define A2W_PLLB_ARM_CHENB_LSB 8 +#define A2W_PLLB_ARM_DIV_SET 0x000000ff #define A2W_PLLA_CORE (A2W_BASE + 0x400) #define A2W_PLLA_CORE_CHENB_LSB 8 #define A2W_PLLA_CORE_DIV_SET 0x000000ff +#define A2W_PLLD_CORE (A2W_BASE + 0x440) +#define A2W_PLLD_CORE_CHENB_LSB 8 +#define A2W_PLLD_CORE_DIV_SET 0x000000ff +#define A2W_PLLH_RCAL (A2W_BASE + 0x460) +#define A2W_PLLH_RCAL_CHENB_LSB 8 +#define A2W_PLLH_RCAL_DIV_SET 0x000000ff +#define A2W_PLLB_SP0 (A2W_BASE + 0x4e0) +#define A2W_PLLB_SP0_CHENB_LSB 8 +#define A2W_PLLB_SP0_DIV_SET 0x000000ff +#define A2W_PLLA_PER (A2W_BASE + 0x500) +#define A2W_PLLA_PER_CHENB_LSB 8 +#define A2W_PLLA_PER_DIV_SET 0x000000ff +#define A2W_PLLC_PER (A2W_BASE + 0x520) +#define A2W_PLLC_PER_CHENB_LSB 8 +#define A2W_PLLC_PER_DIV_SET 0x000000ff #define A2W_PLLD_PER (A2W_BASE + 0x540) #define A2W_PLLD_PER_CHENB_LSB 8 #define A2W_PLLD_PER_DIV_SET 0x000000ff +#define A2W_PLLH_PIX (A2W_BASE + 0x560) +#define A2W_PLLH_PIX_CHENB_LSB 8 +#define A2W_PLLH_PIX_DIV_SET 0x000000ff #define A2W_PLLC_CORE1 (A2W_BASE + 0x420) #define A2W_PLLC_CORE1_CHENB_LSB 8 #define A2W_PLLC_CORE1_DIV_SET 0x000000ff +#define A2W_PLLB_SP1 (A2W_BASE + 0x5e0) +#define A2W_PLLB_SP1_CHENB_LSB 8 +#define A2W_PLLB_SP1_DIV_SET 0x000000ff +#define A2W_PLLA_CCP2 (A2W_BASE + 0x600) +#define A2W_PLLA_CCP2_CHENB_LSB 8 +#define A2W_PLLA_CCP2_DIV_SET 0x000000ff #define A2W_PLLC_CORE0 (A2W_BASE + 0x620) #define A2W_PLLC_CORE0_CHENB_LSB 8 #define A2W_PLLC_CORE0_DIV_SET 0x000000ff +#define A2W_PLLD_DSI1 (A2W_BASE + 0x640) +#define A2W_PLLD_DSI1_CHENB_LSB 8 +#define A2W_PLLD_DSI1_DIV_SET 0x000000ff +#define A2W_PLLB_SP2 (A2W_BASE + 0x6e0) +#define A2W_PLLB_SP2_CHENB_LSB 8 +#define A2W_PLLB_SP2_DIV_SET 0x000000ff diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 7f7bae8dac..82e50ead14 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -69,6 +69,55 @@ const struct pll_chan_def pll_chan_def[] = { .div_mask = A2W_PLLA_CORE_DIV_SET, .pll = PLL_A, }, + [PLL_CHAN_APER] = { + .name = "PLLA_PER", + .ctrl = REG32(A2W_PLLA_PER), + .chenb_bit = A2W_PLLA_PER_CHENB_LSB, + .div_mask = A2W_PLLA_PER_DIV_SET, + .pll = PLL_A, + }, + [PLL_CHAN_ADSI0] = { + .name = "PLLA_DSI0", + .ctrl = REG32(A2W_PLLA_DSI0), + .chenb_bit = A2W_PLLA_DSI0_CHENB_LSB, + .div_mask = A2W_PLLA_DSI0_DIV_SET, + .pll = PLL_A, + }, + [PLL_CHAN_ACCP2] = { + .name = "PLLA_CCP2", + .ctrl = REG32(A2W_PLLA_CCP2), + .chenb_bit = A2W_PLLA_CCP2_CHENB_LSB, + .div_mask = A2W_PLLA_CCP2_DIV_SET, + .pll = PLL_A, + }, + [PLL_CHAN_BARM] = { + .name = "PLLB_ARM", + .ctrl = REG32(A2W_PLLB_ARM), + .chenb_bit = A2W_PLLB_ARM_CHENB_LSB, + .div_mask = A2W_PLLB_ARM_DIV_SET, + .pll = PLL_B, + }, + [PLL_CHAN_BSP0] = { + .name = "PLLB_SP0", + .ctrl = REG32(A2W_PLLB_SP0), + .chenb_bit = A2W_PLLB_SP0_CHENB_LSB, + .div_mask = A2W_PLLB_SP0_DIV_SET, + .pll = PLL_B, + }, + [PLL_CHAN_BSP1] = { + .name = "PLLB_SP1", + .ctrl = REG32(A2W_PLLB_SP1), + .chenb_bit = A2W_PLLB_SP1_CHENB_LSB, + .div_mask = A2W_PLLB_SP1_DIV_SET, + .pll = PLL_B, + }, + [PLL_CHAN_BSP2] = { + .name = "PLLB_SP2", + .ctrl = REG32(A2W_PLLB_SP2), + .chenb_bit = A2W_PLLB_SP2_CHENB_LSB, + .div_mask = A2W_PLLB_SP2_DIV_SET, + .pll = PLL_B, + }, [PLL_CHAN_CCORE0] = { .name = "PLLC_CORE0", .ctrl = REG32(A2W_PLLC_CORE0), @@ -90,6 +139,20 @@ const struct pll_chan_def pll_chan_def[] = { .div_mask = A2W_PLLC_CORE2_DIV_SET, .pll = PLL_C, }, + [PLL_CHAN_CPER] = { + .name = "PLLC_PER", + .ctrl = REG32(A2W_PLLC_PER), + .chenb_bit = A2W_PLLC_PER_CHENB_LSB, + .div_mask = A2W_PLLC_PER_DIV_SET, + .pll = PLL_C, + }, + [PLL_CHAN_DCORE] = { + .name = "PLLD_CORE", + .ctrl = REG32(A2W_PLLD_CORE), + .chenb_bit = A2W_PLLD_CORE_CHENB_LSB, + .div_mask = A2W_PLLD_CORE_DIV_SET, + .pll = PLL_D, + }, [PLL_CHAN_DPER] = { .name = "PLLD_PER", .ctrl = REG32(A2W_PLLD_PER), @@ -97,6 +160,34 @@ const struct pll_chan_def pll_chan_def[] = { .div_mask = A2W_PLLD_PER_DIV_SET, .pll = PLL_D, }, + [PLL_CHAN_DDSI0] = { + .name = "PLLD_DSI0", + .ctrl = REG32(A2W_PLLD_DSI0), + .chenb_bit = A2W_PLLD_DSI0_CHENB_LSB, + .div_mask = A2W_PLLD_DSI0_DIV_SET, + .pll = PLL_D, + }, + [PLL_CHAN_DDSI1] = { + .name = "PLLD_DSI1", + .ctrl = REG32(A2W_PLLD_DSI1), + .chenb_bit = A2W_PLLD_DSI1_CHENB_LSB, + .div_mask = A2W_PLLD_DSI1_DIV_SET, + .pll = PLL_D, + }, + [PLL_CHAN_HPIX] = { + .name = "PLLH_PIX", + .ctrl = REG32(A2W_PLLH_PIX), + .chenb_bit = A2W_PLLH_PIX_CHENB_LSB, + .div_mask = A2W_PLLH_PIX_DIV_SET, + .pll = PLL_H, + }, + [PLL_CHAN_HRCAL] = { + .name = "PLLH_RCAL", + .ctrl = REG32(A2W_PLLH_RCAL), + .chenb_bit = A2W_PLLH_RCAL_CHENB_LSB, + .div_mask = A2W_PLLH_RCAL_DIV_SET, + .pll = PLL_H, + }, [PLL_CHAN_HAUX] = { .name = "PLLH_AUX", .ctrl = REG32(A2W_PLLH_AUX), From f926545a3e4b4a60d25209e1d866445ad896f05f Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Wed, 26 Feb 2020 15:38:39 +0100 Subject: [PATCH 032/100] Loop over PLLs and channels in pll_dump --- platform/bcm28xx/pll_read.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 824da3c955..62abf1c7e0 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -107,15 +107,16 @@ static void dump_plldiv2_state(const char *prefix, uint32_t ctrl, uint32_t div) } static int cmd_pll_dump(int argc, const cmd_args *argv) { - dump_pll_state(PLL_A); - dump_pll_state(PLL_B); - uint32_t pllc_freq = dump_pll_state(PLL_C); - if (pllc_freq > 0) { - dump_pll_chan_state(PLL_CHAN_CCORE0); - dump_pll_chan_state(PLL_CHAN_CCORE1); + enum pll pll; + for (pll = 0; pll < PLL_NUM; ++pll) { + uint32_t freq = dump_pll_state(pll); + if (freq > 0) { + enum pll_chan pll_chan; + for (pll_chan = 0; pll_chan < PLL_CHAN_NUM; ++pll_chan) + if (pll_chan_def[pll_chan].pll == pll) + dump_pll_chan_state(pll_chan); + } } - dump_pll_state(PLL_D); - dump_pll_state(PLL_H); dump_plldiv2_state("VPU", CM_VPUCTL, CM_VPUDIV); return 0; From e00822e47311aaea0c80ef7a76f7498df8091d04 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sat, 29 Feb 2020 21:24:48 +0100 Subject: [PATCH 033/100] get_pll_freq: Fix use of pre-dividers The sense of the "dividers" is currently reversed: - bit 14 / 11 in the ANA1 register _doubles_ the resulting PLL frequency, - PDIV field in the PLL_CTRL register divides the resulting frequency by an integer --- platform/bcm28xx/pll_read.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 62abf1c7e0..bb4ecf56e2 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -28,13 +28,14 @@ uint32_t get_pll_freq(enum pll pll) { uint32_t ctrl = *def->ctrl; uint32_t ndiv = ctrl & def->ndiv_mask; uint32_t pdiv = (ctrl & def->pdiv_mask) >> def->pdiv_shift; + if (pdiv == 0) + return 0; uint32_t frac = *def->frac & A2W_PLL_FRAC_MASK; - uint64_t mult1 = (ndiv << 20) | frac; - mult1 *= pdiv; - uint32_t freq = (xtal_freq * mult1) >> 20; - if (BIT_SET(def->ana[1], def->ana1_pdiv_bit)) - freq >>= 1; - return freq; + uint32_t div = (ndiv << 20) | frac; + uint64_t mult1 = (uint64_t)div * xtal_freq / pdiv; + return (BIT_SET(def->ana[1], def->ana1_pdiv_bit)) + ? mult1 >> 19 + : mult1 >> 20; } uint32_t get_pll_chan_freq(enum pll_chan chan) { From b41001720744c3a88601a1eab742eb933350def5 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sat, 29 Feb 2020 22:46:30 +0100 Subject: [PATCH 034/100] handle starting a PLL Some magic values must be written to the PLLx_DIG registers to take a stopped PLL out of RESET. It is also a good idea to hold all PLL channels while doing so. --- .../bcm28xx/include/platform/bcm28xx/pll.h | 16 ++++++- platform/bcm28xx/pll_control.c | 46 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 0358dc4400..46d85569b6 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -13,6 +13,7 @@ enum pll { struct pll_def { char name[8]; volatile uint32_t *ana; + volatile uint32_t *dig; uint32_t enable_bit; // the bit to enable it within A2W_XOSC_CTRL volatile uint32_t *frac; volatile uint32_t *ctrl; @@ -20,6 +21,7 @@ struct pll_def { uint32_t pdiv_mask; unsigned short pdiv_shift; unsigned short ana1_pdiv_bit; + volatile uint32_t *cm_pll; }; extern const struct pll_def pll_def[PLL_NUM]; @@ -62,7 +64,12 @@ struct pll_chan_def { extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; -#define CM_PLLB 0x7e101170 +#define CM_PLLA (CM_BASE + 0x104) +#define CM_PLLC (CM_BASE + 0x108) +#define CM_PLLD (CM_BASE + 0x10C) +#define CM_PLLH (CM_BASE + 0x110) +#define CM_PLLB (CM_BASE + 0x170) + #define CM_PLLB_LOADARM_SET 0x00000001 #define CM_PLLB_HOLDARM_SET 0x00000002 #define CM_PLLB_ANARST_SET 0x00000100 @@ -81,6 +88,12 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PASSWORD 0x5a000000 +#define A2W_PLLA_DIG0 (A2W_BASE + 0x000) +#define A2W_PLLC_DIG0 (A2W_BASE + 0x020) +#define A2W_PLLD_DIG0 (A2W_BASE + 0x040) +#define A2W_PLLH_DIG0 (A2W_BASE + 0x060) +#define A2W_PLLB_DIG0 (A2W_BASE + 0x0e0) + #define A2W_PLLA_ANA0 (A2W_BASE + 0x010) #define A2W_PLLC_ANA0 (A2W_BASE + 0x030) #define A2W_PLLD_ANA0 (A2W_BASE + 0x050) @@ -114,6 +127,7 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLB_CTRL_PDIV_SET 0x00007000 #define A2W_PLLB_CTRL_NDIV_SET 0x000003ff #define A2W_PLLB_CTRL_PDIV_LSB 12 +#define A2W_PLL_CTRL_PRSTN_SET 0x00020000 #define A2W_PLLA_DSI0 (A2W_BASE + 0x300) #define A2W_PLLA_DSI0_CHENB_LSB 8 diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 82e50ead14..106c97d239 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -7,6 +7,7 @@ const struct pll_def pll_def[] = { [PLL_A] = { .name = "PLLA", .ana = REG32(A2W_PLLA_ANA0), + .dig = REG32(A2W_PLLA_DIG0), .enable_bit = A2W_XOSC_CTRL_PLLAEN_SET, .frac = REG32(A2W_PLLA_FRAC), .ctrl = REG32(A2W_PLLA_CTRL), @@ -14,10 +15,12 @@ const struct pll_def pll_def[] = { .pdiv_mask = A2W_PLLA_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLA_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, + .cm_pll = REG32(CM_PLLA), }, [PLL_B] = { .name = "PLLB", .ana = REG32(A2W_PLLB_ANA0), + .dig = REG32(A2W_PLLB_DIG0), .enable_bit = A2W_XOSC_CTRL_PLLBEN_SET, .frac = REG32(A2W_PLLB_FRAC), .ctrl = REG32(A2W_PLLB_CTRL), @@ -25,10 +28,12 @@ const struct pll_def pll_def[] = { .pdiv_mask = A2W_PLLB_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLB_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, + .cm_pll = REG32(CM_PLLB), }, [PLL_C] = { .name = "PLLC", .ana = REG32(A2W_PLLC_ANA0), + .dig = REG32(A2W_PLLC_DIG0), .enable_bit = A2W_XOSC_CTRL_PLLCEN_SET, .frac = REG32(A2W_PLLC_FRAC), .ctrl = REG32(A2W_PLLC_CTRL), @@ -36,10 +41,12 @@ const struct pll_def pll_def[] = { .pdiv_mask = A2W_PLLC_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLC_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, + .cm_pll = REG32(CM_PLLC), }, [PLL_D] = { .name = "PLLD", .ana = REG32(A2W_PLLD_ANA0), + .dig = REG32(A2W_PLLD_DIG0), .enable_bit = A2W_XOSC_CTRL_PLLDEN_SET, .frac = REG32(A2W_PLLD_FRAC), .ctrl = REG32(A2W_PLLD_CTRL), @@ -47,10 +54,12 @@ const struct pll_def pll_def[] = { .pdiv_mask = A2W_PLLD_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLD_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, + .cm_pll = REG32(CM_PLLD), }, [PLL_H] = { .name = "PLLH", .ana = REG32(A2W_PLLH_ANA0), + .dig = REG32(A2W_PLLH_DIG0), .enable_bit = A2W_XOSC_CTRL_PLLCEN_SET, // official firmware does this (?) .frac = REG32(A2W_PLLH_FRAC), .ctrl = REG32(A2W_PLLH_CTRL), @@ -58,6 +67,7 @@ const struct pll_def pll_def[] = { .pdiv_mask = A2W_PLLH_CTRL_PDIV_SET, .pdiv_shift = A2W_PLLH_CTRL_PDIV_LSB, .ana1_pdiv_bit = 11, + .cm_pll = REG32(CM_PLLH), }, }; @@ -197,8 +207,41 @@ const struct pll_chan_def pll_chan_def[] = { }, }; +static void pll_start(enum pll pll) +{ + const struct pll_def *def = &pll_def[pll]; + uint32_t dig[4]; + + dig[3] = def->dig[3]; + dig[2] = def->dig[2]; + dig[1] = def->dig[1]; + dig[0] = def->dig[0]; + + if (pll == PLL_H) { + // CM_PLLH does not contain any HOLD bits + def->dig[3] = A2W_PASSWORD | dig[3]; + def->dig[2] = A2W_PASSWORD | (dig[2] & 0xffffff57); + def->dig[1] = A2W_PASSWORD | dig[1]; + } else { + // set all HOLD bits + *def->cm_pll = CM_PASSWORD | (*def->cm_pll | 0xaa); + def->dig[3] = A2W_PASSWORD | dig[3]; + def->dig[2] = A2W_PASSWORD | (dig[2] & 0xffeffbfe); + def->dig[1] = A2W_PASSWORD | (dig[1] & 0xffffbfff); + } + def->dig[0] = A2W_PASSWORD | dig[0]; + + *def->ctrl = A2W_PASSWORD | (*def->ctrl | A2W_PLL_CTRL_PRSTN_SET); + + def->dig[3] = A2W_PASSWORD | (dig[3] | 0x42); + def->dig[2] = A2W_PASSWORD | dig[2]; + def->dig[1] = A2W_PASSWORD | dig[1]; + def->dig[0] = A2W_PASSWORD | dig[0]; +} + void configure_pll_b(uint32_t freq) { const struct pll_def *def = &pll_def[PLL_B]; + uint32_t orig_ctrl = *def->ctrl; *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; *def->frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 *def->ctrl = A2W_PASSWORD | 48 | 0x1000; @@ -219,4 +262,7 @@ void configure_pll_b(uint32_t freq) { *REG32(CM_PLLB) = CM_PASSWORD; *REG32(CM_ARMCTL) = CM_PASSWORD | 4 | CM_ARMCTL_ENAB_SET; + + if ((orig_ctrl & A2W_PLL_CTRL_PRSTN_SET) == 0) + pll_start(PLL_B); } From 659558dcd703810bb6fa165cde3473f33b3db994 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 5 Mar 2020 10:21:21 +0100 Subject: [PATCH 035/100] Fix get_pll_freq on RPi4 The prescaler is either not present on a BCM2711, or it works differently. For the record, the PLLC NDIV:FRAC divider is set up to 3 GHz by the firmware as if there was no prescaler. --- platform/bcm28xx/pll_read.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index bb4ecf56e2..dd0d0efcf4 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -32,10 +32,12 @@ uint32_t get_pll_freq(enum pll pll) { return 0; uint32_t frac = *def->frac & A2W_PLL_FRAC_MASK; uint32_t div = (ndiv << 20) | frac; +#ifndef RPI4 + if (BIT_SET(def->ana[1], def->ana1_pdiv_bit)) + div <<= 1; +#endif uint64_t mult1 = (uint64_t)div * xtal_freq / pdiv; - return (BIT_SET(def->ana[1], def->ana1_pdiv_bit)) - ? mult1 >> 19 - : mult1 >> 20; + return mult1 >> 20; } uint32_t get_pll_chan_freq(enum pll_chan chan) { From 6aeb35d5b57b563a6a0c682945d31d1da755e08b Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Fri, 6 Mar 2020 16:53:08 +0100 Subject: [PATCH 036/100] Rename ANARST and DIGRST bit masks These bits are common to all CM_PLL registers. --- platform/bcm28xx/include/platform/bcm28xx/pll.h | 6 ++++-- platform/bcm28xx/pll_control.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 46d85569b6..5dfad51549 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -70,10 +70,12 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_PLLH (CM_BASE + 0x110) #define CM_PLLB (CM_BASE + 0x170) +// Common CM_PLL bits +#define CM_PLL_ANARST 0x00000100 +#define CM_PLL_DIGRST 0x00000200 + #define CM_PLLB_LOADARM_SET 0x00000001 #define CM_PLLB_HOLDARM_SET 0x00000002 -#define CM_PLLB_ANARST_SET 0x00000100 -#define CM_PLLB_DIGRST_SET 0x00000200 #define CM_ARMCTL 0x7e1011b0 #define CM_ARMCTL_ENAB_SET 0x00000010 diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 106c97d239..890781c968 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -257,8 +257,8 @@ void configure_pll_b(uint32_t freq) { *REG32(A2W_PLLB_ARM) = A2W_PASSWORD | 2; - *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET | CM_PLLB_LOADARM_SET; - *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLL_DIGRST | CM_PLL_ANARST | CM_PLLB_HOLDARM_SET | CM_PLLB_LOADARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLL_DIGRST | CM_PLL_ANARST | CM_PLLB_HOLDARM_SET; *REG32(CM_PLLB) = CM_PASSWORD; *REG32(CM_ARMCTL) = CM_PASSWORD | 4 | CM_ARMCTL_ENAB_SET; From ebd096154e05059d5099f816b9542b88f896a07c Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Fri, 6 Mar 2020 20:11:46 +0100 Subject: [PATCH 037/100] Consolidate common PLL control register bits Since the PDIV field and PRSTN bit are found on the same positions in all PLLs, one single define is sufficient. It may even allow some optimizations in the compiler. --- .../bcm28xx/include/platform/bcm28xx/pll.h | 18 +++++------------- platform/bcm28xx/pll_control.c | 18 ++++-------------- platform/bcm28xx/pll_read.c | 2 +- 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 5dfad51549..59a1599b47 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -18,8 +18,6 @@ struct pll_def { volatile uint32_t *frac; volatile uint32_t *ctrl; uint32_t ndiv_mask; - uint32_t pdiv_mask; - unsigned short pdiv_shift; unsigned short ana1_pdiv_bit; volatile uint32_t *cm_pll; }; @@ -109,27 +107,21 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLB_FRAC (A2W_BASE + 0x2e0) #define A2W_PLL_FRAC_MASK 0x000fffff +// Common A2W_PLL_CTRL bits +#define A2W_PLL_CTRL_PDIV_MASK 0x00007000 +#define A2W_PLL_CTRL_PDIV_LSB 12 +#define A2W_PLL_CTRL_PRSTN 0x00020000 + #define A2W_PLLA_CTRL (A2W_BASE + 0x100) -#define A2W_PLLA_CTRL_PDIV_SET 0x00007000 #define A2W_PLLA_CTRL_NDIV_SET 0x000003ff -#define A2W_PLLA_CTRL_PDIV_LSB 12 #define A2W_PLLC_CTRL (A2W_BASE + 0x120) -#define A2W_PLLC_CTRL_PDIV_SET 0x00007000 #define A2W_PLLC_CTRL_NDIV_SET 0x000003ff -#define A2W_PLLC_CTRL_PDIV_LSB 12 #define A2W_PLLD_CTRL (A2W_BASE + 0x140) -#define A2W_PLLD_CTRL_PDIV_SET 0x00007000 #define A2W_PLLD_CTRL_NDIV_SET 0x000003ff -#define A2W_PLLD_CTRL_PDIV_LSB 12 #define A2W_PLLH_CTRL (A2W_BASE + 0x160) -#define A2W_PLLH_CTRL_PDIV_SET 0x00007000 #define A2W_PLLH_CTRL_NDIV_SET 0x000000ff -#define A2W_PLLH_CTRL_PDIV_LSB 12 #define A2W_PLLB_CTRL (A2W_BASE + 0x1e0) -#define A2W_PLLB_CTRL_PDIV_SET 0x00007000 #define A2W_PLLB_CTRL_NDIV_SET 0x000003ff -#define A2W_PLLB_CTRL_PDIV_LSB 12 -#define A2W_PLL_CTRL_PRSTN_SET 0x00020000 #define A2W_PLLA_DSI0 (A2W_BASE + 0x300) #define A2W_PLLA_DSI0_CHENB_LSB 8 diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 890781c968..bc2dc0a09b 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -12,8 +12,6 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLA_FRAC), .ctrl = REG32(A2W_PLLA_CTRL), .ndiv_mask = A2W_PLLA_CTRL_NDIV_SET, - .pdiv_mask = A2W_PLLA_CTRL_PDIV_SET, - .pdiv_shift = A2W_PLLA_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, .cm_pll = REG32(CM_PLLA), }, @@ -25,8 +23,6 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLB_FRAC), .ctrl = REG32(A2W_PLLB_CTRL), .ndiv_mask = A2W_PLLB_CTRL_NDIV_SET, - .pdiv_mask = A2W_PLLB_CTRL_PDIV_SET, - .pdiv_shift = A2W_PLLB_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, .cm_pll = REG32(CM_PLLB), }, @@ -38,8 +34,6 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLC_FRAC), .ctrl = REG32(A2W_PLLC_CTRL), .ndiv_mask = A2W_PLLC_CTRL_NDIV_SET, - .pdiv_mask = A2W_PLLC_CTRL_PDIV_SET, - .pdiv_shift = A2W_PLLC_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, .cm_pll = REG32(CM_PLLC), }, @@ -51,8 +45,6 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLD_FRAC), .ctrl = REG32(A2W_PLLD_CTRL), .ndiv_mask = A2W_PLLD_CTRL_NDIV_SET, - .pdiv_mask = A2W_PLLD_CTRL_PDIV_SET, - .pdiv_shift = A2W_PLLD_CTRL_PDIV_LSB, .ana1_pdiv_bit = 14, .cm_pll = REG32(CM_PLLD), }, @@ -64,8 +56,6 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLH_FRAC), .ctrl = REG32(A2W_PLLH_CTRL), .ndiv_mask = A2W_PLLH_CTRL_NDIV_SET, - .pdiv_mask = A2W_PLLH_CTRL_PDIV_SET, - .pdiv_shift = A2W_PLLH_CTRL_PDIV_LSB, .ana1_pdiv_bit = 11, .cm_pll = REG32(CM_PLLH), }, @@ -231,7 +221,7 @@ static void pll_start(enum pll pll) } def->dig[0] = A2W_PASSWORD | dig[0]; - *def->ctrl = A2W_PASSWORD | (*def->ctrl | A2W_PLL_CTRL_PRSTN_SET); + *def->ctrl = A2W_PASSWORD | (*def->ctrl | A2W_PLL_CTRL_PRSTN); def->dig[3] = A2W_PASSWORD | (dig[3] | 0x42); def->dig[2] = A2W_PASSWORD | dig[2]; @@ -245,8 +235,8 @@ void configure_pll_b(uint32_t freq) { *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; *def->frac = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 *def->ctrl = A2W_PASSWORD | 48 | 0x1000; - *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET; - *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLL_DIGRST | CM_PLL_ANARST; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLL_DIGRST | CM_PLL_ANARST | CM_PLLB_HOLDARM_SET; def->ana[3] = A2W_PASSWORD | 0x100; def->ana[2] = A2W_PASSWORD | 0x0; @@ -263,6 +253,6 @@ void configure_pll_b(uint32_t freq) { *REG32(CM_ARMCTL) = CM_PASSWORD | 4 | CM_ARMCTL_ENAB_SET; - if ((orig_ctrl & A2W_PLL_CTRL_PRSTN_SET) == 0) + if ((orig_ctrl & A2W_PLL_CTRL_PRSTN) == 0) pll_start(PLL_B); } diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index dd0d0efcf4..b2de38f3ac 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -27,7 +27,7 @@ uint32_t get_pll_freq(enum pll pll) { const struct pll_def *def = &pll_def[pll]; uint32_t ctrl = *def->ctrl; uint32_t ndiv = ctrl & def->ndiv_mask; - uint32_t pdiv = (ctrl & def->pdiv_mask) >> def->pdiv_shift; + uint32_t pdiv = (ctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_LSB; if (pdiv == 0) return 0; uint32_t frac = *def->frac & A2W_PLL_FRAC_MASK; From ac4ac8bf6d2da959550c768521221c892ec13f01 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Fri, 6 Mar 2020 20:14:23 +0100 Subject: [PATCH 038/100] Move xtal_freq to pll.h This variable can be useful to any clock-related code, so let's have the declaration in a common header file. --- platform/bcm28xx/include/platform/bcm28xx/pll.h | 1 + platform/bcm28xx/include/platform/bcm28xx/pll_read.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 59a1599b47..f1646b4ea8 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -60,6 +60,7 @@ struct pll_chan_def { enum pll pll; }; +extern uint32_t xtal_freq; extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_PLLA (CM_BASE + 0x104) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h index b85c1b6468..1452a096c5 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -11,7 +11,6 @@ uint32_t get_vpu_per_freq(void); uint32_t get_uart_base_freq(void); uint32_t get_pll_freq(enum pll pll); uint32_t get_pll_chan_freq(enum pll_chan chan); -extern uint32_t xtal_freq; #ifdef __cplusplus } #endif From cfdd1eb26b9ecf7005af987f94577c9b2550d250 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Fri, 6 Mar 2020 20:17:33 +0100 Subject: [PATCH 039/100] Rename ana1_pdiv_bit to ana1_prescale_bit I'm quite confident now that this bit controls a prescaler in the feedback loop, so give it a better name, so it cannot be confused with the PDIV field. --- platform/bcm28xx/include/platform/bcm28xx/pll.h | 2 +- platform/bcm28xx/pll_control.c | 10 +++++----- platform/bcm28xx/pll_read.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index f1646b4ea8..af8847d9b2 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -18,7 +18,7 @@ struct pll_def { volatile uint32_t *frac; volatile uint32_t *ctrl; uint32_t ndiv_mask; - unsigned short ana1_pdiv_bit; + unsigned short ana1_prescale_bit; volatile uint32_t *cm_pll; }; diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index bc2dc0a09b..24e28e6766 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -12,7 +12,7 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLA_FRAC), .ctrl = REG32(A2W_PLLA_CTRL), .ndiv_mask = A2W_PLLA_CTRL_NDIV_SET, - .ana1_pdiv_bit = 14, + .ana1_prescale_bit = 14, .cm_pll = REG32(CM_PLLA), }, [PLL_B] = { @@ -23,7 +23,7 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLB_FRAC), .ctrl = REG32(A2W_PLLB_CTRL), .ndiv_mask = A2W_PLLB_CTRL_NDIV_SET, - .ana1_pdiv_bit = 14, + .ana1_prescale_bit = 14, .cm_pll = REG32(CM_PLLB), }, [PLL_C] = { @@ -34,7 +34,7 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLC_FRAC), .ctrl = REG32(A2W_PLLC_CTRL), .ndiv_mask = A2W_PLLC_CTRL_NDIV_SET, - .ana1_pdiv_bit = 14, + .ana1_prescale_bit = 14, .cm_pll = REG32(CM_PLLC), }, [PLL_D] = { @@ -45,7 +45,7 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLD_FRAC), .ctrl = REG32(A2W_PLLD_CTRL), .ndiv_mask = A2W_PLLD_CTRL_NDIV_SET, - .ana1_pdiv_bit = 14, + .ana1_prescale_bit = 14, .cm_pll = REG32(CM_PLLD), }, [PLL_H] = { @@ -56,7 +56,7 @@ const struct pll_def pll_def[] = { .frac = REG32(A2W_PLLH_FRAC), .ctrl = REG32(A2W_PLLH_CTRL), .ndiv_mask = A2W_PLLH_CTRL_NDIV_SET, - .ana1_pdiv_bit = 11, + .ana1_prescale_bit = 11, .cm_pll = REG32(CM_PLLH), }, }; diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index b2de38f3ac..0d7ff8a935 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -33,7 +33,7 @@ uint32_t get_pll_freq(enum pll pll) { uint32_t frac = *def->frac & A2W_PLL_FRAC_MASK; uint32_t div = (ndiv << 20) | frac; #ifndef RPI4 - if (BIT_SET(def->ana[1], def->ana1_pdiv_bit)) + if (BIT_SET(def->ana[1], def->ana1_prescale_bit)) div <<= 1; #endif uint64_t mult1 = (uint64_t)div * xtal_freq / pdiv; From 53dc6ba1365c21ca6e562f1ee1346b70e6134dd2 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Fri, 6 Mar 2020 21:08:43 +0100 Subject: [PATCH 040/100] Put more information into the PLL definitions --- .../bcm28xx/include/platform/bcm28xx/pll.h | 27 +++++++++++++++++++ platform/bcm28xx/pll_control.c | 15 +++++++++++ 2 files changed, 42 insertions(+) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index af8847d9b2..437f303814 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -19,7 +19,10 @@ struct pll_def { volatile uint32_t *ctrl; uint32_t ndiv_mask; unsigned short ana1_prescale_bit; + unsigned short cm_flock_bit; volatile uint32_t *cm_pll; + volatile uint32_t *ana_kaip; + volatile uint32_t *ana_vco; }; extern const struct pll_def pll_def[PLL_NUM]; @@ -69,6 +72,13 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_PLLH (CM_BASE + 0x110) #define CM_PLLB (CM_BASE + 0x170) +#define CM_LOCK (CM_BASE + 0x114) +#define CM_LOCK_FLOCKA_BIT 8 +#define CM_LOCK_FLOCKB_BIT 9 +#define CM_LOCK_FLOCKC_BIT 10 +#define CM_LOCK_FLOCKD_BIT 11 +#define CM_LOCK_FLOCKH_BIT 12 + // Common CM_PLL bits #define CM_PLL_ANARST 0x00000100 #define CM_PLL_DIGRST 0x00000200 @@ -181,3 +191,20 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLB_SP2 (A2W_BASE + 0x6e0) #define A2W_PLLB_SP2_CHENB_LSB 8 #define A2W_PLLB_SP2_DIV_SET 0x000000ff + +// Common A2W_PLL_ANA_KAIP bits +#define A2W_PLL_ANA_KAIP_KA_LSB 8 +#define A2W_PLL_ANA_KAIP_KI_LSB 4 +#define A2W_PLL_ANA_KAIP_KP_LSB 0 + +#define A2W_PLLA_ANA_KAIP (A2W_BASE + 0x310) +#define A2W_PLLC_ANA_KAIP (A2W_BASE + 0x330) +#define A2W_PLLD_ANA_KAIP (A2W_BASE + 0x350) +#define A2W_PLLH_ANA_KAIP (A2W_BASE + 0x370) +#define A2W_PLLB_ANA_KAIP (A2W_BASE + 0x3f0) + +#define A2W_PLLA_ANA_VCO (A2W_BASE + 0x610) +#define A2W_PLLC_ANA_VCO (A2W_BASE + 0x630) +#define A2W_PLLD_ANA_VCO (A2W_BASE + 0x650) +#define A2W_PLLH_ANA_VCO (A2W_BASE + 0x670) +#define A2W_PLLB_ANA_VCO (A2W_BASE + 0x6f0) diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 24e28e6766..60f6e08bef 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -13,7 +13,10 @@ const struct pll_def pll_def[] = { .ctrl = REG32(A2W_PLLA_CTRL), .ndiv_mask = A2W_PLLA_CTRL_NDIV_SET, .ana1_prescale_bit = 14, + .cm_flock_bit = CM_LOCK_FLOCKA_BIT, .cm_pll = REG32(CM_PLLA), + .ana_kaip = REG32(A2W_PLLA_ANA_KAIP), + .ana_vco = REG32(A2W_PLLA_ANA_VCO), }, [PLL_B] = { .name = "PLLB", @@ -24,7 +27,10 @@ const struct pll_def pll_def[] = { .ctrl = REG32(A2W_PLLB_CTRL), .ndiv_mask = A2W_PLLB_CTRL_NDIV_SET, .ana1_prescale_bit = 14, + .cm_flock_bit = CM_LOCK_FLOCKB_BIT, .cm_pll = REG32(CM_PLLB), + .ana_kaip = REG32(A2W_PLLB_ANA_KAIP), + .ana_vco = REG32(A2W_PLLB_ANA_VCO), }, [PLL_C] = { .name = "PLLC", @@ -35,7 +41,10 @@ const struct pll_def pll_def[] = { .ctrl = REG32(A2W_PLLC_CTRL), .ndiv_mask = A2W_PLLC_CTRL_NDIV_SET, .ana1_prescale_bit = 14, + .cm_flock_bit = CM_LOCK_FLOCKC_BIT, .cm_pll = REG32(CM_PLLC), + .ana_kaip = REG32(A2W_PLLC_ANA_KAIP), + .ana_vco = REG32(A2W_PLLC_ANA_VCO), }, [PLL_D] = { .name = "PLLD", @@ -46,7 +55,10 @@ const struct pll_def pll_def[] = { .ctrl = REG32(A2W_PLLD_CTRL), .ndiv_mask = A2W_PLLD_CTRL_NDIV_SET, .ana1_prescale_bit = 14, + .cm_flock_bit = CM_LOCK_FLOCKD_BIT, .cm_pll = REG32(CM_PLLD), + .ana_kaip = REG32(A2W_PLLD_ANA_KAIP), + .ana_vco = REG32(A2W_PLLD_ANA_VCO), }, [PLL_H] = { .name = "PLLH", @@ -57,7 +69,10 @@ const struct pll_def pll_def[] = { .ctrl = REG32(A2W_PLLH_CTRL), .ndiv_mask = A2W_PLLH_CTRL_NDIV_SET, .ana1_prescale_bit = 11, + .cm_flock_bit = CM_LOCK_FLOCKH_BIT, .cm_pll = REG32(CM_PLLH), + .ana_kaip = REG32(A2W_PLLH_ANA_KAIP), + .ana_vco = REG32(A2W_PLLH_ANA_VCO), }, }; From 8429abc677b12ce60184f30086ce0b19a6936ab8 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Fri, 6 Mar 2020 23:46:37 +0100 Subject: [PATCH 041/100] set_pll_freq command Change the PLL frequency. --- .../bcm28xx/include/platform/bcm28xx/pll.h | 22 +++ platform/bcm28xx/pll_control.c | 175 ++++++++++++++++++ 2 files changed, 197 insertions(+) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 437f303814..edd7663d56 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -1,5 +1,7 @@ #pragma once +#define MHZ_TO_HZ(f) ((f)*1000*1000) + enum pll { PLL_A, PLL_B, @@ -105,6 +107,25 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLH_DIG0 (A2W_BASE + 0x060) #define A2W_PLLB_DIG0 (A2W_BASE + 0x0e0) +#define A2W_PLL_ANA3_KA_LSB 7 +#define A2W_PLL_ANA3_KA_MASK (BIT_MASK(3) << A2W_PLL_ANA3_KA_LSB) +#define A2W_PLL_ANA1_KI_LSB 19 +#define A2W_PLL_ANA1_KI_MASK (BIT_MASK(3) << A2W_PLL_ANA1_KI_LSB) +#define A2W_PLL_ANA1_KP_LSB 15 +#define A2W_PLL_ANA1_KP_MASK (BIT_MASK(4) << A2W_PLL_ANA1_KP_LSB) + +// PLLH is special +#define A2W_PLLH_ANA0_KA_LSB 19 +#define A2W_PLLH_ANA0_KA_MASK (BIT_MASK(3) << A2W_PLLH_ANA0_KA_LSB) +#define A2W_PLLH_ANA0_KI_LO_LSB 22 +#define A2W_PLLH_ANA1_KI_LO_BITS 2 +#define A2W_PLLH_ANA0_KI_LO_MASK (BIT_MASK(A2W_PLLH_ANA1_KI_LO_BITS) \ + << A2W_PLLH_ANA0_KI_LO_LSB) +#define A2W_PLLH_ANA1_KI_HI_LSB 0 +#define A2W_PLLH_ANA1_KI_HI_MASK (BIT_MASK(1) << A2W_PLLH_ANA1_KI_HI_LSB) +#define A2W_PLLH_ANA1_KP_LSB 1 +#define A2W_PLLH_ANA1_KP_MASK (BIT_MASK(4) << A2W_PLLH_ANA1_KP_LSB) + #define A2W_PLLA_ANA0 (A2W_BASE + 0x010) #define A2W_PLLC_ANA0 (A2W_BASE + 0x030) #define A2W_PLLD_ANA0 (A2W_BASE + 0x050) @@ -121,6 +142,7 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; // Common A2W_PLL_CTRL bits #define A2W_PLL_CTRL_PDIV_MASK 0x00007000 #define A2W_PLL_CTRL_PDIV_LSB 12 +#define A2W_PLL_CTRL_PWRDN 0x00010000 #define A2W_PLL_CTRL_PRSTN 0x00020000 #define A2W_PLLA_CTRL (A2W_BASE + 0x100) diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 60f6e08bef..054d39fc6d 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -1,8 +1,18 @@ #include +#include +#include #include #include #include +#define PLL_MAX_LOCKWAIT 1000 + +static int cmd_set_pll_freq(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("set_pll_freq", "set pll frequency", &cmd_set_pll_freq) +STATIC_COMMAND_END(pll_control); + const struct pll_def pll_def[] = { [PLL_A] = { .name = "PLLA", @@ -244,6 +254,161 @@ static void pll_start(enum pll pll) def->dig[0] = A2W_PASSWORD | dig[0]; } +#ifdef RPI4 +static uint32_t saved_ana_vco[PLL_NUM] = { + [PLL_A] = 2, + [PLL_B] = 2, + [PLL_C] = 2, + [PLL_D] = 2, +}; +#endif + +int set_pll_freq(enum pll pll, uint32_t freq) { + const struct pll_def *def = &pll_def[pll]; + bool was_prescaled; + bool is_prescaled; + bool was_off; + + if (!freq) { + *def->cm_pll = CM_PASSWORD | CM_PLL_ANARST; + *def->ctrl = A2W_PASSWORD | A2W_PLL_CTRL_PWRDN; + return 0; + } + + was_off = !(*def->ctrl & A2W_PLL_CTRL_PRSTN); + +#if RPI4 + uint32_t ana_vco = saved_ana_vco[pll]; + was_prescaled = BIT_SET(ana_vco, 4); +#else + uint32_t ana3 = def->ana[3]; + uint32_t ana2 = def->ana[2]; + uint32_t ana1 = def->ana[1]; + uint32_t ana0 = def->ana[0]; + was_prescaled = BIT_SET(ana1, def->ana1_prescale_bit); +#endif + + /* Divider is a fixed-point number with a 20-bit fractional part */ + uint32_t div = (((uint64_t)freq << 20) + xtal_freq / 2) / xtal_freq; + +#if RPI4 + is_prescaled = freq > MHZ_TO_HZ(1600); +#else + is_prescaled = freq > MHZ_TO_HZ(1750); + if (is_prescaled) + div = (div + 1) >> 1; +#endif + + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; + +#ifdef RPI4 + if (!was_off) { + ana_vco |= 0x10000UL; + *def->ana_vco = A2W_PASSWORD | ana_vco; + } +#endif + +#ifndef RPI4 + // PLLs with a prescaler will set all ANA registers, because there + // is no other way to manipulate the prescaler enable bit. Since + // these registers also contain KA, KI and KP, their new values + // must be set here, not through a write to A2W_PLLx_ANA_KAIP. + if (pll == PLL_H) { + ana0 = (ana0 & ~A2W_PLLH_ANA0_KA_MASK & ~A2W_PLLH_ANA0_KI_LO_MASK) + | (2UL << A2W_PLLH_ANA0_KA_LSB) + | (2UL << A2W_PLLH_ANA0_KI_LO_LSB); + ana1 = (ana1 & ~A2W_PLLH_ANA1_KI_HI_MASK & ~A2W_PLLH_ANA1_KP_MASK) + | (0UL << A2W_PLLH_ANA1_KI_HI_MASK) + | (6UL << A2W_PLLH_ANA1_KP_LSB); + } else { + ana3 = (ana3 & ~A2W_PLL_ANA3_KA_MASK) + | (2UL << A2W_PLL_ANA3_KA_LSB); + ana1 = (ana1 & A2W_PLL_ANA1_KI_MASK & ~A2W_PLL_ANA1_KP_MASK) + | (2UL << A2W_PLL_ANA1_KI_LSB) + | (8UL << A2W_PLL_ANA1_KP_LSB); + } +#endif + + if (!was_prescaled || is_prescaled) { +#ifdef RPI4 + if (is_prescaled) { + *def->ana_kaip = A2W_PASSWORD + | (0 << A2W_PLL_ANA_KAIP_KA_LSB) + | (2 << A2W_PLL_ANA_KAIP_KI_LSB) + | (3 << A2W_PLL_ANA_KAIP_KP_LSB); + ana_vco |= 0x10UL; + *def->ana_vco = A2W_PASSWORD | ana_vco; + } else { + *def->ana_kaip = A2W_PASSWORD + | (0 << A2W_PLL_ANA_KAIP_KA_LSB) + | (2 << A2W_PLL_ANA_KAIP_KI_LSB) + | (5 << A2W_PLL_ANA_KAIP_KP_LSB); + ana_vco &= ~0x10UL; + *def->ana_vco = A2W_PASSWORD | ana_vco; + } +#else + if (is_prescaled) + ana1 |= 1UL << def->ana1_prescale_bit; + def->ana[3] = A2W_PASSWORD | ana3; + def->ana[2] = A2W_PASSWORD | ana2; + def->ana[1] = A2W_PASSWORD | ana1; + def->ana[0] = A2W_PASSWORD | ana0; +#endif + } + + *def->ctrl = A2W_PASSWORD + | (*def->ctrl + & ~A2W_PLL_CTRL_PWRDN + & ~A2W_PLL_CTRL_PDIV_MASK + & ~def->ndiv_mask) + | (div >> 20) + | (1 << A2W_PLL_CTRL_PDIV_LSB); + *def->frac = A2W_PASSWORD | (div & A2W_PLL_FRAC_MASK); + + if (was_prescaled && !is_prescaled) { +#ifdef RPI4 + *def->ana_kaip = A2W_PASSWORD + | (0 << A2W_PLL_ANA_KAIP_KA_LSB) + | (2 << A2W_PLL_ANA_KAIP_KI_LSB) + | (5 << A2W_PLL_ANA_KAIP_KP_LSB); + ana_vco &= ~0x10UL; + *def->ana_vco = A2W_PASSWORD | ana_vco; +#else + ana1 &= ~(1UL << def->ana1_prescale_bit); + def->ana[3] = A2W_PASSWORD | ana3; + def->ana[2] = A2W_PASSWORD | ana2; + def->ana[1] = A2W_PASSWORD | ana1; + def->ana[0] = A2W_PASSWORD | ana0; +#endif + } + + *def->cm_pll = CM_PASSWORD | (*def->cm_pll & ~CM_PLL_ANARST); + unsigned lockwait = PLL_MAX_LOCKWAIT; + while (!BIT_SET(*REG32(CM_LOCK), def->cm_flock_bit)) + if (--lockwait == 0) + break; + +#ifdef RPI4 + if (!was_off) { + ana_vco &= ~0x10000UL; + *def->ana_vco = A2W_PASSWORD | ana_vco; + } + saved_ana_vco[pll] = ana_vco; +#endif + + if (!lockwait) { + dprintf(INFO, "%s won't lock\n", def->name); + return -1; + } + + if (was_off) + pll_start(pll); + + dprintf(SPEW, "%s frequency locked after %u iterations\n", + def->name, PLL_MAX_LOCKWAIT - lockwait); + return 0; +} + void configure_pll_b(uint32_t freq) { const struct pll_def *def = &pll_def[PLL_B]; uint32_t orig_ctrl = *def->ctrl; @@ -271,3 +436,13 @@ void configure_pll_b(uint32_t freq) { if ((orig_ctrl & A2W_PLL_CTRL_PRSTN) == 0) pll_start(PLL_B); } + +static int cmd_set_pll_freq(int argc, const cmd_args *argv) { + if (argc != 3) { + printf("usage: set_pll_freq \n"); + return -1; + } + enum pll pll = argv[1].u; + uint32_t freq = argv[2].u; + return set_pll_freq(pll, freq); +} From ba3f97a8ea42022ef1d6a9454c0d7e3106e32fb0 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sat, 7 Mar 2020 16:41:54 +0100 Subject: [PATCH 042/100] PLL control fixes, cleanups and clarifications --- platform/bcm28xx/pll_control.c | 41 ++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 054d39fc6d..0bda2e147f 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -235,14 +235,14 @@ static void pll_start(enum pll pll) if (pll == PLL_H) { // CM_PLLH does not contain any HOLD bits def->dig[3] = A2W_PASSWORD | dig[3]; - def->dig[2] = A2W_PASSWORD | (dig[2] & 0xffffff57); + def->dig[2] = A2W_PASSWORD | (dig[2] & ~0xa8UL); def->dig[1] = A2W_PASSWORD | dig[1]; } else { // set all HOLD bits *def->cm_pll = CM_PASSWORD | (*def->cm_pll | 0xaa); def->dig[3] = A2W_PASSWORD | dig[3]; - def->dig[2] = A2W_PASSWORD | (dig[2] & 0xffeffbfe); - def->dig[1] = A2W_PASSWORD | (dig[1] & 0xffffbfff); + def->dig[2] = A2W_PASSWORD | (dig[2] & ~0x100401UL); + def->dig[1] = A2W_PASSWORD | (dig[1] & ~0x4000UL); } def->dig[0] = A2W_PASSWORD | dig[0]; @@ -288,17 +288,22 @@ int set_pll_freq(enum pll pll, uint32_t freq) { was_prescaled = BIT_SET(ana1, def->ana1_prescale_bit); #endif - /* Divider is a fixed-point number with a 20-bit fractional part */ + // Divider is a fixed-point number with a 20-bit fractional part. uint32_t div = (((uint64_t)freq << 20) + xtal_freq / 2) / xtal_freq; #if RPI4 is_prescaled = freq > MHZ_TO_HZ(1600); #else is_prescaled = freq > MHZ_TO_HZ(1750); - if (is_prescaled) + if (is_prescaled) { div = (div + 1) >> 1; + ana1 |= 1UL << def->ana1_prescale_bit; + } else { + ana1 &= ~(1UL << def->ana1_prescale_bit); + } #endif + // Unmask the reference clock from the crystal oscillator. *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | def->enable_bit; #ifdef RPI4 @@ -329,6 +334,18 @@ int set_pll_freq(enum pll pll, uint32_t freq) { } #endif + // The Linux driver manipulates the prescaler bit before setting + // a new NDIV if the prescaler is being turned _OFF_. + // I believe it is a bug. + // The programmable divider in a BCM283x apparently cannot cope + // with frequencies above 1750 MHz. This is the reason for adding + // an optional prescaler in the feedback path, so the maximum PLL + // frequency can go up to 3.5 GHz, albeit at the cost of precision. + // If the prescaler is turned off, the divider counter will be + // exposed to the full VCO frequency (i.e. above 1750 MHz). + // On BCM2711, bit 4 of ANA_VCO is manipulated after setting the + // new divider if and only if the rate is going from a frequency + // above 1.6 GHz to a frequency less than or equal 1.6 GHz. if (!was_prescaled || is_prescaled) { #ifdef RPI4 if (is_prescaled) { @@ -347,8 +364,6 @@ int set_pll_freq(enum pll pll, uint32_t freq) { *def->ana_vco = A2W_PASSWORD | ana_vco; } #else - if (is_prescaled) - ana1 |= 1UL << def->ana1_prescale_bit; def->ana[3] = A2W_PASSWORD | ana3; def->ana[2] = A2W_PASSWORD | ana2; def->ana[1] = A2W_PASSWORD | ana1; @@ -356,6 +371,8 @@ int set_pll_freq(enum pll pll, uint32_t freq) { #endif } + // Set the PLL multiplier from the oscillator. + *def->frac = A2W_PASSWORD | (div & A2W_PLL_FRAC_MASK); *def->ctrl = A2W_PASSWORD | (*def->ctrl & ~A2W_PLL_CTRL_PWRDN @@ -363,7 +380,6 @@ int set_pll_freq(enum pll pll, uint32_t freq) { & ~def->ndiv_mask) | (div >> 20) | (1 << A2W_PLL_CTRL_PDIV_LSB); - *def->frac = A2W_PASSWORD | (div & A2W_PLL_FRAC_MASK); if (was_prescaled && !is_prescaled) { #ifdef RPI4 @@ -374,7 +390,6 @@ int set_pll_freq(enum pll pll, uint32_t freq) { ana_vco &= ~0x10UL; *def->ana_vco = A2W_PASSWORD | ana_vco; #else - ana1 &= ~(1UL << def->ana1_prescale_bit); def->ana[3] = A2W_PASSWORD | ana3; def->ana[2] = A2W_PASSWORD | ana2; def->ana[1] = A2W_PASSWORD | ana1; @@ -382,7 +397,10 @@ int set_pll_freq(enum pll pll, uint32_t freq) { #endif } + // Take the PLL out of reset. *def->cm_pll = CM_PASSWORD | (*def->cm_pll & ~CM_PLL_ANARST); + + // Wait for the PLL to lock. unsigned lockwait = PLL_MAX_LOCKWAIT; while (!BIT_SET(*REG32(CM_LOCK), def->cm_flock_bit)) if (--lockwait == 0) @@ -424,6 +442,8 @@ void configure_pll_b(uint32_t freq) { def->ana[0] = A2W_PASSWORD | 0x0; // set dig values + if ((orig_ctrl & A2W_PLL_CTRL_PRSTN) == 0) + pll_start(PLL_B); *REG32(A2W_PLLB_ARM) = A2W_PASSWORD | 2; @@ -432,9 +452,6 @@ void configure_pll_b(uint32_t freq) { *REG32(CM_PLLB) = CM_PASSWORD; *REG32(CM_ARMCTL) = CM_PASSWORD | 4 | CM_ARMCTL_ENAB_SET; - - if ((orig_ctrl & A2W_PLL_CTRL_PRSTN) == 0) - pll_start(PLL_B); } static int cmd_set_pll_freq(int argc, const cmd_args *argv) { From 55fb47a94b08d1f235b24af0ee0e4121160a3f0f Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Sun, 8 Mar 2020 23:58:19 +0100 Subject: [PATCH 043/100] I2C raw transfer function Quite useful to research the undocumented internal I2C bus on BCM2711 (bus 7). For example, I can control the PWR LED on my RPi4B like this: Turn off: i2c_xfer 7 0x43 0504 0 Turn on: i2c_xfer 7 0x43 0500 0 --- platform/bcm28xx/i2c.c | 152 ++++++++++++++++++ .../bcm28xx/include/platform/bcm28xx/i2c.h | 35 ++++ platform/bcm28xx/rules.mk | 1 + 3 files changed, 188 insertions(+) create mode 100644 platform/bcm28xx/i2c.c create mode 100644 platform/bcm28xx/include/platform/bcm28xx/i2c.h diff --git a/platform/bcm28xx/i2c.c b/platform/bcm28xx/i2c.c new file mode 100644 index 0000000000..ca39270c0b --- /dev/null +++ b/platform/bcm28xx/i2c.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include + +struct i2c_regs { + uint32_t ctrl; + uint32_t stat; + uint32_t dlen; + uint32_t addr; + uint32_t fifo; + uint32_t div; + uint32_t del; + uint32_t clkt; +}; + +static int cmd_i2c_xfer(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("i2c_xfer", "I2C transfer", &cmd_i2c_xfer) +STATIC_COMMAND_END(i2c); + +static int unhex(char c) { + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static uint32_t i2c_base[] = { + I2C0_BASE, I2C1_BASE, I2C2_BASE, I2C3_BASE, + I2C4_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE, +}; + +static void i2c_clear_fifo(unsigned busnum) { + volatile struct i2c_regs *regs = (struct i2c_regs*) i2c_base[busnum]; + regs->ctrl |= I2C_C_CLEAR0 | I2C_C_CLEAR1; +} + +int i2c_xfer(unsigned busnum, unsigned addr, + char *sendbuf, size_t sendsz, + char *recvbuf, size_t recvsz) { + int ret = 0; + + if (busnum > 7) + return -1; + + volatile struct i2c_regs *regs = (struct i2c_regs*) i2c_base[busnum]; + + regs->ctrl = I2C_C_I2CEN; + regs->stat = I2C_S_CLKT | I2C_S_ERR | I2C_S_DONE; + i2c_clear_fifo(busnum); + regs->addr = addr; + + // Send bytes + if (sendsz) { + regs->dlen = sendsz; + regs->ctrl |= I2C_C_ST; + while (!(regs->stat & (I2C_S_ERR | I2C_S_TA))) + ; + + while(sendsz--) { + while (!(regs->stat & (I2C_S_CLKT | I2C_S_ERR | I2C_S_TXD))) + ; + if (regs->stat & (I2C_S_CLKT | I2C_S_ERR)) { + regs->stat = I2C_S_CLKT | I2C_S_ERR | I2C_S_DONE; + return -1; + } + regs->fifo = *sendbuf++; + } + + while (!(regs->stat & ( (I2C_S_CLKT | I2C_S_ERR | I2C_S_DONE)))) + ; + if ((regs->stat & (I2C_S_CLKT | I2C_S_ERR))) { + while ((regs->stat & I2C_S_TA)) + ; + dprintf(INFO, "Write failed, status 0x%08x\n", regs->stat); + recvsz = 0; + ret = -1; + } + } + + // Receive bytes + if (recvsz) { + regs->dlen = recvsz; + regs->ctrl |= I2C_C_ST | I2C_C_READ; + while (!(regs->stat & (I2C_S_ERR | I2C_S_DONE | I2C_S_TA))) + ; + + while(!(regs->stat & I2C_S_ERR)) { + if ((regs->stat & I2C_S_RXD)) { + *recvbuf++ = regs->fifo; + if (--recvsz == 0) + break; + } + } + if (!recvsz && !regs->dlen) { + while (!(regs->stat & I2C_S_DONE)) + ; + } else { + dprintf(INFO, "Read failed, status 0x%08x\n", regs->stat); + ret = -1; + } + } + + if ((regs->stat & (I2C_S_CLKT | I2C_S_ERR))) { + while ((regs->stat & I2C_S_TA) && !(regs->stat & I2C_S_RXD)) + ; + } + + regs->stat = I2C_S_CLKT | I2C_S_ERR | I2C_S_DONE; + i2c_clear_fifo(busnum); + regs->ctrl = 0; + return ret; +} + +static int cmd_i2c_xfer(int argc, const cmd_args *argv) { + if (argc != 5) { + printf("usage: i2c_xfer \n"); + return -1; + } + unsigned busnum = argv[1].u; + unsigned addr = argv[2].u; + char send_buf[strlen(argv[3].str) / 2]; + size_t recv_len = argv[4].u; + char recv_buf[recv_len]; + const char *p; + char *q; + for (p = argv[3].str, q = send_buf; *p; p += 2) { + if (!p[1]) { + printf("Hex string must have an even number of digits!\n"); + return -1; + } + *q++ = (unhex(p[0]) << 4) | unhex(p[1]); + } + int status = i2c_xfer(busnum, addr, send_buf, q - send_buf, + recv_buf, recv_len); + if (status < 0) { + printf("Transfer failed: %d\n", status); + return -1; + } else { + for (p = recv_buf; p < recv_buf + recv_len; ++p) { + printf("%02x ", *p); + } + printf("\n"); + } + return 0; +} diff --git a/platform/bcm28xx/include/platform/bcm28xx/i2c.h b/platform/bcm28xx/include/platform/bcm28xx/i2c.h new file mode 100644 index 0000000000..c7854e2650 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/i2c.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#define I2C0_BASE (BCM_PERIPH_BASE_VIRT + 0x205000) +#define I2C1_BASE (BCM_PERIPH_BASE_VIRT + 0x804000) +#define I2C2_BASE (BCM_PERIPH_BASE_VIRT + 0x805000) +#define I2C3_BASE (BCM_PERIPH_BASE_VIRT + 0x205600) +#define I2C4_BASE (BCM_PERIPH_BASE_VIRT + 0x205800) +#define I2C5_BASE (BCM_PERIPH_BASE_VIRT + 0x205a00) +#define I2C6_BASE (BCM_PERIPH_BASE_VIRT + 0x205c00) +#define I2C7_BASE (BCM_PERIPH_BASE_VIRT + 0x205e00) + +#define I2C_C_READ 0x00000001 +#define I2C_C_CLEAR0 0x00000010 +#define I2C_C_CLEAR1 0x00000020 +#define I2C_C_ST 0x00000080 +#define I2C_C_I2CEN 0x00008000 + +#define I2C_S_TA 0x00000001 +#define I2C_S_DONE 0x00000002 +#define I2C_S_TXD 0x00000010 +#define I2C_S_RXD 0x00000020 +#define I2C_S_ERR 0x00000100 +#define I2C_S_CLKT 0x00000200 + +#ifdef __cplusplus +extern "C" { +#endif +int i2c_xfer(unsigned busnum, unsigned addr, + char *sendbuf, size_t sendsz, + char *recvbuf, size_t recvsz); +#ifdef __cplusplus +} +#endif diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index a2f05d9682..550c027fa2 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -57,6 +57,7 @@ MODULE_SRCS += \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/pll_read.c \ $(LOCAL_DIR)/pll_control.c \ + $(LOCAL_DIR)/i2c.c \ From da1995d8f212a300e9dfab067d1eb7a23303e073 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Mon, 9 Mar 2020 08:50:33 +0100 Subject: [PATCH 044/100] i2c_set_rate The pre-configured I2C bus rate is too high for MxL7004 on a RPi4 after start4.elf is launched (over 900 kHz). The spec says the maximum SCL clock frequency is 400 kHz, but the firmware uses an even lower value (100 kHz). FWIW 400 kHz does not work on my RPi4B, but maybe the default FEDL/REDL calculation does not satisfy the SCL_H and/or SCL_L period requirements of that chip. Who cares... just use 100 kHz. --- platform/bcm28xx/i2c.c | 27 +++++++++++++++++++ .../bcm28xx/include/platform/bcm28xx/i2c.h | 1 + 2 files changed, 28 insertions(+) diff --git a/platform/bcm28xx/i2c.c b/platform/bcm28xx/i2c.c index ca39270c0b..5bb9f4f7aa 100644 --- a/platform/bcm28xx/i2c.c +++ b/platform/bcm28xx/i2c.c @@ -3,6 +3,7 @@ #include #include #include +#include struct i2c_regs { uint32_t ctrl; @@ -15,10 +16,12 @@ struct i2c_regs { uint32_t clkt; }; +static int cmd_i2c_set_rate(int argc, const cmd_args *argv); static int cmd_i2c_xfer(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("i2c_xfer", "I2C transfer", &cmd_i2c_xfer) +STATIC_COMMAND("i2c_set_rate", "Set I2C rate", &cmd_i2c_set_rate) STATIC_COMMAND_END(i2c); static int unhex(char c) { @@ -36,6 +39,30 @@ static uint32_t i2c_base[] = { I2C4_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE, }; +void i2c_set_rate(unsigned busnum, unsigned long rate) +{ + volatile struct i2c_regs *regs = (struct i2c_regs*) i2c_base[busnum]; + uint32_t base_freq = get_vpu_per_freq(); + uint32_t div = base_freq / rate; + if (div >= (1UL << 16)) + div = 0xffff; + uint32_t fedl = (div >> 4) ?: 1; + uint32_t redl = (div >> 2) ?: 1; + regs->div = div & 0xffffUL; + regs->del = (fedl << 16) | redl; +} + +static int cmd_i2c_set_rate(int argc, const cmd_args *argv) { + if (argc != 3) { + printf("usage: i2c_set_rate \n"); + return -1; + } + unsigned busnum = argv[1].u; + unsigned long rate = argv[2].u; + i2c_set_rate(busnum, rate); + return 0; +} + static void i2c_clear_fifo(unsigned busnum) { volatile struct i2c_regs *regs = (struct i2c_regs*) i2c_base[busnum]; regs->ctrl |= I2C_C_CLEAR0 | I2C_C_CLEAR1; diff --git a/platform/bcm28xx/include/platform/bcm28xx/i2c.h b/platform/bcm28xx/include/platform/bcm28xx/i2c.h index c7854e2650..f158102822 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/i2c.h +++ b/platform/bcm28xx/include/platform/bcm28xx/i2c.h @@ -27,6 +27,7 @@ #ifdef __cplusplus extern "C" { #endif +void i2c_set_rate(unsigned busnum, unsigned long rate); int i2c_xfer(unsigned busnum, unsigned addr, char *sendbuf, size_t sendsz, char *recvbuf, size_t recvsz); From c27e12915e17643895c1e0047002a58b248e9a3d Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 9 Jun 2020 18:45:03 -0300 Subject: [PATCH 045/100] implement sdhost --- platform/bcm28xx/block_device.hpp | 12 +++++++----- platform/bcm28xx/rules.mk | 4 ++-- platform/bcm28xx/sdhost_impl.cpp | 24 +++++++++++++++++++----- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/platform/bcm28xx/block_device.hpp b/platform/bcm28xx/block_device.hpp index f1eae63f65..abfd7ee396 100644 --- a/platform/bcm28xx/block_device.hpp +++ b/platform/bcm28xx/block_device.hpp @@ -17,20 +17,22 @@ Block device. =============================================================================*/ -struct BlockDevice { +#include + +struct BlockDevice : bdev_t { unsigned int block_size; template - inline bool read_block(uint32_t sector, T* dest_buffer) { - return read_block(sector, reinterpret_cast(dest_buffer)); + inline bool real_read_block(bnum_t sector, T* dest_buffer) { + return real_read_block(sector, reinterpret_cast(dest_buffer)); } inline unsigned int get_block_size() { return block_size; } - virtual bool read_block(uint32_t sector, uint32_t* buf) = 0; + bool real_read_block(bnum_t sector, uint32_t* buf); /* called to stop the block device */ - virtual void stop() {} + void stop() {} }; diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 550c027fa2..814da4dc7d 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -56,8 +56,8 @@ MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/pll_read.c \ - $(LOCAL_DIR)/pll_control.c \ - $(LOCAL_DIR)/i2c.c \ + $(LOCAL_DIR)/pll_control.c + #$(LOCAL_DIR)/i2c.c \ diff --git a/platform/bcm28xx/sdhost_impl.cpp b/platform/bcm28xx/sdhost_impl.cpp index 214296bf05..b42e8cdb01 100644 --- a/platform/bcm28xx/sdhost_impl.cpp +++ b/platform/bcm28xx/sdhost_impl.cpp @@ -347,7 +347,7 @@ struct BCM2708SDHost : BlockDevice { } } - virtual bool read_block(uint32_t sector, uint32_t* buf) override { + bool real_read_block(bnum_t sector, uint32_t* buf) { if (!card_ready) panic("card not ready"); @@ -545,7 +545,7 @@ struct BCM2708SDHost : BlockDevice { * looks like a silicon bug to me or a quirk of csd2, who knows */ for (int i = 0; i < 3; i++) { - if (!read_block(0, nullptr)) { + if (!real_read_block(0, nullptr)) { panic("fifo flush cycle %d failed", i); } } @@ -554,7 +554,7 @@ struct BCM2708SDHost : BlockDevice { } } - virtual void stop() override { + void stop() { if (card_ready) { logf("flushing fifo ...\n"); drain_fifo_nowait(); @@ -599,12 +599,26 @@ extern "C" { struct BCM2708SDHost *sdhost = 0; +static ssize_t sdhost_read_block_wrap(struct bdev *bdev, void *buf, bnum_t block, uint count) { + BCM2708SDHost *dev = reinterpret_cast(bdev); + uint32_t *dest = reinterpret_cast(buf); + if (count != 1) panic("tried to read more then 1 sector"); + bool ret = dev->real_read_block(block, dest); + if (ret) { + return sdhost->get_block_size(); + } else { + return -1; + } +} + void rpi_sdhost_init() { sdhost = new BCM2708SDHost; - bdev_t *bdev = new bdev_t; auto blocksize = sdhost->get_block_size(); auto blocks = sdhost->capacity_bytes / blocksize; - //bio_initialize_bdev(bdev, "sdhost", blocksize, blocks, 0, 0, 0); + bio_initialize_bdev(sdhost, "sdhost", blocksize, blocks, 0, NULL, BIO_FLAGS_NONE); + //sdhost->read = sdhost_read_wrap; + sdhost->read_block = sdhost_read_block_wrap; + bio_register_device(sdhost); } static int cmd_sdhost_init(int argc, const cmd_args *argv) { From 73356d1b12150fd420b591702b12e6266cecda63 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 9 Jun 2020 18:45:30 -0300 Subject: [PATCH 046/100] expose dram init as a command --- platform/bcm28xx/rpi-ddr2/sdram.c | 27 ++++++++++++++++++++------- project/rpi3-bootcode.mk | 4 +++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index 741a87867d..5b075779fe 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -18,16 +18,18 @@ VideoCoreIV SDRAM initialization code. =============================================================================*/ -#include -#include +#include "ddr2.h" +#include +#include +#include #include #include -#include -#include -#include -#include +#include #include -#include "ddr2.h" +#include +#include +#include +#include #define ALWAYS_INLINE __attribute__((always_inline)) inline @@ -94,6 +96,12 @@ static const char* lpddr2_manufacturer_name(uint32_t mr) { #define MR8_DENSITY_SHIFT 0x2 #define MR8_DENSITY_MASK (0xF << 0x2) +static int cmd_dram_init(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dram_init", "initialize dram controller", &cmd_dram_init) +STATIC_COMMAND_END(dram); + static enum RamSize lpddr2_size(uint32_t mr) { switch (mr) { case 0x58: @@ -593,3 +601,8 @@ void sdram_init() { init_late(); selftest(); } + +static int cmd_dram_init(int argc, const cmd_args *argv) { + sdram_init(); + return 0; +} diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk index ef4c4750ff..bfb98916ea 100644 --- a/project/rpi3-bootcode.mk +++ b/project/rpi3-bootcode.mk @@ -4,8 +4,10 @@ TARGET := rpi3-vpu ARCH := vc4 MODULES += \ - lib/debugcommands \ app/shell \ + platform/bcm28xx/rpi-ddr2 \ + #platform/bcm28xx/otp \ + #lib/debugcommands \ #app/shell \ #app/tests \ #app/stringtests \ From 67fa6b0e6d5850b11117c347735f743ca78eefb9 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 9 Jun 2020 18:47:40 -0300 Subject: [PATCH 047/100] jitter test --- arch/vc4/arch.c | 37 ++++++++++++++++++++++++++++++---- arch/vc4/intc.c | 2 +- arch/vc4/start.S | 18 +++++++++++++++++ platform/bcm28xx/pll_control.c | 4 ++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index 4df9504a86..c12339238b 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -7,16 +7,20 @@ #include #include #include +#include +#include static int cmd_boot_other_core(int argc, const cmd_args *argv); static int cmd_testit(int argc, const cmd_args *argv); +static int cmd_jitter(int argc, const cmd_args *argv); -static char core2_stack[4096]; +static char core2_stack[512]; uint32_t core2_stack_top = 0; STATIC_COMMAND_START STATIC_COMMAND("boot_other_core", "boot the 2nd vpu core", &cmd_boot_other_core) STATIC_COMMAND("testit", "do some asm tests", &cmd_testit) +STATIC_COMMAND("jitter", "jitter test", &cmd_jitter) STATIC_COMMAND_END(arch); extern uint8_t _fbss; @@ -35,10 +39,11 @@ void arch_early_init(void) { } void arch_init(void) { - uint32_t r28, sp; + uint32_t r28, sp, cpuid; __asm__ volatile ("mov %0, r28" : "=r"(r28)); __asm__ volatile ("mov %0, sp" : "=r"(sp)); - dprintf(INFO, "arch_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); + __asm__ volatile ("version %0" : "=r"(cpuid)); + dprintf(INFO, "arch_init\nr28: 0x%x\nsp: 0x%x\ncpuid: %x\n", r28, sp, cpuid); } void arch_idle(void) { @@ -51,15 +56,25 @@ void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3 void core2_start(void); +volatile uint32_t foo; + static int cmd_boot_other_core(int argc, const cmd_args *argv) { core2_stack_top = (core2_stack + sizeof(core2_stack)) - 4; - *REG32(A2W_PLLC_CORE1) = A2W_PASSWORD | 6; // 3ghz/6 == 500mhz + //*REG32(A2W_PLLC_CORE1) = A2W_PASSWORD | 6; // 3ghz/6 == 500mhz *REG32(IC1_WAKEUP) = &core2_start; + for (int i=0; i<20; i++) { + udelay(2); + printf("%d %d\n", i, foo); + } return 0; } void core2_entry(void) { dprintf(INFO, "core2 says hello\n"); + for (int i=0; i<300; i++) { + udelay(1); + foo = i; + } for (;;); } @@ -72,6 +87,20 @@ static int cmd_testit(int argc, const cmd_args *argv) { return 0; } +void toggle18(void); + +static int cmd_jitter(int argc, const cmd_args *argv) { + //__asm__ volatile("di"); + gpio_config(18, 1); + for (int i=0; i < 10000000; i++) { + toggle18(); + //gpio_set(18,1); + //gpio_set(18,0); + } + //__asm__ volatile("ei"); + return 0; +} + int vc4_atomic_add(volatile int *ptr, int val) { // TODO //spin_lock_saved_state_t state; diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index 090d76c019..d0d46cd98d 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -21,7 +21,7 @@ struct handlerArgPair irq_handlers[64]; // if the highest bit on this addr is set, the cpu will switch into supervisor mode irqType vectorTable[128] __attribute__ ((section(".data.vectorTable"))); -uint8_t irq_stack0[4096]; +uint8_t irq_stack0[1024]; static const char* g_ExceptionNames[] = { "Zero", diff --git a/arch/vc4/start.S b/arch/vc4/start.S index ffc3c1cd00..cbdb2b0bf1 100644 --- a/arch/vc4/start.S +++ b/arch/vc4/start.S @@ -35,6 +35,24 @@ testit: st r4, (r0+12) rts +.global toggle18 +toggle18: + mov r0, 0x7e20001c // set + mov r1, 0x7e200028 // clear + mov r2, 1<<18 + mov r3, 100000000 +loop18: + st r2, (r0) // high + mov r4, 1 + addcmpbne r4, -1, 0, 0 // delay + + st r2, (r1) // low + mov r4, 1 + addcmpbne r4, -1, 0, 0 // delay + + addcmpbne r3,-1,0x0,loop18 // repeat + rts + #ifdef MANUAL_UART manual_uart_cfg: mov r0, 0x7e200004 // GP_FSEL1 diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 0bda2e147f..653d657a5c 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -14,6 +14,7 @@ STATIC_COMMAND("set_pll_freq", "set pll frequency", &cmd_set_pll_freq) STATIC_COMMAND_END(pll_control); const struct pll_def pll_def[] = { +#if 0 [PLL_A] = { .name = "PLLA", .ana = REG32(A2W_PLLA_ANA0), @@ -84,9 +85,11 @@ const struct pll_def pll_def[] = { .ana_kaip = REG32(A2W_PLLH_ANA_KAIP), .ana_vco = REG32(A2W_PLLH_ANA_VCO), }, +#endif }; const struct pll_chan_def pll_chan_def[] = { +#if 0 [PLL_CHAN_ACORE] = { .name = "PLLA_CORE", .ctrl = REG32(A2W_PLLA_CORE), @@ -220,6 +223,7 @@ const struct pll_chan_def pll_chan_def[] = { .div_mask = A2W_PLLH_AUX_DIV_SET, .pll = PLL_H, }, +#endif }; static void pll_start(enum pll pll) From 453f4efa82a13c250d175f0d53d4be52a9b8b982 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 23 Aug 2020 05:55:15 -0300 Subject: [PATCH 048/100] implement clock measuring --- .../bcm28xx/include/platform/bcm28xx/pll.h | 4 + platform/bcm28xx/pll_read.c | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index edd7663d56..2051d03a57 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -68,6 +68,10 @@ struct pll_chan_def { extern uint32_t xtal_freq; extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; +#define CM_TCNTCTL (CM_BASE + 0x0c0) +#define CM_TCNTCNT (CM_BASE + 0x0c4) +#define CM_OSCCOUNT (CM_BASE + 0x100) + #define CM_PLLA (CM_BASE + 0x104) #define CM_PLLC (CM_BASE + 0x108) #define CM_PLLD (CM_BASE + 0x10C) diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 0d7ff8a935..dcf00a598b 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -6,13 +6,18 @@ #include #include #include +#include uint32_t xtal_freq; static int cmd_pll_dump(int argc, const cmd_args *argv); +static int cmd_measure_clock(int argc, const cmd_args *argv); +static int cmd_measure_clocks(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dump_pll_state", "print all pll state", &cmd_pll_dump) +STATIC_COMMAND("measure_clock", "measure an internal clock rate", &cmd_measure_clock) +STATIC_COMMAND("measure_clocks", "measure all internal clocks", &cmd_measure_clocks) STATIC_COMMAND_END(pll); uint32_t get_vpu_per_freq(void) { @@ -124,3 +129,72 @@ static int cmd_pll_dump(int argc, const cmd_args *argv) { dump_plldiv2_state("VPU", CM_VPUCTL, CM_VPUDIV); return 0; } + +// based on https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/clk/bcm/clk-bcm2835.c#L356 +#define CM_KILL 0x40 +#define CM_BUSY 0x80 +#define CM_SRC_MASK 0xf +#define CM_SRC_BITS 4 +#define CM_TCNT_SRC1_SHIFT 12 + +static int measure_clock(int mux) { + *REG32(CM_TCNTCTL) = CM_PASSWORD | CM_KILL; + *REG32(CM_TCNTCTL) = CM_PASSWORD | (mux & CM_SRC_MASK) | (mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT; + *REG32(CM_OSCCOUNT) = CM_PASSWORD | (xtal_freq / 1000); + udelay(1); + while (*REG32(CM_OSCCOUNT)) { + } + + while (*REG32(CM_TCNTCTL) & CM_BUSY) { + } + + int count = *REG32(CM_TCNTCNT); + *REG32(CM_TCNTCNT) = CM_PASSWORD | 0; + return count; +} + +static int cmd_measure_clock(int argc, const cmd_args *argv) { + if (argc != 2) { + puts("error, missing argument"); + // reg offset default-freq when netbooting + puts("1 - H264"); // CM_H264 0x28 + puts("2 - ISP"); // CM_ISP 0x30 + puts("3 - sdram"); // CM_SDC 0xa8 + puts("5 - VPU"); // CM_VPU 0x08 100,000khz + puts("6 - OTP"); // CM_OTP 0x90 4,800khz + puts("9 - ???"); // 500khz + puts("12 - dsi0p"); // CM_DSI0P 0x60 + puts("13 - dsi1p"); // CM_DSI1P 0x160 + puts("14 - cam0"); // CM_CAM0 0x40 + puts("15 - cam1"); // CM_CAM1 0x48 + puts("17 - dpi"); // CM_DPI 0x68 + puts("18 - dsi0e"); // CM_DSI0E 0x58 + puts("19 - dsi1e"); // CM_DSI1E 0x158 + puts("20 - gp0"); // CM_GP0 0x70 + puts("21 - gp1"); // CM_GP1 0x78 25,000khz + puts("22 - hsm"); // CM_HSM 0x88 + puts("23 - pcm"); // CM_PCM 0x98 + puts("24 - pwm"); // CM_PWM 0xa0 + puts("25 - slim"); // CM_SLIM 0xa8 + puts("27 - smi"); // CM_SMI 0xb0 + puts("28 - uart"); // CM_UART 0xf0 1,916khz + puts("29 - vec"); // CM_VEC 0xf8 + puts("30 - ???"); // 44khz + puts("38 - aveo"); // CM_AVEO 0x1b8 + puts("39 - emmc"); // CM_EMMC 0x1c0 + puts("42 - emmc2"); // CM_EMMC2 0x1d0 + return 0; + } + int mux = argv[1].u; + int count = measure_clock(mux); + printf("count is %d\n", count); + return 0; +} + +static int cmd_measure_clocks(int argc, const cmd_args *argv) { + for (int i=0; i<43; i++) { + int count = measure_clock(i); + printf("clock #%d is %d\n", i, count); + } + return 0; +} From 1da15f167e33cf031fa6e98558867c1d64c7c779 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 8 Sep 2020 01:31:44 -0300 Subject: [PATCH 049/100] begin the vc4-stage1 binary it will bring up the DDR2 controller then mount an ext2 fs on SD partition 2 then drop into a shell for testing --- app/vc4-stage1/rules.mk | 15 +++++ app/vc4-stage1/stage1.c | 34 +++++++++++ arch/vc4/arch.c | 6 +- arch/vc4/include/arch/defines.h | 2 +- arch/vc4/intc.c | 10 ++-- arch/vc4/thread.c | 12 ++-- .../include/platform/bcm28xx/sdhost_impl.h | 13 ++++ platform/bcm28xx/print_timestamp.c | 2 +- platform/bcm28xx/sdhost_impl.cpp | 59 +++++++++---------- platform/bcm28xx/uart.c | 6 +- project/vc4-stage1.mk | 13 ++++ 11 files changed, 121 insertions(+), 51 deletions(-) create mode 100644 app/vc4-stage1/rules.mk create mode 100644 app/vc4-stage1/stage1.c create mode 100644 platform/bcm28xx/include/platform/bcm28xx/sdhost_impl.h create mode 100644 project/vc4-stage1.mk diff --git a/app/vc4-stage1/rules.mk b/app/vc4-stage1/rules.mk new file mode 100644 index 0000000000..19dc87a889 --- /dev/null +++ b/app/vc4-stage1/rules.mk @@ -0,0 +1,15 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += \ + lib/partition \ + lib/fs \ + lib/fs/ext2 \ + lib/debugcommands \ + +MODULE_SRCS += \ + $(LOCAL_DIR)/stage1.c \ + +include make/module.mk + diff --git a/app/vc4-stage1/stage1.c b/app/vc4-stage1/stage1.c new file mode 100644 index 0000000000..bb314144b7 --- /dev/null +++ b/app/vc4-stage1/stage1.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static void stage2_dram_init(uint level) { + sdram_init(); + // add 1mb of heap, 1mb from start of ram + novm_add_arena("dram", 0xc0000000 + (1024*1024), 1024*1024); +} + +LK_INIT_HOOK(stage1, &stage2_dram_init, LK_INIT_LEVEL_PLATFORM_EARLY + 1); + +static void stage2_init(const struct app_descriptor *app) { + printf("stage2 init\n"); + bdev_t *sd = rpi_sdhost_init(); + partition_publish("sdhost", 0); + //fs_mount("/boot", "fat32", "sdhostp0"); + int ret = fs_mount("/root", "ext2", "sdhostp1"); + printf("mount status %d\n", ret); +} + +static void stage2_entry(const struct app_descriptor *app, void *args) { + printf("stage2 entry\n"); +} + +APP_START(stage2) + .init = stage2_init, + .entry = stage2_entry, +APP_END diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index c12339238b..e0d76813c4 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -20,7 +20,7 @@ uint32_t core2_stack_top = 0; STATIC_COMMAND_START STATIC_COMMAND("boot_other_core", "boot the 2nd vpu core", &cmd_boot_other_core) STATIC_COMMAND("testit", "do some asm tests", &cmd_testit) -STATIC_COMMAND("jitter", "jitter test", &cmd_jitter) +//STATIC_COMMAND("jitter", "jitter test", &cmd_jitter) STATIC_COMMAND_END(arch); extern uint8_t _fbss; @@ -59,9 +59,9 @@ void core2_start(void); volatile uint32_t foo; static int cmd_boot_other_core(int argc, const cmd_args *argv) { - core2_stack_top = (core2_stack + sizeof(core2_stack)) - 4; + core2_stack_top = (uint32_t)((core2_stack + sizeof(core2_stack)) - 4); //*REG32(A2W_PLLC_CORE1) = A2W_PASSWORD | 6; // 3ghz/6 == 500mhz - *REG32(IC1_WAKEUP) = &core2_start; + *REG32(IC1_WAKEUP) = (uint32_t)(&core2_start); for (int i=0; i<20; i++) { udelay(2); printf("%d %d\n", i, foo); diff --git a/arch/vc4/include/arch/defines.h b/arch/vc4/include/arch/defines.h index 9db873d37c..72019baa51 100644 --- a/arch/vc4/include/arch/defines.h +++ b/arch/vc4/include/arch/defines.h @@ -3,6 +3,6 @@ #define PAGE_SIZE 4096 #define PAGE_SIZE_SHIFT 12 -#define ARCH_DEFAULT_STACK_SIZE 4096 +#define ARCH_DEFAULT_STACK_SIZE 8192 #define CACHE_LINE 32 // TODO, confirm diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index d0d46cd98d..aa81a923fc 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -61,9 +61,9 @@ void intc_init(void) { } // rather then call set_interrupt for each bit in each byte, just blanket clear all // this will disable every hardware irq - volatile uint32_t *maskreg = IC0_BASE + 0x10; + volatile uint32_t *maskreg = (uint32_t*)(IC0_BASE + 0x10); for (int i=0; i<8; i++) maskreg[i] = 0; - maskreg = IC1_BASE + 0x10; + maskreg = (uint32_t*)(IC1_BASE + 0x10); for (int i=0; i<8; i++) maskreg[i] = 0; // https://github.com/hermanhermitage/videocoreiv/wiki/VideoCore-IV-Programmers-Manual#interrupts @@ -87,14 +87,14 @@ void intc_init(void) { } // swi opcode handler for (int i=32; i<=63; i++) { - vectorTable[i] = (uint32_t)fleh_swi; + vectorTable[i] = fleh_swi; } // external interrupts for (int i=64; i<=127; i++) { - vectorTable[i] = (uint32_t)fleh_irq | 1; + vectorTable[i] = (irqType)((uint32_t)fleh_irq | 1); } - uint32_t irq_sp = (irq_stack0 + sizeof(irq_stack0)) - 4; + uint32_t irq_sp = (uint32_t)((irq_stack0 + sizeof(irq_stack0)) - 4); dprintf(INFO, "r28 = 0x%x\nirq_stack0: %p\nsizeof(irq_stack0): %d\n", irq_sp, irq_stack0, sizeof(irq_stack0)); __asm__ volatile ("mov r28, %0": :"r"(irq_sp)); diff --git a/arch/vc4/thread.c b/arch/vc4/thread.c index 90bc75b685..9919d28894 100644 --- a/arch/vc4/thread.c +++ b/arch/vc4/thread.c @@ -1,7 +1,7 @@ #include #include -void vc4_context_switch(uint32_t *oldsp, uint32_t newsp); +void vc4_context_switch(struct arch_thread *oldsp, struct arch_thread *newsp); void arch_context_switch(thread_t *oldthread, thread_t *newthread) { uint32_t r28, sp; @@ -15,10 +15,6 @@ void arch_context_switch(thread_t *oldthread, thread_t *newthread) { //dprintf(INFO, "switched\n\n"); } -void boop() { - dprintf(INFO, "boop\n"); -} - static inline void push(thread_t *t, uint32_t val) { // SP always points to the last valid value in the stack t->arch.sp -= 4; @@ -29,7 +25,7 @@ static inline void push(thread_t *t, uint32_t val) { static void initial_thread_func(void) __NO_RETURN; static void initial_thread_func(void) { thread_t *ct = get_current_thread(); - uint32_t own_sp, sr; + uint32_t own_sp; __asm__ volatile ("mov %0, sp": "=r"(own_sp)); //dprintf(INFO, "thread %p(%s) starting with sp near 0x%x\n", ct, ct->name, own_sp); @@ -41,9 +37,9 @@ static void initial_thread_func(void) { void arch_thread_initialize(thread_t *t) { //printf("thread %p(%s) has a stack of %p+0x%x\n", t, t->name, t->stack, t->stack_size); - t->arch.sp = (t->stack + t->stack_size) - 4; + t->arch.sp = (uint32_t)((t->stack + t->stack_size) - 4); __asm__ volatile ("mov %0, sr": "=r"(t->arch.sr)); - push(t, &initial_thread_func); // lr + push(t, (uint32_t)(&initial_thread_func)); // lr for (int i=6; i<=23; i++) { push(t, 0); // r${i} } diff --git a/platform/bcm28xx/include/platform/bcm28xx/sdhost_impl.h b/platform/bcm28xx/include/platform/bcm28xx/sdhost_impl.h new file mode 100644 index 0000000000..64b5b13b9d --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/sdhost_impl.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bdev_t *rpi_sdhost_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/platform/bcm28xx/print_timestamp.c b/platform/bcm28xx/print_timestamp.c index 0bd7a8c059..53a22e47ad 100644 --- a/platform/bcm28xx/print_timestamp.c +++ b/platform/bcm28xx/print_timestamp.c @@ -5,5 +5,5 @@ void print_timestamp() { uint32_t clock_lo = *REG32(ST_CLO); - printf("%3ld.%06ld ", clock_lo / 1000000, clock_lo % 1000000); + printf("%3d.%06d ", clock_lo / 1000000, clock_lo % 1000000); } diff --git a/platform/bcm28xx/sdhost_impl.cpp b/platform/bcm28xx/sdhost_impl.cpp index b42e8cdb01..890846813f 100644 --- a/platform/bcm28xx/sdhost_impl.cpp +++ b/platform/bcm28xx/sdhost_impl.cpp @@ -30,6 +30,7 @@ SDHOST driver. This used to be known as ALTMMC. #include #include #include +#include extern "C" { #include @@ -96,7 +97,7 @@ struct BCM2708SDHost : BlockDevice { uint32_t cid[4]; uint32_t csd[4]; - uint32_t capacity_bytes; + uint64_t capacity_bytes; uint32_t r[4]; @@ -170,7 +171,7 @@ struct BCM2708SDHost : BlockDevice { GPIO_PULL_SET(pullBatch, 53, kPullUp); gpio_apply_batch(&pullBatch); - logf("pinmux configured for aux0\n"); + //logf("pinmux configured for aux0\n"); } void reset() { @@ -255,7 +256,7 @@ struct BCM2708SDHost : BlockDevice { if (r[0] & MMC_OCR_MEM_READY) break; - logf("waiting for SD (0x%x) ...\n", r[0]); + //logf("waiting for SD (0x%x) ...\n", r[0]); udelay(100); } @@ -290,7 +291,7 @@ struct BCM2708SDHost : BlockDevice { return false; rca = SD_R6_RCA(r); - logf("RCA = 0x%x\n", rca); + //logf("RCA = 0x%x\n", rca); send_136_resp(MMC_SEND_CID, MMC_ARG_RCA(rca)); if (!wait_and_get_response()) @@ -433,24 +434,24 @@ struct BCM2708SDHost : BlockDevice { bool init_card() { char pnm[8]; - uint32_t block_length; + uint64_t block_length; uint32_t clock_div = 0; send_no_resp(MMC_GO_IDLE_STATE); if (!query_voltage_and_type()) { - logf("ERROR: Failed to query card voltage!\n"); + //logf("ERROR: Failed to query card voltage!\n"); return false; } if (!identify_card()) { - logf("ERROR: Failed to identify card!\n"); + //logf("ERROR: Failed to identify card!\n"); return false; } SD_CID_PNM_CPY(cid, pnm); - logf("Detected SD card:\n"); + //logf("Detected SD card:\n"); printf(" Product : %s\n", pnm); if (SD_CSD_CSDVER(csd) == SD_CSD_CSDVER_2_0) { @@ -483,7 +484,7 @@ struct BCM2708SDHost : BlockDevice { printf(" BlockLen: 0x%x\n", block_length); if (!select_card()) { - logf("ERROR: Failed to select card!\n"); + //logf("ERROR: Failed to select card!\n"); return false; } @@ -492,7 +493,7 @@ struct BCM2708SDHost : BlockDevice { * only needed for 1.0 ones, the 2.0 ones have this * fixed at 512. */ - logf("Setting block length to 512 ...\n"); + //logf("Setting block length to 512 ...\n"); send(MMC_SET_BLOCKLEN, 512); if (!wait()) { logf("ERROR: Failed to set block length!\n"); @@ -502,7 +503,7 @@ struct BCM2708SDHost : BlockDevice { block_size = 512; - logf("Card initialization complete: %s %dMB SD%s Card\n", pnm, capacity_bytes >> 20, is_high_capacity ? "HC" : ""); + logf("Card initialization complete: %s %dMB SD%s Card\n", pnm, (uint32_t)(capacity_bytes >> 20), is_high_capacity ? "HC" : ""); /* * this makes some dangerous assumptions that the all csd2 cards are sdio cards @@ -593,32 +594,30 @@ struct BCM2708SDHost : BlockDevice { } }; -extern "C" { - void rpi_sdhost_init(void); -}; - struct BCM2708SDHost *sdhost = 0; static ssize_t sdhost_read_block_wrap(struct bdev *bdev, void *buf, bnum_t block, uint count) { BCM2708SDHost *dev = reinterpret_cast(bdev); - uint32_t *dest = reinterpret_cast(buf); - if (count != 1) panic("tried to read more then 1 sector"); - bool ret = dev->real_read_block(block, dest); - if (ret) { - return sdhost->get_block_size(); - } else { - return -1; + //printf("sdhost_read_block_wrap(..., 0x%x, %d, %d)\n", buf, block, count); + for (int i=0; i(buf + (sdhost->get_block_size() * i)); + bool ret = dev->real_read_block(block + i, dest); + if (!ret) return -1; } + return sdhost->get_block_size() * count; } -void rpi_sdhost_init() { - sdhost = new BCM2708SDHost; - auto blocksize = sdhost->get_block_size(); - auto blocks = sdhost->capacity_bytes / blocksize; - bio_initialize_bdev(sdhost, "sdhost", blocksize, blocks, 0, NULL, BIO_FLAGS_NONE); - //sdhost->read = sdhost_read_wrap; - sdhost->read_block = sdhost_read_block_wrap; - bio_register_device(sdhost); +bdev_t *rpi_sdhost_init() { + if (!sdhost) { + sdhost = new BCM2708SDHost; + auto blocksize = sdhost->get_block_size(); + auto blocks = sdhost->capacity_bytes / blocksize; + bio_initialize_bdev(sdhost, "sdhost", blocksize, blocks, 0, NULL, BIO_FLAGS_NONE); + //sdhost->read = sdhost_read_wrap; + sdhost->read_block = sdhost_read_block_wrap; + bio_register_device(sdhost); + } + return sdhost; } static int cmd_sdhost_init(int argc, const cmd_args *argv) { diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 74d09f4964..ddbc0699a0 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -45,9 +45,9 @@ static cbuf_t uart_rx_buf[NUM_UART]; static int cmd_uart_dump(int argc, const cmd_args *argv); -STATIC_COMMAND_START -STATIC_COMMAND("dump_uart_state", "print uart state relating to baud", &cmd_uart_dump) -STATIC_COMMAND_END(uart); +//STATIC_COMMAND_START +//STATIC_COMMAND("dump_uart_state", "print uart state relating to baud", &cmd_uart_dump) +//STATIC_COMMAND_END(uart); static inline uintptr_t uart_to_ptr(unsigned int n) { switch (n) { diff --git a/project/vc4-stage1.mk b/project/vc4-stage1.mk new file mode 100644 index 0000000000..a9b07274aa --- /dev/null +++ b/project/vc4-stage1.mk @@ -0,0 +1,13 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi3-vpu +ARCH := vc4 + +MODULES += \ + app/vc4-stage1 \ + app/shell \ + platform/bcm28xx/otp \ + platform/bcm28xx/rpi-ddr2 \ + +GLOBAL_DEFINES += BOOTCODE=1 WITH_NO_FP=1 NOVM_MAX_ARENAS=2 NOVM_DEFAULT_ARENA=0 +BOOTCODE := 1 From 573b1a8fa0db3bea86f378e643d9614446e757f6 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 8 Sep 2020 01:59:36 -0300 Subject: [PATCH 050/100] fix release file --- release.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.nix b/release.nix index dd170fb250..a7243647e8 100644 --- a/release.nix +++ b/release.nix @@ -2,6 +2,6 @@ let self = import ./.; in { vc4 = { - inherit (self.vc4) rpi3 rpi4; + inherit (self.vc4) rpi3 rpi4 vc4; }; } From 81eddd771818a7b6e7459430382f63c571e7e1a9 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 8 Sep 2020 02:04:22 -0300 Subject: [PATCH 051/100] add missing default.nix line --- default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/default.nix b/default.nix index aa7d1bbc4f..5ca94083dc 100644 --- a/default.nix +++ b/default.nix @@ -25,6 +25,7 @@ in lib.fix (self: { rpi3.bootcode = vc4.callPackage ./lk.nix { project = "rpi3-bootcode"; }; rpi3.start = vc4.callPackage ./lk.nix { project = "rpi3-start"; }; rpi4.start4 = vc4.callPackage ./lk.nix { project = "rpi4-start4"; }; + vc4.stage1 = vc4.callPackage ./lk.nix { project = "vc4-stage1"; }; }; x86_64 = { inherit (x86_64) uart-manager; From b0b46be215d14350fbe8b96c3546194f178b3546 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 18:41:39 -0300 Subject: [PATCH 052/100] implement 2 stage bootloader --- app/vc4-stage1/rules.mk | 2 +- app/vc4-stage1/stage1.c | 94 +++++++++++++++++-- app/vc4-stage2/rules.mk | 15 +++ app/vc4-stage2/stage2.c | 22 +++++ arch/vc4/arch.c | 14 ++- lib/elf/elf.c | 4 + lib/elf/include/lib/elf_defines.h | 1 + platform/bcm28xx/bootcode.ld | 2 + platform/bcm28xx/include/platform/bcm28xx.h | 6 -- .../bcm28xx/include/platform/bcm28xx/pm.h | 28 ++++++ platform/bcm28xx/platform.c | 10 +- platform/bcm28xx/rpi-ddr2/ddr2.h | 2 - platform/bcm28xx/uart.c | 6 ++ project/vc4-stage1.mk | 1 - project/vc4-stage2.mk | 17 ++++ 15 files changed, 202 insertions(+), 22 deletions(-) create mode 100644 app/vc4-stage2/rules.mk create mode 100644 app/vc4-stage2/stage2.c create mode 100644 platform/bcm28xx/include/platform/bcm28xx/pm.h create mode 100644 project/vc4-stage2.mk diff --git a/app/vc4-stage1/rules.mk b/app/vc4-stage1/rules.mk index 19dc87a889..a0310d7977 100644 --- a/app/vc4-stage1/rules.mk +++ b/app/vc4-stage1/rules.mk @@ -6,7 +6,7 @@ MODULE_DEPS += \ lib/partition \ lib/fs \ lib/fs/ext2 \ - lib/debugcommands \ + lib/elf \ MODULE_SRCS += \ $(LOCAL_DIR)/stage1.c \ diff --git a/app/vc4-stage1/stage1.c b/app/vc4-stage1/stage1.c index bb314144b7..68fb722e3d 100644 --- a/app/vc4-stage1/stage1.c +++ b/app/vc4-stage1/stage1.c @@ -1,11 +1,18 @@ #include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include -#include -#include #include -#include -#include static void stage2_dram_init(uint level) { sdram_init(); @@ -15,13 +22,84 @@ static void stage2_dram_init(uint level) { LK_INIT_HOOK(stage1, &stage2_dram_init, LK_INIT_LEVEL_PLATFORM_EARLY + 1); -static void stage2_init(const struct app_descriptor *app) { - printf("stage2 init\n"); +static ssize_t fs_read_wrapper(struct elf_handle *handle, void *buf, uint64_t offset, size_t len) { + return fs_read_file(handle->read_hook_arg, buf, offset, len); +} + +static wait_queue_t waiter; + +static int waker_entry(wait_queue_t *waiter) { + char c; + int ret = platform_dgetc(&c, true); + if (ret) { + puts("failed to getc\n"); + thread_exit(0); + } + if (c == 'X') { + THREAD_LOCK(state); + wait_queue_wake_all(waiter, false, c); + THREAD_UNLOCK(state); + } + thread_exit(0); +} + +static void load_stage2() { + int ret; + bdev_t *sd = rpi_sdhost_init(); partition_publish("sdhost", 0); //fs_mount("/boot", "fat32", "sdhostp0"); - int ret = fs_mount("/root", "ext2", "sdhostp1"); - printf("mount status %d\n", ret); + ret = fs_mount("/root", "ext2", "sdhostp1"); + if (ret) { + printf("mount failure: %d\n", ret); + return; + } + filehandle *stage2; + ret = fs_open_file("/root/lk.elf", &stage2); + if (ret) { + printf("open failed: %d\n", ret); + return; + } + elf_handle_t *stage2_elf = malloc(sizeof(elf_handle_t)); + ret = elf_open_handle(stage2_elf, fs_read_wrapper, stage2, false); + if (ret) { + printf("failed to elf open: %d\n", ret); + return; + } + ret = elf_load(stage2_elf); + if (ret) { + printf("failed to load elf: %d\n", ret); + return; + } + printf("entrypoing: 0x%x\n", stage2_elf->entry); + fs_close_file(stage2); + elf_close_handle(stage2_elf); + free(stage2_elf); + arch_chain_load(stage2_elf->entry, 0, 0, 0, 0); +} + +static void stage2_init(const struct app_descriptor *app) { + printf("stage2 init\n"); + puts("press X to stop autoboot and go into xmodem mode..."); + wait_queue_init(&waiter); + + thread_t *waker = thread_create("waker", waker_entry, &waiter, DEFAULT_PRIORITY, ARCH_DEFAULT_STACK_SIZE); + thread_resume(waker); + + THREAD_LOCK(state); + int ret = wait_queue_block(&waiter, 10000); + THREAD_UNLOCK(state); + + printf("wait result: %d\n", ret); + + if (ret == 'X') { + puts("going into xmodem mode"); + uint32_t rsts = *REG32(PM_RSTS); + printf("%x\n", rsts); + platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET); + } else { + load_stage2(); + } } static void stage2_entry(const struct app_descriptor *app, void *args) { diff --git a/app/vc4-stage2/rules.mk b/app/vc4-stage2/rules.mk new file mode 100644 index 0000000000..184800bc4e --- /dev/null +++ b/app/vc4-stage2/rules.mk @@ -0,0 +1,15 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += \ + lib/partition \ + lib/fs \ + lib/fs/fat32 \ + lib/fs/ext2 \ + +MODULE_SRCS += \ + $(LOCAL_DIR)/stage2.c \ + +include make/module.mk + diff --git a/app/vc4-stage2/stage2.c b/app/vc4-stage2/stage2.c new file mode 100644 index 0000000000..3e5a19cba3 --- /dev/null +++ b/app/vc4-stage2/stage2.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +static void stage2_init(const struct app_descriptor *app) { + printf("stage2 init\n"); + bdev_t *sd = rpi_sdhost_init(); + partition_publish("sdhost", 0); + //fs_mount("/boot", "fat32", "sdhostp0"); + fs_mount("/root", "ext2", "sdhostp0"); +} + +static void stage2_entry(const struct app_descriptor *app, void *args) { + printf("stage2 entry\n"); +} + +APP_START(stage2) + .init = stage2_init, + .entry = stage2_entry, +APP_END diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index e0d76813c4..c6e6b73540 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -9,6 +9,7 @@ #include #include #include +#include static int cmd_boot_other_core(int argc, const cmd_args *argv); static int cmd_testit(int argc, const cmd_args *argv); @@ -51,7 +52,18 @@ void arch_idle(void) { } void arch_chain_load(void *entry, ulong arg0, ulong arg1, ulong arg2, ulong arg3) { - PANIC_UNIMPLEMENTED; + puts("flushing uart tx and chainloading...\n"); + uart_flush_tx(0); + __asm__ volatile ("mov r0, %0\nmov r1, %1\nmov r2, %2\nmov r3, %3\nbl %4": + : "r"(arg0) + , "r"(arg1) + , "r"(arg2) + , "r"(arg3) + , "r"(entry)); + panic("chainload somehow returned"); +} + +void arch_sync_cache_range(addr_t start, size_t len) { } void core2_start(void); diff --git a/lib/elf/elf.c b/lib/elf/elf.c index 5163419f44..6de7220edc 100644 --- a/lib/elf/elf.c +++ b/lib/elf/elf.c @@ -154,6 +154,10 @@ static int verify_eheader(const void *header) { #elif ARCH_MICROBLAZE if (eheader->e_machine != EM_MICROBLAZE) return ERR_NOT_FOUND; +#elif ARCH_VC4 + printf("%d %d\n", eheader->e_machine, EM_VC4); + if (eheader->e_machine != EM_VC4) + return ERR_NOT_FOUND; #else #error find proper EM_ define for your machine #endif diff --git a/lib/elf/include/lib/elf_defines.h b/lib/elf/include/lib/elf_defines.h index d6e26712e3..5dd475094c 100644 --- a/lib/elf/include/lib/elf_defines.h +++ b/lib/elf/include/lib/elf_defines.h @@ -40,6 +40,7 @@ #define EM_IA_64 50 #define EM_X86_64 62 #define EM_OR1K 92 +#define EM_VC4 137 #define EM_AARCH64 183 #define EM_MICROBLAZE 189 #define EM_ALPHA 0x9026 diff --git a/platform/bcm28xx/bootcode.ld b/platform/bcm28xx/bootcode.ld index c6a8a7e6f9..751026b59a 100644 --- a/platform/bcm28xx/bootcode.ld +++ b/platform/bcm28xx/bootcode.ld @@ -3,6 +3,7 @@ MEMORY { } GROUP(-lgcc) SECTIONS { + _start = .; .vectorTable : { . = 0x0; *(.data.vectorTable) @@ -48,3 +49,4 @@ SECTIONS { } _fstack = ORIGIN(ram) + LENGTH(ram) - 4; } +/* ASSERT((_end - _start) <= LENGTH(ram), "bss wont fit within L2") */ diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 1630df44ca..04dd21e677 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -47,7 +47,6 @@ void print_timestamp(void); #define MPHI_BASE (BCM_PERIPH_BASE_VIRT + 0x6000) #define DMA_BASE (BCM_PERIPH_BASE_VIRT + 0x7000) #define ARM_BASE (BCM_PERIPH_BASE_VIRT + 0xB000) -#define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) #define CM_BASE (BCM_PERIPH_BASE_VIRT + 0x101000) #define PCM_CLOCK_BASE (BCM_PERIPH_BASE_VIRT + 0x101098) #define RNG_BASE (BCM_PERIPH_BASE_VIRT + 0x104000) @@ -91,15 +90,10 @@ void print_timestamp(void); #define IC1_VADDR (IC1_BASE + 0x30) #define IC1_WAKEUP (IC1_BASE + 0x34) -#define PM_PASSWORD 0x5a000000 #define CM_PASSWORD 0x5a000000 #define CM_SRC_OSC 1 #define CM_UARTCTL_FRAC_SET 0x00000200 #define CM_UARTCTL_ENAB_SET 0x00000010 -#define PM_RSTC (PM_BASE + 0x1c) -#define PM_RSTC_WRCFG_CLR 0xffffffcf // mask to keep everything but the watchdog config -#define PM_WDOG (PM_BASE + 0x24) -#define PM_WDOG_MASK 0x00000fff #define ARMCTRL_BASE (ARM_BASE + 0x000) #define ARMCTRL_INTC_BASE (ARM_BASE + 0x200) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pm.h b/platform/bcm28xx/include/platform/bcm28xx/pm.h new file mode 100644 index 0000000000..6e658b0680 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/pm.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) +#define PM_PASSWORD 0x5a000000 + +#define PM_RSTC (PM_BASE + 0x1c) +#define PM_RSTC_WRCFG_CLR 0xffffffcf // mask to keep everything but the watchdog config +// https://github.com/raspberrypi/linux/issues/932 +// docs for RSTS +// definitions from broadcom/bcm2708_chip/cpr_powman.h +// comments from github issue +#define PM_RSTS (PM_BASE + 0x20) +#define PM_RSTS_HADPOR_SET 0x00001000 // bit 12 had power-on reset +#define PM_RSTS_HADSRH_SET 0x00000400 // bit 10 had software hard reset +#define PM_RSTS_HADSRF_SET 0x00000200 // bit 9 had software full reset +#define PM_RSTS_HADSRQ_SET 0x00000100 // bit 8 had software quick reset +#define PM_RSTS_HADWRH_SET 0x00000040 // bit 6 had watchdog hard reset +#define PM_RSTS_HADWRF_SET 0x00000020 // bit 5 had watchdog full reset +#define PM_RSTS_HADWRQ_SET 0x00000010 // bit 4 had watchdog quick reset +#define PM_RSTS_HADDRH_SET 0x00000004 // bit 2 had debugger hard reset +#define PM_RSTS_HADDRF_SET 0x00000002 // bit 1 had debugger full reset +#define PM_RSTS_HADDRQ_SET 0x00000001 // bit 0 had debugger quick reset +#define PM_WDOG (PM_BASE + 0x24) +#define PM_WDOG_MASK 0x00000fff +#define PM_SMPS (PM_BASE + 0x6c) +#define PM_SPAREW (PM_BASE + 0x74) diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 768cd7ea9e..888f2ac92b 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -22,9 +22,10 @@ #endif #include -#include #include #include +#include +#include #if BCM2836 #include @@ -105,12 +106,14 @@ extern void intc_init(void); extern void arm_reset(void); +#ifdef WITH_KERNEL_VM static pmm_arena_t arena = { .name = "sdram", .base = SDRAM_BASE, .size = MEMSIZE, .flags = PMM_ARENA_FLAG_KMAP, }; +#endif void platform_init_mmu_mappings(void) { } @@ -242,13 +245,14 @@ int platform_dgetc(char *c, bool wait) { void platform_halt(platform_halt_action suggested_action, platform_halt_reason reason) { if (suggested_action == HALT_ACTION_REBOOT) { + dprintf(ALWAYS, "waiting for watchdog\n"); + uart_flush_tx(0); + arch_disable_ints(); *REG32(PM_WDOG) = PM_PASSWORD | (1 & PM_WDOG_MASK); uint32_t t = *REG32(PM_RSTC); t &= PM_RSTC_WRCFG_CLR; t |= 0x20; *REG32(PM_RSTC) = PM_PASSWORD | t; - dprintf(ALWAYS, "waiting for watchdog\n"); - arch_disable_ints(); for (;;); } dprintf(ALWAYS, "HALT: spinning forever... (reason = %d)\n", reason); diff --git a/platform/bcm28xx/rpi-ddr2/ddr2.h b/platform/bcm28xx/rpi-ddr2/ddr2.h index 86302eea58..0fef492612 100644 --- a/platform/bcm28xx/rpi-ddr2/ddr2.h +++ b/platform/bcm28xx/rpi-ddr2/ddr2.h @@ -105,8 +105,6 @@ #define A2W_SMPS_LDO0 0x7e1020d0 #define A2W_SMPS_LDO1 0x7e1020d4 -#define PM_SMPS 0x7e10006c - // copied from rpi-open-firmware #define LPDDR2_MR_DEVICE_FEATURE_2 2 #define LPDDR2_MR_IO_CONFIG 3 diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index ddbc0699a0..617a2363c6 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -98,6 +98,7 @@ static enum handler_return uart_irq(void *arg) { } static void uart_flush(int port) { + // waits until tx FIFO has room, but is not flushed fully uintptr_t base = uart_to_ptr(port); while (UARTREG(base, UART_TFR) & 0x20); } @@ -195,6 +196,11 @@ int uart_getc(int port, bool wait) { } void uart_flush_tx(int port) { + // waits until FIFO is empty and the final stop bit has been sent + uintptr_t base = uart_to_ptr(port); + while (!(UARTREG(base, UART_TFR) & 0x80)); + while (UARTREG(base, UART_TFR) & 0x8); + //udelay(250); // ugly hack } void uart_flush_rx(int port) { diff --git a/project/vc4-stage1.mk b/project/vc4-stage1.mk index a9b07274aa..446852f5dc 100644 --- a/project/vc4-stage1.mk +++ b/project/vc4-stage1.mk @@ -5,7 +5,6 @@ ARCH := vc4 MODULES += \ app/vc4-stage1 \ - app/shell \ platform/bcm28xx/otp \ platform/bcm28xx/rpi-ddr2 \ diff --git a/project/vc4-stage2.mk b/project/vc4-stage2.mk new file mode 100644 index 0000000000..421c3f0ff6 --- /dev/null +++ b/project/vc4-stage2.mk @@ -0,0 +1,17 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi3-vpu +ARCH := vc4 + +MODULES += \ + app/vc4-stage2 \ + app/shell \ + platform/bcm28xx/otp \ + #lib/debugcommands \ + lib/cksum \ + app/stringtests \ + app/tests \ + +#ARCH_COMPILEFLAGS += -fPIE +#ARCH_LDFLAGS += --emit-relocs --discard-none +#ARCH_LDFLAGS += --emit-relocs --discard-none --export-dynamic From bc3a35727df2c9aad8c205ce6350b4de48d5cf37 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 18:55:33 -0300 Subject: [PATCH 053/100] clean up alignments in linker script --- platform/bcm28xx/start.ld | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/platform/bcm28xx/start.ld b/platform/bcm28xx/start.ld index 59eef170c4..4a31f677a5 100644 --- a/platform/bcm28xx/start.ld +++ b/platform/bcm28xx/start.ld @@ -24,8 +24,7 @@ SECTIONS { _etext = .; } >ram =0 - .rodata : { - . = ALIGN(4); + .rodata : ALIGN(4) { _frodata = .; *(.rodata .rodata.* .gnu.linkonce.r.*) *(.rodata1) @@ -47,8 +46,9 @@ SECTIONS { *(.data.vectorTable) } >ram - .data : { - . = ALIGN(4); + .rel : { *(.*.rel*) } + + .data : ALIGN(4) { _fdata = .; *(.data .data.* .gnu.linkonce.d.*) *(.data1) @@ -57,8 +57,7 @@ SECTIONS { _edata = .; } >ram - .bss : { - . = ALIGN(4); + .bss : ALIGN(4) { _fbss = .; *(.dynsbss) *(.sbss .sbss.* .gnu.linkonce.sb.*) From ce5757d241cc3b1a866ed8e100f9f341f4287acc Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 19:01:40 -0300 Subject: [PATCH 054/100] redo alignment again --- platform/bcm28xx/start.ld | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platform/bcm28xx/start.ld b/platform/bcm28xx/start.ld index 4a31f677a5..0686f2195d 100644 --- a/platform/bcm28xx/start.ld +++ b/platform/bcm28xx/start.ld @@ -13,7 +13,7 @@ MEMORY { ram (rwx) : ORIGIN = 0xc0000000 + 2M, LENGTH = 20M } SECTIONS { - .text : ALIGN(32) { + .text : { PROVIDE(_start = .); . = ALIGN(4); *(.text .stub .text.* .gnu.linkonce.t.*) @@ -24,7 +24,8 @@ SECTIONS { _etext = .; } >ram =0 - .rodata : ALIGN(4) { + .rodata : { + . = ALIGN(4); _frodata = .; *(.rodata .rodata.* .gnu.linkonce.r.*) *(.rodata1) @@ -48,7 +49,8 @@ SECTIONS { .rel : { *(.*.rel*) } - .data : ALIGN(4) { + .data : { + . = ALIGN(4); _fdata = .; *(.data .data.* .gnu.linkonce.d.*) *(.data1) @@ -57,7 +59,8 @@ SECTIONS { _edata = .; } >ram - .bss : ALIGN(4) { + .bss : { + . = ALIGN(4); _fbss = .; *(.dynsbss) *(.sbss .sbss.* .gnu.linkonce.sb.*) From 7d8e9af1b7f99e31e3854bef5b0cdcf39f7f6310 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 20:09:26 -0300 Subject: [PATCH 055/100] fix use after free --- app/vc4-stage1/stage1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/vc4-stage1/stage1.c b/app/vc4-stage1/stage1.c index 68fb722e3d..a3e1f48c01 100644 --- a/app/vc4-stage1/stage1.c +++ b/app/vc4-stage1/stage1.c @@ -71,11 +71,11 @@ static void load_stage2() { printf("failed to load elf: %d\n", ret); return; } - printf("entrypoing: 0x%x\n", stage2_elf->entry); fs_close_file(stage2); elf_close_handle(stage2_elf); + uint32_t entry = stage2_elf->entry; free(stage2_elf); - arch_chain_load(stage2_elf->entry, 0, 0, 0, 0); + arch_chain_load(entry, 0, 0, 0, 0); } static void stage2_init(const struct app_descriptor *app) { From 0a982f0328013c085206c28775ead9e9af51ff92 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 20:10:52 -0300 Subject: [PATCH 056/100] build stage2 on CI --- default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/default.nix b/default.nix index 5ca94083dc..b1a4c5e4f7 100644 --- a/default.nix +++ b/default.nix @@ -26,6 +26,7 @@ in lib.fix (self: { rpi3.start = vc4.callPackage ./lk.nix { project = "rpi3-start"; }; rpi4.start4 = vc4.callPackage ./lk.nix { project = "rpi4-start4"; }; vc4.stage1 = vc4.callPackage ./lk.nix { project = "vc4-stage1"; }; + vc4.stage2 = vc4.callPackage ./lk.nix { project = "vc4-stage2"; }; }; x86_64 = { inherit (x86_64) uart-manager; From e9a8f0e54ef0a9501db093afe9392c2127667f7a Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 20:19:32 -0300 Subject: [PATCH 057/100] missed a fix in ddr2 driver --- platform/bcm28xx/rpi-ddr2/sdram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index 5b075779fe..6a0fbdfa00 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -25,6 +25,7 @@ VideoCoreIV SDRAM initialization code. #include #include #include +#include #include #include #include From 6396c6ed4b5f84de3b56aa138407fec2d64a6af9 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Thu, 10 Sep 2020 20:28:45 -0300 Subject: [PATCH 058/100] add a hydra-build-products --- lk.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lk.nix b/lk.nix index 42b64b7df2..9211fd2f8d 100644 --- a/lk.nix +++ b/lk.nix @@ -12,5 +12,7 @@ stdenv.mkDerivation { lk.bin $(stat --printf=%s $out/lk.bin) bytes lk.elf $(stat --printf=%s $out/lk.elf) bytes EOF + echo "file binary-dist $out/lk.bin" >> $out/nix-support/hydra-build-products + echo "file binary-dist $out/lk.elf" >> $out/nix-support/hydra-build-products ''; } From 697c38101158a3954a11aee810c40626fc11d818 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 13 Sep 2020 02:50:15 -0300 Subject: [PATCH 059/100] implement xmodem loading of stage2 --- app/vc4-stage1/stage1.c | 139 ++++++++++++++++-- app/vc4-stage2/rules.mk | 3 + arch/vc4/include/arch/arch_ops.h | 4 + arch/vc4/include/arch/defines.h | 2 +- arch/vc4/include/arch/spinlock.h | 2 - arch/vc4/intc.c | 17 ++- arch/vc4/thread.c | 7 +- lib/debug/debug.c | 1 + platform/bcm28xx/include/platform/bcm28xx.h | 10 -- .../bcm28xx/include/platform/bcm28xx/pll.h | 36 +++++ .../include/platform/bcm28xx/pll_read.h | 1 + platform/bcm28xx/platform.c | 60 ++++++++ platform/bcm28xx/pll_read.c | 7 +- platform/bcm28xx/sdhost_impl.cpp | 2 +- platform/bcm28xx/start.ld | 2 +- platform/bcm28xx/uart.c | 5 +- 16 files changed, 253 insertions(+), 45 deletions(-) diff --git a/app/vc4-stage1/stage1.c b/app/vc4-stage1/stage1.c index a3e1f48c01..26e1abf786 100644 --- a/app/vc4-stage1/stage1.c +++ b/app/vc4-stage1/stage1.c @@ -13,11 +13,16 @@ #include #include #include +#include + +#define UNCACHED_RAM 0xc0000000 +#define MB (1024*1024) static void stage2_dram_init(uint level) { sdram_init(); - // add 1mb of heap, 1mb from start of ram - novm_add_arena("dram", 0xc0000000 + (1024*1024), 1024*1024); + uint32_t start = UNCACHED_RAM | (1 * MB); + uint32_t length = 10 * MB; + novm_add_arena("dram", start, length); } LK_INIT_HOOK(stage1, &stage2_dram_init, LK_INIT_LEVEL_PLATFORM_EARLY + 1); @@ -33,17 +38,30 @@ static int waker_entry(wait_queue_t *waiter) { int ret = platform_dgetc(&c, true); if (ret) { puts("failed to getc\n"); - thread_exit(0); + return 0; } if (c == 'X') { + printf("got char 0x%x\n", c); THREAD_LOCK(state); wait_queue_wake_all(waiter, false, c); THREAD_UNLOCK(state); } - thread_exit(0); + return 0; +} + +static void *load_and_run_elf(elf_handle_t *stage2_elf) { + int ret = elf_load(stage2_elf); + if (ret) { + printf("failed to load elf: %d\n", ret); + return; + } + elf_close_handle(stage2_elf); + void *entry = stage2_elf->entry; + free(stage2_elf); + return entry; } -static void load_stage2() { +static void load_stage2(void) { int ret; bdev_t *sd = rpi_sdhost_init(); @@ -66,28 +84,110 @@ static void load_stage2() { printf("failed to elf open: %d\n", ret); return; } - ret = elf_load(stage2_elf); - if (ret) { - printf("failed to load elf: %d\n", ret); - return; - } + void *entry = load_and_run_elf(stage2_elf); fs_close_file(stage2); - elf_close_handle(stage2_elf); - uint32_t entry = stage2_elf->entry; - free(stage2_elf); arch_chain_load(entry, 0, 0, 0, 0); } -static void stage2_init(const struct app_descriptor *app) { +struct xmodem_packet { + uint8_t magic; + uint8_t block_num; + uint8_t block_num_invert; + uint8_t payload[128]; + uint8_t checksum; +} __attribute__((packed)); + +//static_assert(sizeof(struct xmodem_packet) == 132, "xmodem packet malformed"); + +static ssize_t read_repeat(io_handle_t *in, void *buf, ssize_t len) { + ssize_t total_read = 0; + ssize_t ret; + while ((ret = io_read(in, buf, len)) > 0) { + //printf("0X%02x %d\n\n", ((uint8_t*)buf)[0], ret); + len -= ret; + total_read += ret; + buf += ret; + if (len <= 0) return total_read; + } + return -1; +} + +static void xmodem_receive(void) { + size_t capacity = 2 * MB; + void *buffer = malloc(capacity); + size_t used = 0; + struct xmodem_packet *packet = malloc(sizeof(struct xmodem_packet)); + ssize_t ret; + int blockNr = 1; + bool success = false; + + io_write(&console_io, "\x15", 1); + while ((ret = io_read(&console_io, packet, 1)) == 1) { + if (packet->magic == 4) { + puts("R: EOF!"); + success = true; + break; + } + ret = read_repeat(&console_io, &packet->block_num, sizeof(struct xmodem_packet) - 1); + if (ret != (sizeof(struct xmodem_packet)-1)) { + puts("read error"); + break; + } + uint8_t checksum = 0; + for (int i=0; i<128; i++) { + checksum += packet->payload[i]; + } + bool fail = true; + if (packet->checksum == checksum) { + if (packet->block_num_invert == (255 - packet->block_num)) { + if (packet->block_num == (blockNr & 0xff)) { + memcpy(buffer + (128 * (blockNr-1)), packet->payload, 128); + blockNr++; + io_write(&console_io, "\6", 1); + fail = false; + } else if (packet->block_num == ((blockNr - 1) & 0xff)) { // ack was lost, just re-ack + io_write(&console_io, "\6", 1); + } else { + io_write(&console_io, "\x15", 1); + } + } else { // block_invert wrong + io_write(&console_io, "\x15", 1); + } + } else { // wrong checksum + io_write(&console_io, "\x15", 1); + } + if (fail) printf("got packet: %d %d %d %d/%d\n", packet->magic, packet->block_num, packet->block_num_invert, packet->checksum, checksum); + } + printf("final ret was %ld\n", ret); + free(packet); + if (success) { + elf_handle_t *stage2_elf = malloc(sizeof(elf_handle_t)); + ret = elf_open_handle_memory(stage2_elf, buffer, blockNr*128); + if (ret) { + printf("failed to elf open: %d\n", ret); + return; + } + void *entry = load_and_run_elf(stage2_elf); + free(buffer); + arch_chain_load(entry, 0, 0, 0, 0); + return; + } + free(buffer); +} + +static void stage2_core_entry(void *_unused) { + spin_lock_saved_state_t state1; + arch_interrupt_save(&state1, 0); printf("stage2 init\n"); puts("press X to stop autoboot and go into xmodem mode..."); wait_queue_init(&waiter); thread_t *waker = thread_create("waker", waker_entry, &waiter, DEFAULT_PRIORITY, ARCH_DEFAULT_STACK_SIZE); thread_resume(waker); + arch_interrupt_restore(state1, 0); THREAD_LOCK(state); - int ret = wait_queue_block(&waiter, 10000); + int ret = wait_queue_block(&waiter, 100000); THREAD_UNLOCK(state); printf("wait result: %d\n", ret); @@ -96,12 +196,19 @@ static void stage2_init(const struct app_descriptor *app) { puts("going into xmodem mode"); uint32_t rsts = *REG32(PM_RSTS); printf("%x\n", rsts); - platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET); + xmodem_receive(); } else { load_stage2(); } } +static thread_t *stage2_core; + +static void stage2_init(const struct app_descriptor *app) { + stage2_core = thread_create("stage2", stage2_core_entry, 0, DEFAULT_PRIORITY, ARCH_DEFAULT_STACK_SIZE); + thread_resume(stage2_core); +} + static void stage2_entry(const struct app_descriptor *app, void *args) { printf("stage2 entry\n"); } diff --git a/app/vc4-stage2/rules.mk b/app/vc4-stage2/rules.mk index 184800bc4e..08768925d3 100644 --- a/app/vc4-stage2/rules.mk +++ b/app/vc4-stage2/rules.mk @@ -7,6 +7,9 @@ MODULE_DEPS += \ lib/fs \ lib/fs/fat32 \ lib/fs/ext2 \ + lib/debugcommands \ + app/stringtests \ + app/tests \ MODULE_SRCS += \ $(LOCAL_DIR)/stage2.c \ diff --git a/arch/vc4/include/arch/arch_ops.h b/arch/vc4/include/arch/arch_ops.h index 9333f5d960..0828a2e921 100644 --- a/arch/vc4/include/arch/arch_ops.h +++ b/arch/vc4/include/arch/arch_ops.h @@ -35,6 +35,10 @@ static inline int atomic_and(volatile int *ptr, int val) { static inline int atomic_swap(volatile int *ptr, int val) { return __atomic_exchange_n(ptr, val, __ATOMIC_RELAXED); } + +// todo, use global register instead +// register struct thread *current __asm__("r29"); + static inline struct thread *get_current_thread(void) { struct thread *thread_reg; __asm__ volatile("mov %0, r29" : "=r"(thread_reg)); diff --git a/arch/vc4/include/arch/defines.h b/arch/vc4/include/arch/defines.h index 72019baa51..999b2c075d 100644 --- a/arch/vc4/include/arch/defines.h +++ b/arch/vc4/include/arch/defines.h @@ -3,6 +3,6 @@ #define PAGE_SIZE 4096 #define PAGE_SIZE_SHIFT 12 -#define ARCH_DEFAULT_STACK_SIZE 8192 +#define ARCH_DEFAULT_STACK_SIZE (8*1024) #define CACHE_LINE 32 // TODO, confirm diff --git a/arch/vc4/include/arch/spinlock.h b/arch/vc4/include/arch/spinlock.h index 2e252d8524..15ea2ad813 100644 --- a/arch/vc4/include/arch/spinlock.h +++ b/arch/vc4/include/arch/spinlock.h @@ -55,7 +55,6 @@ arch_interrupt_save(spin_lock_saved_state_t *statep, spin_lock_save_flags_t flag if (!arch_ints_disabled()) { state |= SPIN_LOCK_STATE_RESTORE_IRQ; arch_disable_ints(); - //printf("irq was on, disabled\n"); } *statep = state; } @@ -63,7 +62,6 @@ arch_interrupt_save(spin_lock_saved_state_t *statep, spin_lock_save_flags_t flag static inline void arch_interrupt_restore(spin_lock_saved_state_t old_state, spin_lock_save_flags_t flags) { if (old_state & SPIN_LOCK_STATE_RESTORE_IRQ) { - //printf("restoring ints\n"); arch_enable_ints(); } } diff --git a/arch/vc4/intc.c b/arch/vc4/intc.c index aa81a923fc..0637858bb5 100644 --- a/arch/vc4/intc.c +++ b/arch/vc4/intc.c @@ -168,10 +168,14 @@ void print_vpu_state(vc4_saved_state_t* pcb) { void register_int_handler(unsigned int vector, int_handler handler, void *arg) { assert(vector < 64); - __asm__ volatile("di"); + + spin_lock_saved_state_t state; + arch_interrupt_save(&state, 0); + irq_handlers[vector].h = handler; irq_handlers[vector].arg = arg; - __asm__ volatile("ei"); + + arch_interrupt_restore(state, 0); } status_t unmask_interrupt(unsigned int vector) { @@ -211,11 +215,10 @@ void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { uint32_t source = status & 0xFF; enum handler_return ret = INT_NO_RESCHEDULE; - uint32_t r28, sp, sr; - __asm__ volatile ("mov %0, r28" : "=r"(r28)); - __asm__ volatile ("mov %0, sp" : "=r"(sp)); - __asm__ volatile ("mov %0, sr" : "=r"(sr)); - //dprintf(INFO, "sleh_irq\nr28: 0x%x\nsp: 0x%x\nsr: 0x%x\n", r28, sp, sr); + //uint32_t sp, sr; + //__asm__ volatile ("mov %0, sp" : "=r"(sp)); + //__asm__ volatile ("mov %0, sr" : "=r"(sr)); + //dprintf(INFO, "sleh_irq\nsp: 0x%x\nsr: 0x%x\n", sp, sr); //dprintf(INFO, "VPU Received interrupt from source %d\n", source); diff --git a/arch/vc4/thread.c b/arch/vc4/thread.c index 9919d28894..b90ff8eff7 100644 --- a/arch/vc4/thread.c +++ b/arch/vc4/thread.c @@ -47,6 +47,11 @@ void arch_thread_initialize(thread_t *t) { void arch_dump_thread(thread_t *t) { if (t->state != THREAD_RUNNING) { - dprintf(INFO, "\tarch: sp 0x%x\n", t->arch.sp); + dprintf(INFO, "\tarch: sp 0x%x\n\t sr: 0x%x\n", t->arch.sp, t->arch.sr); } + /* else if (t->state == THREAD_RUNNING) { + uint32_t sp; + __asm__ volatile ("mov %0, sp" : "=r"(sp)); + dprintf(INFO, "\tarch: sp ~0x%x\n", sp); + }*/ } diff --git a/lib/debug/debug.c b/lib/debug/debug.c index cc117ca50c..52aed9a11f 100644 --- a/lib/debug/debug.c +++ b/lib/debug/debug.c @@ -25,6 +25,7 @@ void spin(uint32_t usecs) { } void _panic(void *caller, const char *fmt, ...) { + arch_disable_ints(); printf("panic (caller %p): ", caller); va_list ap; diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 04dd21e677..450e8f10e4 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -71,11 +71,6 @@ void print_timestamp(void); #define ST_CHI (ST_BASE + 0x8) #define ST_C0 (ST_BASE + 0xc) -#define CM_VPUCTL (CM_BASE + 0x008) -#define CM_VPUDIV (CM_BASE + 0x00c) -#define CM_UARTCTL (CM_BASE + 0xf0) -#define CM_UARTDIV (CM_BASE + 0xf4) - #define IC0_C (IC0_BASE + 0x0) #define IC0_S (IC0_BASE + 0x4) #define IC0_SRC0 (IC0_BASE + 0x8) @@ -90,11 +85,6 @@ void print_timestamp(void); #define IC1_VADDR (IC1_BASE + 0x30) #define IC1_WAKEUP (IC1_BASE + 0x34) -#define CM_PASSWORD 0x5a000000 -#define CM_SRC_OSC 1 -#define CM_UARTCTL_FRAC_SET 0x00000200 -#define CM_UARTCTL_ENAB_SET 0x00000010 - #define ARMCTRL_BASE (ARM_BASE + 0x000) #define ARMCTRL_INTC_BASE (ARM_BASE + 0x200) #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 2051d03a57..38b843c8b7 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -68,16 +68,41 @@ struct pll_chan_def { extern uint32_t xtal_freq; extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; + +#define CM_SRC_OSC 1 +#define CM_SRC_PLLC_CORE0 5 + +#define CM_PASSWORD 0x5a000000 + +#define CM_VPUCTL (CM_BASE + 0x008) +#define CM_VPUCTL_FRAC_SET 0x00000200 +#define CM_VPUCTL_GATE_SET 0x00000040 +#define CM_VPUDIV (CM_BASE + 0x00c) +#define CM_TIMERCTL (CM_BASE + 0x0e8) +#define CM_TIMERDIV (CM_BASE + 0x0ec) #define CM_TCNTCTL (CM_BASE + 0x0c0) #define CM_TCNTCNT (CM_BASE + 0x0c4) +#define CM_UARTCTL (CM_BASE + 0x0f0) +#define CM_UARTCTL_FRAC_SET 0x00000200 +#define CM_UARTCTL_ENAB_SET 0x00000010 +#define CM_UARTDIV (CM_BASE + 0x0f4) #define CM_OSCCOUNT (CM_BASE + 0x100) #define CM_PLLA (CM_BASE + 0x104) #define CM_PLLC (CM_BASE + 0x108) +#define CM_PLLC_DIGRST_SET 0x00000200 +#define CM_PLLC_HOLDPER_SET 0x00000080 +#define CM_PLLC_HOLDCORE2_SET 0x00000020 +#define CM_PLLC_HOLDCORE1_SET 0x00000008 +#define CM_PLLC_HOLDCORE0_SET 0x00000002 +#define CM_PLLC_LOADCORE0_SET 0x00000001 #define CM_PLLD (CM_BASE + 0x10C) #define CM_PLLH (CM_BASE + 0x110) #define CM_PLLB (CM_BASE + 0x170) + + + #define CM_LOCK (CM_BASE + 0x114) #define CM_LOCK_FLOCKA_BIT 8 #define CM_LOCK_FLOCKB_BIT 9 @@ -85,6 +110,9 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_LOCK_FLOCKD_BIT 11 #define CM_LOCK_FLOCKH_BIT 12 +#define CM_DPICTL_KILL_SET 0x20 +#define CM_DPICTL_BUSY_SET 0x80 + // Common CM_PLL bits #define CM_PLL_ANARST 0x00000100 #define CM_PLL_DIGRST 0x00000200 @@ -111,6 +139,13 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLH_DIG0 (A2W_BASE + 0x060) #define A2W_PLLB_DIG0 (A2W_BASE + 0x0e0) +#define A2W_PLLC_DIG1 (A2W_BASE + 0x024) +#define A2W_PLLC_DIG2 (A2W_BASE + 0x028) +#define A2W_PLLC_DIG3 (A2W_BASE + 0x02c) +#define A2W_PLLC_ANA1 (A2W_BASE + 0x034) +#define A2W_PLLC_ANA2 (A2W_BASE + 0x038) +#define A2W_PLLC_ANA3 (A2W_BASE + 0x03c) + #define A2W_PLL_ANA3_KA_LSB 7 #define A2W_PLL_ANA3_KA_MASK (BIT_MASK(3) << A2W_PLL_ANA3_KA_LSB) #define A2W_PLL_ANA1_KI_LSB 19 @@ -152,6 +187,7 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLA_CTRL (A2W_BASE + 0x100) #define A2W_PLLA_CTRL_NDIV_SET 0x000003ff #define A2W_PLLC_CTRL (A2W_BASE + 0x120) +#define A2W_PLLC_CTRL_PRSTN_SET 0x00020000 #define A2W_PLLC_CTRL_NDIV_SET 0x000003ff #define A2W_PLLD_CTRL (A2W_BASE + 0x140) #define A2W_PLLD_CTRL_NDIV_SET 0x000003ff diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h index 1452a096c5..684edff26d 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -11,6 +11,7 @@ uint32_t get_vpu_per_freq(void); uint32_t get_uart_base_freq(void); uint32_t get_pll_freq(enum pll pll); uint32_t get_pll_chan_freq(enum pll_chan chan); +int measure_clock(int mux); #ifdef __cplusplus } #endif diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 888f2ac92b..5493fc66eb 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -118,6 +118,60 @@ static pmm_arena_t arena = { void platform_init_mmu_mappings(void) { } +static void switch_vpu_to_pllc() { + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLCEN_SET; + + *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | 87380; + *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | 52 | 0x1000; + + *REG32(A2W_PLLC_ANA3) = A2W_PASSWORD | 0x100; + *REG32(A2W_PLLC_ANA2) = A2W_PASSWORD | 0x0; + *REG32(A2W_PLLC_ANA1) = A2W_PASSWORD | 0x144000; + *REG32(A2W_PLLC_ANA0) = A2W_PASSWORD | 0x0; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET; + + /* hold all */ + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET; + + *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x0; + *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x400000; + *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x5; + *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | 52 | 0x555000; + + *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | 52 | 0x1000 | A2W_PLLC_CTRL_PRSTN_SET; + + *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x42; + *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x500401; + *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x4005; + *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | 52 | 0x555000; + + *REG32(A2W_PLLC_CORE0) = A2W_PASSWORD | 2; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET | CM_PLLC_LOADCORE0_SET; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET; + + *REG32(CM_VPUCTL) = CM_PASSWORD | CM_VPUCTL_FRAC_SET | CM_SRC_OSC | CM_VPUCTL_GATE_SET; + *REG32(CM_VPUDIV) = CM_PASSWORD | (4 << 12); + *REG32(CM_VPUCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET; + *REG32(CM_VPUCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET | 0x10; /* ENAB */ + + *REG32(CM_TIMERDIV) = CM_PASSWORD | (19 << 12) | 819; // TODO, look into this timer + *REG32(CM_TIMERCTL) = CM_PASSWORD | CM_SRC_OSC | 0x10; + dprintf(INFO, "VPU now at 500mhz\n"); +} + void platform_early_init(void) { // 19.2mhz for most models // 54mhz for rpi4 @@ -126,6 +180,12 @@ void platform_early_init(void) { intc_init(); +#ifdef VPU + if (xtal_freq == 19200000) { + switch_vpu_to_pllc(); + } +#endif + #if BCM2837 arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 0); diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index dcf00a598b..2c6a400828 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -137,10 +137,11 @@ static int cmd_pll_dump(int argc, const cmd_args *argv) { #define CM_SRC_BITS 4 #define CM_TCNT_SRC1_SHIFT 12 -static int measure_clock(int mux) { +int measure_clock(int mux) { + int divisor = 1000; *REG32(CM_TCNTCTL) = CM_PASSWORD | CM_KILL; *REG32(CM_TCNTCTL) = CM_PASSWORD | (mux & CM_SRC_MASK) | (mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT; - *REG32(CM_OSCCOUNT) = CM_PASSWORD | (xtal_freq / 1000); + *REG32(CM_OSCCOUNT) = CM_PASSWORD | (xtal_freq / divisor); udelay(1); while (*REG32(CM_OSCCOUNT)) { } @@ -150,7 +151,7 @@ static int measure_clock(int mux) { int count = *REG32(CM_TCNTCNT); *REG32(CM_TCNTCNT) = CM_PASSWORD | 0; - return count; + return count * divisor; } static int cmd_measure_clock(int argc, const cmd_args *argv) { diff --git a/platform/bcm28xx/sdhost_impl.cpp b/platform/bcm28xx/sdhost_impl.cpp index 890846813f..fba34de14f 100644 --- a/platform/bcm28xx/sdhost_impl.cpp +++ b/platform/bcm28xx/sdhost_impl.cpp @@ -216,7 +216,7 @@ struct BCM2708SDHost : BlockDevice { get_response(); - printf("Cmd: 0x%x Resp: %08x %08x %08x %08x\n", current_cmd, r[0], r[1], r[2], r[3]); + //printf("Cmd: 0x%x Resp: %08x %08x %08x %08x\n", current_cmd, r[0], r[1], r[2], r[3]); if (*REG32(SH_CMD) & SH_CMD_FAIL_FLAG_SET) { if (*REG32(SH_HSTS) & SDHSTS_ERROR_MASK) { diff --git a/platform/bcm28xx/start.ld b/platform/bcm28xx/start.ld index 0686f2195d..a6ba619403 100644 --- a/platform/bcm28xx/start.ld +++ b/platform/bcm28xx/start.ld @@ -10,7 +10,7 @@ GROUP(-lgcc) MEMORY { /* in the C alias, direct uncached */ - ram (rwx) : ORIGIN = 0xc0000000 + 2M, LENGTH = 20M + ram (rwx) : ORIGIN = 0xc0000000 + 20M, LENGTH = 20M } SECTIONS { .text : { diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 617a2363c6..3cb455cd9c 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -44,6 +44,8 @@ static cbuf_t uart_rx_buf[NUM_UART]; static int cmd_uart_dump(int argc, const cmd_args *argv); +int uart_putc(int port, char c); +void udelay(uint32_t t); //STATIC_COMMAND_START //STATIC_COMMAND("dump_uart_state", "print uart state relating to baud", &cmd_uart_dump) @@ -145,9 +147,6 @@ void uart_init(void) { } } -int uart_putc(int port, char c); -void udelay(uint32_t t); - void uart_init_early(void) { if (*REG32(CM_UARTDIV) == 0) { // CM_UARTDIV can range from 0 to 1023 with a fractional resolution of 1/4096th From 18a4f56dbbe1fc798dca4dd494dbb5c750050164 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 14 Sep 2020 04:01:22 -0300 Subject: [PATCH 060/100] improve stage1 more fix DPI clocks and hsync/vsync generation implement HVS code --- app/vc4-stage1/stage1.c | 25 +++---- app/vc4-stage2/rules.mk | 1 + platform/bcm28xx/dpi/dpi.c | 67 +++++++++++++++++ platform/bcm28xx/dpi/rules.mk | 13 ++++ platform/bcm28xx/hvs/hvs.c | 46 ++++++++++++ .../hvs/include/platform/bcm28xx/hvs.h | 71 ++++++++++++++++++ platform/bcm28xx/hvs/rules.mk | 10 +++ .../bcm28xx/include/platform/bcm28xx/dpi.h | 28 +++++++ .../bcm28xx/include/platform/bcm28xx/pll.h | 32 +++++--- .../include/platform/bcm28xx/pll_read.h | 2 + .../bcm28xx/include/platform/bcm28xx/pv.h | 8 ++ platform/bcm28xx/pixelvalve/pv.c | 60 +++++++++++++++ platform/bcm28xx/pixelvalve/rules.mk | 8 ++ platform/bcm28xx/platform.c | 57 ++++---------- platform/bcm28xx/pll_control.c | 75 +++++++++++++++++++ platform/bcm28xx/pll_read.c | 32 +++++++- 16 files changed, 463 insertions(+), 72 deletions(-) create mode 100644 platform/bcm28xx/dpi/dpi.c create mode 100644 platform/bcm28xx/dpi/rules.mk create mode 100644 platform/bcm28xx/hvs/hvs.c create mode 100644 platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h create mode 100644 platform/bcm28xx/hvs/rules.mk create mode 100644 platform/bcm28xx/include/platform/bcm28xx/dpi.h create mode 100644 platform/bcm28xx/include/platform/bcm28xx/pv.h create mode 100644 platform/bcm28xx/pixelvalve/pv.c create mode 100644 platform/bcm28xx/pixelvalve/rules.mk diff --git a/app/vc4-stage1/stage1.c b/app/vc4-stage1/stage1.c index 26e1abf786..e18f882f81 100644 --- a/app/vc4-stage1/stage1.c +++ b/app/vc4-stage1/stage1.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -175,16 +176,19 @@ static void xmodem_receive(void) { free(buffer); } -static void stage2_core_entry(void *_unused) { - spin_lock_saved_state_t state1; - arch_interrupt_save(&state1, 0); - printf("stage2 init\n"); + +static void stage2_init(const struct app_descriptor *app) { + puts("stage2_init"); +} + +static void stage2_entry(const struct app_descriptor *app, void *args) { + puts("stage2 entry\n"); + puts("press X to stop autoboot and go into xmodem mode..."); wait_queue_init(&waiter); thread_t *waker = thread_create("waker", waker_entry, &waiter, DEFAULT_PRIORITY, ARCH_DEFAULT_STACK_SIZE); thread_resume(waker); - arch_interrupt_restore(state1, 0); THREAD_LOCK(state); int ret = wait_queue_block(&waiter, 100000); @@ -202,17 +206,6 @@ static void stage2_core_entry(void *_unused) { } } -static thread_t *stage2_core; - -static void stage2_init(const struct app_descriptor *app) { - stage2_core = thread_create("stage2", stage2_core_entry, 0, DEFAULT_PRIORITY, ARCH_DEFAULT_STACK_SIZE); - thread_resume(stage2_core); -} - -static void stage2_entry(const struct app_descriptor *app, void *args) { - printf("stage2 entry\n"); -} - APP_START(stage2) .init = stage2_init, .entry = stage2_entry, diff --git a/app/vc4-stage2/rules.mk b/app/vc4-stage2/rules.mk index 08768925d3..b0904c2858 100644 --- a/app/vc4-stage2/rules.mk +++ b/app/vc4-stage2/rules.mk @@ -9,6 +9,7 @@ MODULE_DEPS += \ lib/fs/ext2 \ lib/debugcommands \ app/stringtests \ + platform/bcm28xx/dpi \ app/tests \ MODULE_SRCS += \ diff --git a/platform/bcm28xx/dpi/dpi.c b/platform/bcm28xx/dpi/dpi.c new file mode 100644 index 0000000000..3e57fb7f33 --- /dev/null +++ b/platform/bcm28xx/dpi/dpi.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int cmd_dpi_start(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dpi_start", "start DPI interface", &cmd_dpi_start) +STATIC_COMMAND_END(dpi); + +uint32_t *framebuffer; + +static int cmd_dpi_start(int argc, const cmd_args *argv) { + *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE; + *REG32(SCALER_DISPCTRL0) = SCALER_DISPCTRLX_RESET; + if (!framebuffer) { + framebuffer = malloc(4*10*10); + } + for (int i=0; i< (10*10); i++) { + framebuffer[i] = (i<<24) | (i << 16) | (i << 8) | i; + } + int list_start = display_slot; + hvs_add_plane(framebuffer); + hvs_terminate_list(); + + *REG32(SCALER_DISPLIST0) = list_start; + *REG32(SCALER_DISPLIST1) = list_start; + *REG32(SCALER_DISPLIST2) = list_start; + *REG32(SCALER_DISPCTRL0) = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(10) | SCALER_DISPCTRL_H(10); + *REG32(SCALER_DISPBKGND0) = SCALER_DISPBKGND_AUTOHS; + + // 0x200 means clock/2 + *REG32(CM_DPIDIV) = CM_PASSWORD | (0xf00 << 4); + *REG32(CM_DPICTL) = CM_PASSWORD | CM_DPICTL_KILL_SET | CM_SRC_OSC; + while (*REG32(CM_DPICTL) & CM_DPICTL_BUSY_SET) {}; + *REG32(CM_DPICTL) = CM_PASSWORD | CM_DPICTL_ENAB_SET | CM_SRC_OSC; + while (*REG32(CM_DPICTL) & CM_DPICTL_BUSY_SET) {}; + printf("DPI clock set\n"); + int rate = measure_clock(17); + printf("DPI clock measured at %d\n", rate); + struct pv_timings t; + t.vfp = 0; + t.vsync = 1; + t.vbp = 0; + t.vactive = 10; + + t.hfp = 0; + t.hsync = 1; + t.hbp = 0; + t.hactive = 10; + + setup_pixelvalve(&t, 0); + + *REG32(DPI_C) = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE; + //gpio_config(0, kBCM2708Pinmux_ALT2); // pixel-clock + gpio_config(2, kBCM2708Pinmux_ALT2); // vsync + gpio_config(3, kBCM2708Pinmux_ALT2); // hsync + gpio_config(5, kBCM2708Pinmux_ALT2); // D1 + return 0; +} diff --git a/platform/bcm28xx/dpi/rules.mk b/platform/bcm28xx/dpi/rules.mk new file mode 100644 index 0000000000..19f4d36b43 --- /dev/null +++ b/platform/bcm28xx/dpi/rules.mk @@ -0,0 +1,13 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULES += \ + platform/bcm28xx/pixelvalve \ + platform/bcm28xx/hvs \ + + +MODULE_SRCS += \ + $(LOCAL_DIR)/dpi.c \ + +include make/module.mk diff --git a/platform/bcm28xx/hvs/hvs.c b/platform/bcm28xx/hvs/hvs.c new file mode 100644 index 0000000000..ad54602db1 --- /dev/null +++ b/platform/bcm28xx/hvs/hvs.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +// note, 4096 slots total +volatile uint32_t* dlist_memory = REG32(SCALER_LIST_MEMORY); +int display_slot = 0; + +static int cmd_hvs_dump(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("hvs_dump", "dump hvs state", &cmd_hvs_dump) +STATIC_COMMAND_END(hvs); + +void hvs_add_plane(void *framebuffer) { + dlist_memory[display_slot++] = CONTROL_VALID + | CONTROL_WORDS(7) + | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ARGB) + | CONTROL_UNITY + | CONTROL_FORMAT(HVS_PIXEL_FORMAT_RGB565); + dlist_memory[display_slot++] = CONTROL0_X(0) | CONTROL0_Y(0); + dlist_memory[display_slot++] = CONTROL2_H(10) | CONTROL2_W(10); + dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state + dlist_memory[display_slot++] = framebuffer; + dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state + dlist_memory[display_slot++] = 4 * 10; // stride +} + +void hvs_terminate_list(void) { + dlist_memory[display_slot++] = CONTROL_END; +} + +static int cmd_hvs_dump(int argc, const cmd_args *argv) { + printf("SCALER_DISPCTRL: 0x%x\n", *REG32(SCALER_DISPCTRL)); + printf("SCALER_DISPLIST0: 0x%x\n", *REG32(SCALER_DISPLIST0)); + printf("SCALER_DISPLIST1: 0x%x\n", *REG32(SCALER_DISPLIST1)); + printf("SCALER_DISPLIST2: 0x%x\n", *REG32(SCALER_DISPLIST2)); + printf("SCALER_DISPCTRL0: 0x%x\n", *REG32(SCALER_DISPCTRL0)); + printf("SCALER_DISPBKGND0: 0x%x\n", *REG32(SCALER_DISPBKGND0)); + printf("SCALER_DISPSTAT0: 0x%x\n", *REG32(SCALER_DISPSTAT0)); + for (int i=0; i<16; i++) { + printf("dlist[%d]: 0x%x\n", i, dlist_memory[i]); + } + return 0; +} diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h new file mode 100644 index 0000000000..3b26146914 --- /dev/null +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +#define SCALER_BASE (BCM_PERIPH_BASE_VIRT + 0x400000) + +#define SCALER_DISPCTRL (SCALER_BASE + 0x00) +#define SCALER_DISPCTRL_ENABLE (1<<31) +#define SCALER_DISPLIST0 (SCALER_BASE + 0x20) +#define SCALER_DISPLIST1 (SCALER_BASE + 0x24) +#define SCALER_DISPLIST2 (SCALER_BASE + 0x28) + +#define SCALER_DISPCTRL0 (SCALER_BASE + 0x40) +#define SCALER_DISPCTRLX_ENABLE (1<<31) +#define SCALER_DISPCTRLX_RESET (1<<30) +#define SCALER_DISPCTRL_W(n) ((n & 0xfff) << 12) +#define SCALER_DISPCTRL_H(n) (n & 0xfff) +#define SCALER_DISPBKGND0 (SCALER_BASE + 0x44) +#define SCALER_DISPBKGND_AUTOHS (1<<31) +#define SCALER_DISPBKGND_GAMMA (1<<29) +#define SCALER_DISPSTAT0 (SCALER_BASE + 0x48) + +#define SCALER_LIST_MEMORY (BCM_PERIPH_BASE_VIRT + 0x402000) + + +#define CONTROL_FORMAT(n) (n & 0xf) +#define CONTROL_END (1<<31) +#define CONTROL_VALID (1<<30) +#define CONTROL_WORDS(n) ((n & 0x3f) << 24) +#define CONTROL_PIXEL_ORDER(n) ((n & 3) << 13) +#define CONTROL_UNITY (1<<4) + +#define HVS_PIXEL_ORDER_ARGB 2 + +enum hvs_pixel_format { + /* 8bpp */ + HVS_PIXEL_FORMAT_RGB332 = 0, + /* 16bpp */ + HVS_PIXEL_FORMAT_RGBA4444 = 1, + HVS_PIXEL_FORMAT_RGB555 = 2, + HVS_PIXEL_FORMAT_RGBA5551 = 3, + HVS_PIXEL_FORMAT_RGB565 = 4, + /* 24bpp */ + HVS_PIXEL_FORMAT_RGB888 = 5, + HVS_PIXEL_FORMAT_RGBA6666 = 6, + /* 32bpp */ + HVS_PIXEL_FORMAT_RGBA8888 = 7, + + HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE = 8, + HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE = 9, + HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE = 10, + HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE = 11, + HVS_PIXEL_FORMAT_H264 = 12, + HVS_PIXEL_FORMAT_PALETTE = 13, + HVS_PIXEL_FORMAT_YUV444_RGB = 14, + HVS_PIXEL_FORMAT_AYUV444_RGB = 15, + HVS_PIXEL_FORMAT_RGBA1010102 = 16, + HVS_PIXEL_FORMAT_YCBCR_10BIT = 17, +}; + +#define CONTROL0_X(n) (n & 0xfff) +#define CONTROL0_Y(n) ((n & 0xfff) << 12) + +#define CONTROL2_W(n) (n & 0xffff) +#define CONTROL2_H(n) ((n & 0xffff) << 16) + +extern int display_slot; +extern volatile uint32_t* dlist_memory; + +void hvs_add_plane(void *framebuffer); +void hvs_terminate_list(void); diff --git a/platform/bcm28xx/hvs/rules.mk b/platform/bcm28xx/hvs/rules.mk new file mode 100644 index 0000000000..0d5c63f751 --- /dev/null +++ b/platform/bcm28xx/hvs/rules.mk @@ -0,0 +1,10 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += \ + +MODULE_SRCS += \ + $(LOCAL_DIR)/hvs.c + +include make/module.mk diff --git a/platform/bcm28xx/include/platform/bcm28xx/dpi.h b/platform/bcm28xx/include/platform/bcm28xx/dpi.h new file mode 100644 index 0000000000..3b0d16bcc9 --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/dpi.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#define DPI_C (BCM_PERIPH_BASE_VIRT + 0x208000) + +#define BIT(b) (1 << b) + +// copied from linux/drivers/gpu/drm/vc4/vc4_dpi.c +# define DPI_OUTPUT_ENABLE_MODE BIT(16) +/* Reverses the polarity of the corresponding signal */ +# define DPI_PIXEL_CLK_INVERT BIT(10) +# define DPI_HSYNC_INVERT BIT(9) +# define DPI_VSYNC_INVERT BIT(8) +# define DPI_OUTPUT_ENABLE_INVERT BIT(7) + +/* Outputs the signal the falling clock edge instead of rising. */ +# define DPI_HSYNC_NEGATE BIT(6) +# define DPI_VSYNC_NEGATE BIT(5) +# define DPI_OUTPUT_ENABLE_NEGATE BIT(4) + +/* Disables the signal */ +# define DPI_HSYNC_DISABLE BIT(3) +# define DPI_VSYNC_DISABLE BIT(2) +# define DPI_OUTPUT_ENABLE_DISABLE BIT(1) + +/* Power gate to the device, full reset at 0 -> 1 transition */ +# define DPI_ENABLE BIT(0) diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 38b843c8b7..7c902275e4 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -68,6 +68,9 @@ struct pll_chan_def { extern uint32_t xtal_freq; extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; +void setup_pllc(uint64_t freq); +void switch_vpu_to_src(int src); + #define CM_SRC_OSC 1 #define CM_SRC_PLLC_CORE0 5 @@ -76,21 +79,33 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_VPUCTL (CM_BASE + 0x008) #define CM_VPUCTL_FRAC_SET 0x00000200 +#define CM_VPUCTL_BUSY_SET 0x00000080 #define CM_VPUCTL_GATE_SET 0x00000040 #define CM_VPUDIV (CM_BASE + 0x00c) + +#define CM_DPICTL (CM_BASE + 0x068) +#define CM_DPICTL_KILL_SET 0x20 +#define CM_DPICTL_BUSY_SET 0x80 +#define CM_DPICTL_ENAB_SET 0x00000010 +#define CM_DPIDIV (CM_BASE + 0x06c) + #define CM_TIMERCTL (CM_BASE + 0x0e8) #define CM_TIMERDIV (CM_BASE + 0x0ec) + #define CM_TCNTCTL (CM_BASE + 0x0c0) #define CM_TCNTCNT (CM_BASE + 0x0c4) + #define CM_UARTCTL (CM_BASE + 0x0f0) #define CM_UARTCTL_FRAC_SET 0x00000200 #define CM_UARTCTL_ENAB_SET 0x00000010 #define CM_UARTDIV (CM_BASE + 0x0f4) + #define CM_OSCCOUNT (CM_BASE + 0x100) #define CM_PLLA (CM_BASE + 0x104) #define CM_PLLC (CM_BASE + 0x108) #define CM_PLLC_DIGRST_SET 0x00000200 +#define CM_PLLC_ANARST_SET 0x00000100 #define CM_PLLC_HOLDPER_SET 0x00000080 #define CM_PLLC_HOLDCORE2_SET 0x00000020 #define CM_PLLC_HOLDCORE1_SET 0x00000008 @@ -98,10 +113,6 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_PLLC_LOADCORE0_SET 0x00000001 #define CM_PLLD (CM_BASE + 0x10C) #define CM_PLLH (CM_BASE + 0x110) -#define CM_PLLB (CM_BASE + 0x170) - - - #define CM_LOCK (CM_BASE + 0x114) #define CM_LOCK_FLOCKA_BIT 8 @@ -110,19 +121,19 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define CM_LOCK_FLOCKD_BIT 11 #define CM_LOCK_FLOCKH_BIT 12 -#define CM_DPICTL_KILL_SET 0x20 -#define CM_DPICTL_BUSY_SET 0x80 +#define CM_PLLB (CM_BASE + 0x170) +#define CM_PLLB_LOADARM_SET 0x00000001 +#define CM_PLLB_HOLDARM_SET 0x00000002 // Common CM_PLL bits #define CM_PLL_ANARST 0x00000100 #define CM_PLL_DIGRST 0x00000200 -#define CM_PLLB_LOADARM_SET 0x00000001 -#define CM_PLLB_HOLDARM_SET 0x00000002 -#define CM_ARMCTL 0x7e1011b0 +#define CM_ARMCTL (CM_BASE + 0x1b0) #define CM_ARMCTL_ENAB_SET 0x00000010 -#define A2W_XOSC_CTRL 0x7e102190 + +#define A2W_XOSC_CTRL (A2W_BASE + 0x190) #define A2W_XOSC_CTRL_DDREN_SET 0x00000010 #define A2W_XOSC_CTRL_PLLAEN_SET 0x00000040 #define A2W_XOSC_CTRL_PLLBEN_SET 0x00000080 @@ -188,6 +199,7 @@ extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; #define A2W_PLLA_CTRL_NDIV_SET 0x000003ff #define A2W_PLLC_CTRL (A2W_BASE + 0x120) #define A2W_PLLC_CTRL_PRSTN_SET 0x00020000 +#define A2W_PLLC_CTRL_PWRDN_SET 0x00010000 #define A2W_PLLC_CTRL_NDIV_SET 0x000003ff #define A2W_PLLD_CTRL (A2W_BASE + 0x140) #define A2W_PLLD_CTRL_NDIV_SET 0x000003ff diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h index 684edff26d..3efb6311f9 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll_read.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll_read.h @@ -1,5 +1,6 @@ #pragma once +#include #include #ifdef __cplusplus @@ -12,6 +13,7 @@ uint32_t get_uart_base_freq(void); uint32_t get_pll_freq(enum pll pll); uint32_t get_pll_chan_freq(enum pll_chan chan); int measure_clock(int mux); +int cmd_measure_clocks(int argc, const cmd_args *argv); #ifdef __cplusplus } #endif diff --git a/platform/bcm28xx/include/platform/bcm28xx/pv.h b/platform/bcm28xx/include/platform/bcm28xx/pv.h new file mode 100644 index 0000000000..775b04dade --- /dev/null +++ b/platform/bcm28xx/include/platform/bcm28xx/pv.h @@ -0,0 +1,8 @@ +#pragma once + +struct pv_timings { + uint16_t vfp, vsync, vbp, vactive; + uint16_t hfp, hsync, hbp, hactive; +}; + +void setup_pixelvalve(struct pv_timings *timings, int pvnr); diff --git a/platform/bcm28xx/pixelvalve/pv.c b/platform/bcm28xx/pixelvalve/pv.c new file mode 100644 index 0000000000..6ffd4f0fdd --- /dev/null +++ b/platform/bcm28xx/pixelvalve/pv.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#define BV(b) (1 << b) + +struct pixel_valve { + volatile uint32_t c; + volatile uint32_t vc; + volatile uint32_t vsyncd_even; + volatile uint32_t horza; + volatile uint32_t horzb; + volatile uint32_t verta; + volatile uint32_t vertb; + volatile uint32_t verta_even; + volatile uint32_t vertb_even; + volatile uint32_t int_enable; + volatile uint32_t int_status; + volatile uint32_t h_active; +}; + +void setup_pixelvalve(struct pv_timings *t, int pvnr) { + uint32_t addr; + switch (pvnr) { + case 0: + addr = BCM_PERIPH_BASE_VIRT + 0x206000; + break; + default: + return; + } + volatile struct pixel_valve *rawpv = addr; + + // reset the PV fifo + rawpv->c = 0; + rawpv->c = BV(0) | BV(1); + rawpv->c = 0; + + rawpv->horza = (t->hbp << 16) | t->hsync; + rawpv->horzb = (t->hfp << 16) | t->hactive; + + rawpv->verta = (t->vbp << 16) | t->vsync; + rawpv->vertb = (t->vfp << 16) | t->vactive; + + rawpv->h_active = t->hactive; + +#define CLK_SELECT(n) ((n & 3) << 2) +# define PV_CONTROL_CLK_SELECT_DSI 0 +# define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 +# define PV_CONTROL_CLK_SELECT_VEC 2 + + rawpv->c = BV(0) | // enable + BV(1) | // fifo clear + CLK_SELECT(PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI) | // set to DPI clock + BV(12) | // wait for h-start + BV(13) | // trigger underflow + BV(14); // clear at start + rawpv->vc = BV(0) | // video enable + BV(1); // continous +} diff --git a/platform/bcm28xx/pixelvalve/rules.mk b/platform/bcm28xx/pixelvalve/rules.mk new file mode 100644 index 0000000000..e2e38965f7 --- /dev/null +++ b/platform/bcm28xx/pixelvalve/rules.mk @@ -0,0 +1,8 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/pv.c \ + +include make/module.mk diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 5493fc66eb..80a9b38b1a 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -104,7 +104,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { extern void intc_init(void); extern void arm_reset(void); - +static void switch_vpu_to_pllc(void); #ifdef WITH_KERNEL_VM static pmm_arena_t arena = { @@ -119,57 +119,28 @@ void platform_init_mmu_mappings(void) { } static void switch_vpu_to_pllc() { - *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLCEN_SET; - - *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | 87380; - *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | 52 | 0x1000; - - *REG32(A2W_PLLC_ANA3) = A2W_PASSWORD | 0x100; - *REG32(A2W_PLLC_ANA2) = A2W_PASSWORD | 0x0; - *REG32(A2W_PLLC_ANA1) = A2W_PASSWORD | 0x144000; - *REG32(A2W_PLLC_ANA0) = A2W_PASSWORD | 0x0; - - *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET; - - /* hold all */ - *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | - CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | - CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET; - - *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x0; - *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x400000; - *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x5; - *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | 52 | 0x555000; + switch_vpu_to_src(CM_SRC_OSC); + *REG32(CM_VPUDIV) = CM_PASSWORD | (1 << 12); - *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | 52 | 0x1000 | A2W_PLLC_CTRL_PRSTN_SET; + setup_pllc( 2000LL * 1000 * 1000); - *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x42; - *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x500401; - *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x4005; - *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | 52 | 0x555000; - - *REG32(A2W_PLLC_CORE0) = A2W_PASSWORD | 2; - - *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | - CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | - CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET | CM_PLLC_LOADCORE0_SET; - - *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | - CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | - CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET; - - *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | - CM_PLLC_HOLDCORE2_SET | - CM_PLLC_HOLDCORE1_SET; + // 1ghz / 4 == 250mhz + int vpu_divisor = 4; *REG32(CM_VPUCTL) = CM_PASSWORD | CM_VPUCTL_FRAC_SET | CM_SRC_OSC | CM_VPUCTL_GATE_SET; - *REG32(CM_VPUDIV) = CM_PASSWORD | (4 << 12); + *REG32(CM_VPUDIV) = CM_PASSWORD | (vpu_divisor << 12); *REG32(CM_VPUCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET; *REG32(CM_VPUCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET | 0x10; /* ENAB */ *REG32(CM_TIMERDIV) = CM_PASSWORD | (19 << 12) | 819; // TODO, look into this timer *REG32(CM_TIMERCTL) = CM_PASSWORD | CM_SRC_OSC | 0x10; - dprintf(INFO, "VPU now at 500mhz\n"); + + int vpu = measure_clock(5); + int pllc_core0 = vpu*vpu_divisor; + uint32_t pllc = pllc_core0 * 2; + dprintf(INFO, "VPU now at %dmhz, ", vpu/1000/1000); + dprintf(INFO, "PLLC_CORE0 at %dmhz, ", pllc_core0/1000/1000); + dprintf(INFO, "PLLC at %dmhz\n", pllc / 1000 / 1000); } void platform_early_init(void) { diff --git a/platform/bcm28xx/pll_control.c b/platform/bcm28xx/pll_control.c index 653d657a5c..85b429637f 100644 --- a/platform/bcm28xx/pll_control.c +++ b/platform/bcm28xx/pll_control.c @@ -467,3 +467,78 @@ static int cmd_set_pll_freq(int argc, const cmd_args *argv) { uint32_t freq = argv[2].u; return set_pll_freq(pll, freq); } + +// in A2W_PLLC_CTRL +#define PDIV(n) ((n & 7) << 12) +// in A2W_PLLC_ANA1 +#define KP(n) ((n & 0xf) << 15) +#define KI(n) ((n & 0x7) << 19) +// in A2W_PLLC_ANA3 +#define KA(n) ((n & 7) << 7) +// for all but PLLH +#define ANA1_DOUBLE (1<<14) +// for PLLH +#define PLLH_ANA1_DOUBLE (1<<11) + +void switch_vpu_to_src(int src) { + *REG32(CM_VPUCTL) = CM_PASSWORD | (*REG32(CM_VPUCTL) & ~0xf) | (src & 0xf); + while (*REG32(CM_VPUCTL) & CM_VPUCTL_BUSY_SET) {}; +} + +void setup_pllc(uint64_t target_freq) { + int pdiv = 1; + uint64_t xtal_in = xtal_freq; + uint64_t goal_freq = target_freq / 2; + uint64_t divisor = (goal_freq<<20) / xtal_in; + int div = divisor >> 20; + int frac = divisor & 0xfffff; + printf("divisor 0x%llx -> %d+(%d/2^20)\n", divisor, div, frac); + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_ANARST_SET; + + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLCEN_SET; + + *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | frac; + *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | div | PDIV(pdiv); + printf("frac set to 0x%x\n", *REG32(A2W_PLLC_FRAC)); + + *REG32(A2W_PLLC_ANA3) = A2W_PASSWORD | KA(2); + *REG32(A2W_PLLC_ANA2) = A2W_PASSWORD | 0x0; + *REG32(A2W_PLLC_ANA1) = A2W_PASSWORD | ANA1_DOUBLE | KI(2) | KP(8); + *REG32(A2W_PLLC_ANA0) = A2W_PASSWORD | 0x0; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET; + + /* hold all */ + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET; + + *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x0; + *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x400000; + *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x5; + *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | div | 0x555000; + + *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | div | PDIV(pdiv) | A2W_PLLC_CTRL_PRSTN_SET; + + *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x42; + *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x500401; + *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x4005; + *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | div | 0x555000; + + *REG32(A2W_PLLC_CORE0) = A2W_PASSWORD | 2; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET | CM_PLLC_LOADCORE0_SET; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET | CM_PLLC_HOLDCORE0_SET; + + *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | + CM_PLLC_HOLDCORE2_SET | + CM_PLLC_HOLDCORE1_SET; + + while (!BIT_SET(*REG32(CM_LOCK), CM_LOCK_FLOCKC_BIT)) {} +} diff --git a/platform/bcm28xx/pll_read.c b/platform/bcm28xx/pll_read.c index 2c6a400828..002f3853dd 100644 --- a/platform/bcm28xx/pll_read.c +++ b/platform/bcm28xx/pll_read.c @@ -12,7 +12,6 @@ uint32_t xtal_freq; static int cmd_pll_dump(int argc, const cmd_args *argv); static int cmd_measure_clock(int argc, const cmd_args *argv); -static int cmd_measure_clocks(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dump_pll_state", "print all pll state", &cmd_pll_dump) @@ -154,6 +153,33 @@ int measure_clock(int mux) { return count * divisor; } +const char *clock_names[] = { + [1] = "H264", + [2] = "ISP", + [3] = "SDRAM", + [5] = "VPU", + "OTP", + [12] = "dsi0p", + "dsi1p", + "cam0", + "cam1", + [17] = "dpi", + "dsi0e", + "dsi1e", + "gp0", + "gp1", + "hsm", + "pcm", + "pwm", + "slim", + [27] = "smi", + "uart", + "vec", + [38] = "aveo", + "emmc", + [42] = "emmc2" +}; + static int cmd_measure_clock(int argc, const cmd_args *argv) { if (argc != 2) { puts("error, missing argument"); @@ -192,10 +218,10 @@ static int cmd_measure_clock(int argc, const cmd_args *argv) { return 0; } -static int cmd_measure_clocks(int argc, const cmd_args *argv) { +int cmd_measure_clocks(int argc, const cmd_args *argv) { for (int i=0; i<43; i++) { int count = measure_clock(i); - printf("clock #%d is %d\n", i, count); + printf("clock #%d(%s) is %d\n", i, clock_names[i], count); } return 0; } From 1b69585e7e3d2aaad2f5d42cc0f62100d85a64d3 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 15 Sep 2020 01:56:20 -0300 Subject: [PATCH 061/100] it versk!! https://www.youtube.com/watch?v=Yu61pURyucM --- platform/bcm28xx/dpi/dpi.c | 65 ++++++++++++++++--- platform/bcm28xx/hvs/hvs.c | 32 +++++++-- .../hvs/include/platform/bcm28xx/hvs.h | 22 ++++++- .../bcm28xx/include/platform/bcm28xx/pv.h | 3 + platform/bcm28xx/pixelvalve/pv.c | 24 ++++--- 5 files changed, 122 insertions(+), 24 deletions(-) diff --git a/platform/bcm28xx/dpi/dpi.c b/platform/bcm28xx/dpi/dpi.c index 3e57fb7f33..ffed455617 100644 --- a/platform/bcm28xx/dpi/dpi.c +++ b/platform/bcm28xx/dpi/dpi.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -10,21 +11,44 @@ #include static int cmd_dpi_start(int argc, const cmd_args *argv); +static int cmd_dpi_count(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dpi_start", "start DPI interface", &cmd_dpi_start) +STATIC_COMMAND("dpi_count", "begin counting on framebuffer", &cmd_dpi_count) STATIC_COMMAND_END(dpi); uint32_t *framebuffer; +int width; +int height; +int stride; +timer_t updater; static int cmd_dpi_start(int argc, const cmd_args *argv) { - *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE; - *REG32(SCALER_DISPCTRL0) = SCALER_DISPCTRLX_RESET; + *REG32(SCALER_DISPCTRL) &= ~SCALER_DISPCTRL_ENABLE; // disable HVS + *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE | 0x9a0dddff; // re-enable HVS + for (int i=0; i<3; i++) { + hvs_channels[i].dispctrl = SCALER_DISPCTRLX_RESET; + hvs_channels[i].dispctrl = 0; + hvs_channels[i].dispbkgnd = 0x1020202; // bit 24 + } + + hvs_channels[2].dispbase = BASE_BASE(0) | BASE_TOP(0xf00); + hvs_channels[1].dispbase = BASE_BASE(0xf10) | BASE_TOP(0x4b00); + hvs_channels[0].dispbase = BASE_BASE(0x4b10) | BASE_TOP(0x7700); + + hvs_wipe_displaylist(); + if (!framebuffer) { - framebuffer = malloc(4*10*10); + framebuffer = malloc(4*12*10); + width = 10; + height = 10; + stride = 12; } - for (int i=0; i< (10*10); i++) { - framebuffer[i] = (i<<24) | (i << 16) | (i << 8) | i; + for (int x=0; x< 10; x++) { + for (int y=0; y<10; y++) { + framebuffer[(x*stride) + y] = (y<<24) | (y << 16) | (y << 8) | y; + } } int list_start = display_slot; hvs_add_plane(framebuffer); @@ -33,8 +57,12 @@ static int cmd_dpi_start(int argc, const cmd_args *argv) { *REG32(SCALER_DISPLIST0) = list_start; *REG32(SCALER_DISPLIST1) = list_start; *REG32(SCALER_DISPLIST2) = list_start; - *REG32(SCALER_DISPCTRL0) = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(10) | SCALER_DISPCTRL_H(10); - *REG32(SCALER_DISPBKGND0) = SCALER_DISPBKGND_AUTOHS; + + hvs_channels[0].dispctrl = SCALER_DISPCTRLX_RESET; + hvs_channels[0].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(10) | SCALER_DISPCTRL_H(10); + + hvs_channels[0].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202; + *REG32(SCALER_DISPEOLN) = 0x40000000; // 0x200 means clock/2 *REG32(CM_DPIDIV) = CM_PASSWORD | (0xf00 << 4); @@ -58,10 +86,31 @@ static int cmd_dpi_start(int argc, const cmd_args *argv) { setup_pixelvalve(&t, 0); - *REG32(DPI_C) = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE; +#define FORMAT(n) ((n & 0x7) << 11) + + *REG32(DPI_C) = DPI_ENABLE | FORMAT(6) | DPI_OUTPUT_ENABLE_MODE; //gpio_config(0, kBCM2708Pinmux_ALT2); // pixel-clock gpio_config(2, kBCM2708Pinmux_ALT2); // vsync gpio_config(3, kBCM2708Pinmux_ALT2); // hsync + gpio_config(4, kBCM2708Pinmux_ALT2); // D0 gpio_config(5, kBCM2708Pinmux_ALT2); // D1 return 0; } + +uint8_t count; + +static enum handler_return updater_entry(struct timer *t, lk_time_t now, void *arg) { + for (int y=0; y> 30) & 0x3); + if (stat & (1<<29)) puts("full"); + if (stat & (1<<28)) puts("empty"); + printf("unknown: 0x%x\n", (stat >> 18) & 0x3ff); + printf("frame count: %d\n", (stat >> 12) & 0x3f); + printf("line: %d\n", stat & 0xfff); + uint32_t base = hvs_channels[i].dispbase; + printf("SCALER_DISPBASE%d: base 0x%x top 0x%x\n\n", i, base & 0xffff, base >> 16); + } for (int i=0; i<16; i++) { printf("dlist[%d]: 0x%x\n", i, dlist_memory[i]); } diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index 3b26146914..f7ef3ca41d 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -6,19 +6,36 @@ #define SCALER_DISPCTRL (SCALER_BASE + 0x00) #define SCALER_DISPCTRL_ENABLE (1<<31) +#define SCALER_DISPEOLN (SCALER_BASE + 0x18) #define SCALER_DISPLIST0 (SCALER_BASE + 0x20) #define SCALER_DISPLIST1 (SCALER_BASE + 0x24) #define SCALER_DISPLIST2 (SCALER_BASE + 0x28) +struct hvs_channel { + volatile uint32_t dispctrl; + volatile uint32_t dispbkgnd; + volatile uint32_t dispstat; + // 31:30 mode + // 29 full + // 28 empty + // 17:12 frame count + // 11:0 line + volatile uint32_t dispbase; +}; + +extern volatile struct hvs_channel *hvs_channels; + #define SCALER_DISPCTRL0 (SCALER_BASE + 0x40) #define SCALER_DISPCTRLX_ENABLE (1<<31) #define SCALER_DISPCTRLX_RESET (1<<30) #define SCALER_DISPCTRL_W(n) ((n & 0xfff) << 12) #define SCALER_DISPCTRL_H(n) (n & 0xfff) -#define SCALER_DISPBKGND0 (SCALER_BASE + 0x44) #define SCALER_DISPBKGND_AUTOHS (1<<31) #define SCALER_DISPBKGND_GAMMA (1<<29) -#define SCALER_DISPSTAT0 (SCALER_BASE + 0x48) + +#define BASE_BASE(n) (n & 0xffff) +#define BASE_TOP(n) ((n & 0xffff) << 16) + #define SCALER_LIST_MEMORY (BCM_PERIPH_BASE_VIRT + 0x402000) @@ -69,3 +86,4 @@ extern volatile uint32_t* dlist_memory; void hvs_add_plane(void *framebuffer); void hvs_terminate_list(void); +void hvs_wipe_displaylist(void); diff --git a/platform/bcm28xx/include/platform/bcm28xx/pv.h b/platform/bcm28xx/include/platform/bcm28xx/pv.h index 775b04dade..4acd4b899f 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pv.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pv.h @@ -6,3 +6,6 @@ struct pv_timings { }; void setup_pixelvalve(struct pv_timings *timings, int pvnr); + +#define PV_CONTROL_FIFO_CLR (1<<1) +#define PV_CONTROL_EN (1<<0) diff --git a/platform/bcm28xx/pixelvalve/pv.c b/platform/bcm28xx/pixelvalve/pv.c index 6ffd4f0fdd..c5f6993e40 100644 --- a/platform/bcm28xx/pixelvalve/pv.c +++ b/platform/bcm28xx/pixelvalve/pv.c @@ -33,7 +33,7 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { // reset the PV fifo rawpv->c = 0; - rawpv->c = BV(0) | BV(1); + rawpv->c = PV_CONTROL_FIFO_CLR | PV_CONTROL_EN; rawpv->c = 0; rawpv->horza = (t->hbp << 16) | t->hsync; @@ -42,19 +42,27 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { rawpv->verta = (t->vbp << 16) | t->vsync; rawpv->vertb = (t->vfp << 16) | t->vactive; - rawpv->h_active = t->hactive; - #define CLK_SELECT(n) ((n & 3) << 2) # define PV_CONTROL_CLK_SELECT_DSI 0 # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 # define PV_CONTROL_CLK_SELECT_VEC 2 +#define PIXEL_REP(n) ((n & 0x3) << 4) +#define FIFO_LEVEL(n) ((n & 0x3f) << 15) + + rawpv->vc = BV(0) | // video enable + BV(1); // continous - rawpv->c = BV(0) | // enable - BV(1) | // fifo clear + rawpv->h_active = t->hactive; + + uint32_t fifo_len_bytes = 64; + fifo_len_bytes = fifo_len_bytes - 3 * 6; + + rawpv->c = PV_CONTROL_EN | + PV_CONTROL_FIFO_CLR | CLK_SELECT(PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI) | // set to DPI clock + PIXEL_REP(1 - 1) | BV(12) | // wait for h-start BV(13) | // trigger underflow - BV(14); // clear at start - rawpv->vc = BV(0) | // video enable - BV(1); // continous + BV(14) | // clear at start + FIFO_LEVEL(fifo_len_bytes); } From 6c501e249e6ca8cddba35356b1adbe3cf1fb81d7 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 15 Sep 2020 22:37:39 -0300 Subject: [PATCH 062/100] add another graphics example --- platform/bcm28xx/dpi/dpi.c | 41 ++++++++++--------- platform/bcm28xx/hvs/hvs.c | 22 ++++++++++ .../hvs/include/platform/bcm28xx/hvs.h | 1 + 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/platform/bcm28xx/dpi/dpi.c b/platform/bcm28xx/dpi/dpi.c index ffed455617..72c474f063 100644 --- a/platform/bcm28xx/dpi/dpi.c +++ b/platform/bcm28xx/dpi/dpi.c @@ -12,10 +12,12 @@ static int cmd_dpi_start(int argc, const cmd_args *argv); static int cmd_dpi_count(int argc, const cmd_args *argv); +static int cmd_dpi_move(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dpi_start", "start DPI interface", &cmd_dpi_start) STATIC_COMMAND("dpi_count", "begin counting on framebuffer", &cmd_dpi_count) +STATIC_COMMAND("dpi_move", "move a pixel on the frame", &cmd_dpi_move) STATIC_COMMAND_END(dpi); uint32_t *framebuffer; @@ -25,19 +27,7 @@ int stride; timer_t updater; static int cmd_dpi_start(int argc, const cmd_args *argv) { - *REG32(SCALER_DISPCTRL) &= ~SCALER_DISPCTRL_ENABLE; // disable HVS - *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE | 0x9a0dddff; // re-enable HVS - for (int i=0; i<3; i++) { - hvs_channels[i].dispctrl = SCALER_DISPCTRLX_RESET; - hvs_channels[i].dispctrl = 0; - hvs_channels[i].dispbkgnd = 0x1020202; // bit 24 - } - - hvs_channels[2].dispbase = BASE_BASE(0) | BASE_TOP(0xf00); - hvs_channels[1].dispbase = BASE_BASE(0xf10) | BASE_TOP(0x4b00); - hvs_channels[0].dispbase = BASE_BASE(0x4b10) | BASE_TOP(0x7700); - - hvs_wipe_displaylist(); + hvs_initialize(); if (!framebuffer) { framebuffer = malloc(4*12*10); @@ -47,9 +37,10 @@ static int cmd_dpi_start(int argc, const cmd_args *argv) { } for (int x=0; x< 10; x++) { for (int y=0; y<10; y++) { - framebuffer[(x*stride) + y] = (y<<24) | (y << 16) | (y << 8) | y; + framebuffer[(x*stride) + y] = (0xff<<24) | (y << 16) | (y << 8) | y; } } + int list_start = display_slot; hvs_add_plane(framebuffer); hvs_terminate_list(); @@ -58,11 +49,6 @@ static int cmd_dpi_start(int argc, const cmd_args *argv) { *REG32(SCALER_DISPLIST1) = list_start; *REG32(SCALER_DISPLIST2) = list_start; - hvs_channels[0].dispctrl = SCALER_DISPCTRLX_RESET; - hvs_channels[0].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(10) | SCALER_DISPCTRL_H(10); - - hvs_channels[0].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202; - *REG32(SCALER_DISPEOLN) = 0x40000000; // 0x200 means clock/2 *REG32(CM_DPIDIV) = CM_PASSWORD | (0xf00 << 4); @@ -114,3 +100,20 @@ static int cmd_dpi_count(int argc, const cmd_args *argv) { timer_set_periodic(&updater, 1000, updater_entry, NULL); return 0; } + +static enum handler_return mover_entry(struct timer *t, lk_time_t now, void *arg) { + int y = count / width; + int x = count % width; + framebuffer[(y * stride) + x] = 0xff000000; + count = (count+1) % (width*height); + y = count / width; + x = count % width; + framebuffer[(y * stride) + x] = 0xffffffff; + return INT_NO_RESCHEDULE; +} + +static int cmd_dpi_move(int argc, const cmd_args *argv) { + timer_initialize(&updater); + timer_set_periodic(&updater, 100, mover_entry, NULL); + return 0; +} diff --git a/platform/bcm28xx/hvs/hvs.c b/platform/bcm28xx/hvs/hvs.c index 3918138d1e..3b306133af 100644 --- a/platform/bcm28xx/hvs/hvs.c +++ b/platform/bcm28xx/hvs/hvs.c @@ -32,6 +32,28 @@ void hvs_terminate_list(void) { dlist_memory[display_slot++] = CONTROL_END; } +void hvs_initialize() { + *REG32(SCALER_DISPCTRL) &= ~SCALER_DISPCTRL_ENABLE; // disable HVS + *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE | 0x9a0dddff; // re-enable HVS + for (int i=0; i<3; i++) { + hvs_channels[i].dispctrl = SCALER_DISPCTRLX_RESET; + hvs_channels[i].dispctrl = 0; + hvs_channels[i].dispbkgnd = 0x1020202; // bit 24 + } + + hvs_channels[2].dispbase = BASE_BASE(0) | BASE_TOP(0xf00); + hvs_channels[1].dispbase = BASE_BASE(0xf10) | BASE_TOP(0x4b00); + hvs_channels[0].dispbase = BASE_BASE(0x4b10) | BASE_TOP(0x7700); + + hvs_wipe_displaylist(); + + hvs_channels[0].dispctrl = SCALER_DISPCTRLX_RESET; + hvs_channels[0].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(10) | SCALER_DISPCTRL_H(10); + + hvs_channels[0].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202; + *REG32(SCALER_DISPEOLN) = 0x40000000; +} + void hvs_wipe_displaylist(void) { for (int i=0; i<1024; i++) { dlist_memory[i] = CONTROL_END; diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index f7ef3ca41d..6b6d1f52a6 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -87,3 +87,4 @@ extern volatile uint32_t* dlist_memory; void hvs_add_plane(void *framebuffer); void hvs_terminate_list(void); void hvs_wipe_displaylist(void); +void hvs_initialize(void); From 34483f7fb236177945feae5d71b9cee01c219e22 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sat, 3 Oct 2020 00:27:24 -0300 Subject: [PATCH 063/100] fix the rpi3-bootcode project --- default.nix | 36 +++++++++++++++++++-- platform/bcm28xx/platform.c | 11 +++++-- platform/bcm28xx/{ => pll}/pll_control.c | 4 ++- platform/bcm28xx/{ => pll}/pll_read.c | 20 ++++++------ platform/bcm28xx/pll/rules.mk | 9 ++++++ platform/bcm28xx/rpi-ddr2/autoram/autoram.c | 14 ++++++++ platform/bcm28xx/rpi-ddr2/autoram/rules.mk | 11 +++++++ platform/bcm28xx/rules.mk | 5 ++- platform/bcm28xx/uart.c | 1 + project/rpi3-bootcode.mk | 3 +- 10 files changed, 95 insertions(+), 19 deletions(-) rename platform/bcm28xx/{ => pll}/pll_control.c (99%) rename platform/bcm28xx/{ => pll}/pll_read.c (95%) create mode 100644 platform/bcm28xx/pll/rules.mk create mode 100644 platform/bcm28xx/rpi-ddr2/autoram/autoram.c create mode 100644 platform/bcm28xx/rpi-ddr2/autoram/rules.mk diff --git a/default.nix b/default.nix index b1a4c5e4f7..c8c399b767 100644 --- a/default.nix +++ b/default.nix @@ -6,7 +6,9 @@ let littlekernel = self.stdenv.mkDerivation { name = "littlekernel"; src = lib.cleanSource ./.; - nativeBuildInputs = [ x86_64.uart-manager ]; + #nativeBuildInputs = [ x86_64.uart-manager ]; + nativeBuildInputs = [ x86_64.python ]; + hardeningDisable = [ "format" ]; }; uart-manager = self.stdenv.mkDerivation { name = "uart-manager"; @@ -15,7 +17,7 @@ let }; vc4 = pkgs.pkgsCross.vc4.extend overlay; x86_64 = pkgs.extend overlay; - arm7 = pkgs.pkgsCross.armv7l-hf-multiplatform.extend overlay; + arm7 = pkgs.pkgsCross.arm-embedded.extend overlay; in lib.fix (self: { arm7 = { inherit (arm7) littlekernel; @@ -36,4 +38,34 @@ in lib.fix (self: { scp ${self.vc4.rpi3.bootcode}/lk.bin root@router.localnet:/tftproot/open-firmware/bootcode.bin exec ${x86_64.uart-manager}/bin/uart-manager ''; + disk_image = pkgs.vmTools.runInLinuxVM (pkgs.runCommand "disk-image" { + buildInputs = with pkgs; [ utillinux dosfstools e2fsprogs mtools libfaketime ]; + preVM = '' + mkdir -p $out + diskImage=$out/disk-image.img + truncate $diskImage -s 64m + ''; + postVM = '' + ''; + } '' + sfdisk /dev/vda < #include -uint32_t xtal_freq; - static int cmd_pll_dump(int argc, const cmd_args *argv); static int cmd_measure_clock(int argc, const cmd_args *argv); @@ -157,13 +155,17 @@ const char *clock_names[] = { [1] = "H264", [2] = "ISP", [3] = "SDRAM", + [4] = "V3D", // guess, from start.elf [5] = "VPU", - "OTP", - [12] = "dsi0p", + [6] = "OTP", + [7] = "ARM", // guess, from start.elf + [9] = "TIMER", // guess, from start.elf + [0xa] = "PVTMON", // VC6 only, from a start.elf + [0xc] = "dsi0p", "dsi1p", "cam0", "cam1", - [17] = "dpi", + [0x11] = "dpi", "dsi0e", "dsi1e", "gp0", @@ -172,12 +174,12 @@ const char *clock_names[] = { "pcm", "pwm", "slim", - [27] = "smi", + [0x1b] = "smi", "uart", "vec", - [38] = "aveo", - "emmc", - [42] = "emmc2" + [0x26] = "aveo", + [0x26] = "emmc", + [0x2a] = "emmc2" }; static int cmd_measure_clock(int argc, const cmd_args *argv) { diff --git a/platform/bcm28xx/pll/rules.mk b/platform/bcm28xx/pll/rules.mk new file mode 100644 index 0000000000..7018cb8bc1 --- /dev/null +++ b/platform/bcm28xx/pll/rules.mk @@ -0,0 +1,9 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/pll_read.c \ + $(LOCAL_DIR)/pll_control.c \ + +include make/module.mk diff --git a/platform/bcm28xx/rpi-ddr2/autoram/autoram.c b/platform/bcm28xx/rpi-ddr2/autoram/autoram.c new file mode 100644 index 0000000000..0cb8e948af --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/autoram/autoram.c @@ -0,0 +1,14 @@ +#include +#include +#include + +#define UNCACHED_RAM 0xc0000000 +#define MB (1024*1024) + +static void stage2_dram_init(uint level) { + sdram_init(); + uint32_t start = UNCACHED_RAM | (1 * MB); + uint32_t length = 10 * MB; + novm_add_arena("dram", start, length); +} +LK_INIT_HOOK(stage1, &stage2_dram_init, LK_INIT_LEVEL_PLATFORM_EARLY + 1); diff --git a/platform/bcm28xx/rpi-ddr2/autoram/rules.mk b/platform/bcm28xx/rpi-ddr2/autoram/rules.mk new file mode 100644 index 0000000000..9bf99ac42a --- /dev/null +++ b/platform/bcm28xx/rpi-ddr2/autoram/rules.mk @@ -0,0 +1,11 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_DEPS += platform/bcm28xx/rpi-ddr2 + +MODULE_SRCS += $(LOCAL_DIR)/autoram.c + +GLOBAL_DEFINES += NOVM_MAX_ARENAS=2 NOVM_DEFAULT_ARENA=0 + +include make/module.mk diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 814da4dc7d..74e6d46146 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -34,6 +34,7 @@ MODULE_SRCS += \ LINKER_SCRIPT += \ $(BUILDDIR)/system-onesegment.ld else # VPU + MODULE_DEPS += platform/bcm28xx/pll ifeq ($(BOOTCODE),1) MEMBASE := 0x80000000 # in the 8 alias MEMSIZE := 0x20000 # 128kb @@ -55,8 +56,7 @@ endif MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/platform.c \ - $(LOCAL_DIR)/pll_read.c \ - $(LOCAL_DIR)/pll_control.c + $(LOCAL_DIR)/udelay.c \ #$(LOCAL_DIR)/i2c.c \ @@ -104,7 +104,6 @@ else ifeq ($(TARGET),rpi3-vpu) MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ - $(LOCAL_DIR)/udelay.c \ $(LOCAL_DIR)/sdhost_impl.cpp \ $(LOCAL_DIR)/print_timestamp.c \ diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index 3cb455cd9c..a027c9fb00 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -61,6 +61,7 @@ static inline uintptr_t uart_to_ptr(unsigned int n) { static uint32_t calculate_baud_divisor(uint32_t baud) { uint32_t uart_freq = get_uart_base_freq(); + if (uart_freq == 0) return 0; uint32_t divisor = (uart_freq << 6) / baud / 16; return divisor; } diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk index bfb98916ea..5ddfcc3b04 100644 --- a/project/rpi3-bootcode.mk +++ b/project/rpi3-bootcode.mk @@ -5,7 +5,8 @@ ARCH := vc4 MODULES += \ app/shell \ - platform/bcm28xx/rpi-ddr2 \ + platform/bcm28xx/rpi-ddr2/autoram \ + #platform/bcm28xx/dpi \ #platform/bcm28xx/otp \ #lib/debugcommands \ #app/shell \ From fa37f8b8097a6e09655bf54c240c3b7a6ff6dee0 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 9 Oct 2020 04:56:30 -0300 Subject: [PATCH 064/100] [arch][arm] fix booting when in HYP mode --- arch/arm/arm/start.S | 34 ++++++++++++++++++++++++++-------- arch/arm/rules.mk | 3 ++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/arch/arm/arm/start.S b/arch/arm/arm/start.S index b78fcc2b94..1a088a915e 100644 --- a/arch/arm/arm/start.S +++ b/arch/arm/arm/start.S @@ -31,6 +31,14 @@ platform_reset: .globl arm_reset arm_reset: +#if ARM_WITH_HYP + /* if in HYP mode, move to SVC */ + mrs r12, cpsr + and r12, r12, #0x1f + cmp r12, #0x1a + bleq arm32_hyp_to_svc +#endif // ARM_WITH_HYP + /* do some early cpu setup */ mrc p15, 0, r12, c1, c0, 0 /* i/d cache disable, mmu disabled */ @@ -204,7 +212,7 @@ arm_reset: /* set up the mmu */ bl .Lmmu_setup -#endif // WITH_KERNEL_VM +#endif // ARM_WITH_MMU /* at this point we're running at our final location in virtual memory (if enabled) */ .Lstack_setup: @@ -281,7 +289,7 @@ arm_reset: orr r12, r4, #MMU_TTBRx_FLAGS /* Write ttbr with phys addr of the translation table */ - mcr p15, 0, r12, c2, c0, 0 + mcr p15, 0, r12, c2, c0, 0 // TTBR0 isb /* Write DACR */ @@ -310,7 +318,7 @@ arm_reset: /* Switch to main page table */ mcr p15, 0, r8, c2, c0, 0 isb -#endif +#endif // MMU_WITH_TRAMPOLINE /* Invalidate TLB. The value in r0 is ignored */ mcr p15, 0, r0, c8, c7, 0 @@ -320,7 +328,7 @@ arm_reset: /* assume lr was in physical memory, adjust it before returning */ sub lr, r11 bx lr -#endif +#endif // WITH_KERNEL_VM #if WITH_SMP /* secondary cpu entry point */ @@ -387,11 +395,11 @@ FUNCTION(arm_secondary_setup) /* Calculate pagetable physical addresses */ ldr r4, =tt_trampoline /* r4 = tt_trampoline vaddr */ add r4, r4, r11 /* r4 = tt_trampoline paddr */ -#endif +#endif // MMU_WITH_TRAMPOLINE /* set up the mmu on this cpu and switch to virtual memory */ bl .Lmmu_setup -#endif +#endif // WITH_KERNEL_VM /* stay in supervisor and call into arm arch code to continue setup */ mov r0, r5 @@ -401,7 +409,17 @@ FUNCTION(arm_secondary_setup) unsupported_cpu_trap: wfe b unsupported_cpu_trap -#endif +#endif // WITH_SMP + +#if ARM_WITH_HYP +arm32_hyp_to_svc: + mrs r12, cpsr + bic r12, #0x1f // clear mode bits + orr r12, r12, #0x13 // set mode bits to SVC + msr SPSR_hyp, r12 + msr ELR_hyp, lr + eret // "restore" the mode, and return +#endif // ARM_WITH_HYP .ltorg @@ -410,7 +428,7 @@ unsupported_cpu_trap: .align 14 DATA(tt_trampoline) .skip 16384 -#endif +#endif // WITH_KERNEL_VM && MMU_WITH_TRAMPOLINE .data .align 2 diff --git a/arch/arm/rules.mk b/arch/arm/rules.mk index ba8993fb28..b866351231 100644 --- a/arch/arm/rules.mk +++ b/arch/arm/rules.mk @@ -103,7 +103,8 @@ GLOBAL_DEFINES += \ ARM_WITH_NEON=1 \ ARM_WITH_THUMB=1 \ ARM_WITH_THUMB2=1 \ - ARM_WITH_CACHE=1 + ARM_WITH_CACHE=1 \ + ARM_WITH_HYP=1 HANDLED_CORE := true endif ifeq ($(ARM_CPU),cortex-a15) From e2367de177d5d25ab24c5d66d04b16ca743c084c Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 9 Oct 2020 07:46:54 -0300 Subject: [PATCH 065/100] overhaul the HVS code, and test it under arm --- app/vc4-stage2/stage2.c | 8 +- arch/vc4/arch.c | 4 + lib/gfx/gfx.c | 1 + lib/tga/rules.mk | 3 + platform/bcm28xx/dpi/dpi.c | 189 ++++++++++++++---- platform/bcm28xx/hvs-dance/dance.c | 73 +++++++ platform/bcm28xx/hvs-dance/rules.mk | 11 + platform/bcm28xx/hvs/hvs.c | 50 +++-- .../hvs/include/platform/bcm28xx/hvs.h | 4 +- platform/bcm28xx/hvs/rules.mk | 1 + platform/bcm28xx/include/platform/bcm28xx.h | 2 +- .../bcm28xx/include/platform/bcm28xx/dpi.h | 8 + platform/bcm28xx/platform.c | 2 +- platform/bcm28xx/pll/pll_control.c | 3 +- platform/bcm28xx/pll/pll_read.c | 26 ++- platform/bcm28xx/rpi-ddr2/autoram/autoram.c | 4 +- platform/bcm28xx/rpi-ddr2/sdram.c | 12 -- platform/bcm28xx/rules.mk | 26 ++- platform/bcm28xx/uart.c | 1 + project/rpi2-test.mk | 4 +- 20 files changed, 340 insertions(+), 92 deletions(-) create mode 100644 platform/bcm28xx/hvs-dance/dance.c create mode 100644 platform/bcm28xx/hvs-dance/rules.mk diff --git a/app/vc4-stage2/stage2.c b/app/vc4-stage2/stage2.c index 3e5a19cba3..0b3631915f 100644 --- a/app/vc4-stage2/stage2.c +++ b/app/vc4-stage2/stage2.c @@ -1,8 +1,9 @@ #include +#include +#include #include +#include #include -#include -#include static void stage2_init(const struct app_descriptor *app) { printf("stage2 init\n"); @@ -14,6 +15,9 @@ static void stage2_init(const struct app_descriptor *app) { static void stage2_entry(const struct app_descriptor *app, void *args) { printf("stage2 entry\n"); + cmd_dpi_start(0, NULL); + cmd_dpi_move(0, NULL); + //cmd_dpi_count(0, NULL); } APP_START(stage2) diff --git a/arch/vc4/arch.c b/arch/vc4/arch.c index c6e6b73540..04854ce611 100644 --- a/arch/vc4/arch.c +++ b/arch/vc4/arch.c @@ -124,3 +124,7 @@ int vc4_atomic_add(volatile int *ptr, int val) { THREAD_UNLOCK(state); return old; } + +void arch_clean_cache_range(addr_t start, size_t len) { + // TODO +} diff --git a/lib/gfx/gfx.c b/lib/gfx/gfx.c index 9b1e31d8f9..91a22a69ac 100644 --- a/lib/gfx/gfx.c +++ b/lib/gfx/gfx.c @@ -556,6 +556,7 @@ gfx_surface *gfx_create_surface(void *ptr, uint width, uint height, uint stride, surface->height = height; surface->stride = stride; surface->alpha = MAX_ALPHA; + surface->flush = NULL; // set up some function pointers switch (format) { diff --git a/lib/tga/rules.mk b/lib/tga/rules.mk index 3c63f5fd3f..27a4f6f9ca 100644 --- a/lib/tga/rules.mk +++ b/lib/tga/rules.mk @@ -5,4 +5,7 @@ MODULE := $(LOCAL_DIR) MODULE_SRCS += \ $(LOCAL_DIR)/tga.c +MODULES += \ + lib/gfx \ + include make/module.mk diff --git a/platform/bcm28xx/dpi/dpi.c b/platform/bcm28xx/dpi/dpi.c index 72c474f063..2206255e1d 100644 --- a/platform/bcm28xx/dpi/dpi.c +++ b/platform/bcm28xx/dpi/dpi.c @@ -10,9 +10,9 @@ #include #include -static int cmd_dpi_start(int argc, const cmd_args *argv); -static int cmd_dpi_count(int argc, const cmd_args *argv); -static int cmd_dpi_move(int argc, const cmd_args *argv); +int cmd_dpi_start(int argc, const cmd_args *argv); +int cmd_dpi_count(int argc, const cmd_args *argv); +int cmd_dpi_move(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dpi_start", "start DPI interface", &cmd_dpi_start) @@ -20,29 +20,57 @@ STATIC_COMMAND("dpi_count", "begin counting on framebuffer", &cmd_dpi_count) STATIC_COMMAND("dpi_move", "move a pixel on the frame", &cmd_dpi_move) STATIC_COMMAND_END(dpi); -uint32_t *framebuffer; +gfx_surface *framebuffer; int width; int height; int stride; timer_t updater; +uint8_t count; +uint32_t count2; + +#define HYPERPIXEL -static int cmd_dpi_start(int argc, const cmd_args *argv) { +int cmd_dpi_start(int argc, const cmd_args *argv) { hvs_initialize(); + struct pv_timings t; +#ifdef HYPERPIXEL + t.vfp = 15; + t.vsync = 113; + t.vbp = 15; + t.vactive = 800; + + t.hfp = 10; + t.hsync = 16; + t.hbp = 59; + t.hactive = 480; +#else + t.vfp = 0; + t.vsync = 1; + t.vbp = 0; + t.vactive = 10; + + t.hfp = 0; + t.hsync = 1; + t.hbp = 0; + t.hactive = 10; +#endif + if (!framebuffer) { - framebuffer = malloc(4*12*10); - width = 10; - height = 10; - stride = 12; - } - for (int x=0; x< 10; x++) { - for (int y=0; y<10; y++) { - framebuffer[(x*stride) + y] = (0xff<<24) | (y << 16) | (y << 8) | y; + width = t.hactive; + height = t.vactive; + stride = t.hactive; + framebuffer = gfx_create_surface(NULL, width, height, width, GFX_FORMAT_ARGB_8888); + } + for (int x=0; x< height; x++) { + for (int y=0; y < width; y++) { + gfx_putpixel(framebuffer, x, y, (0xff<<24) | (y << 16) | (y << 8) | y); } } + hvs_configure_channel(0, width, height); int list_start = display_slot; - hvs_add_plane(framebuffer); + hvs_add_plane(framebuffer, 0, 0); hvs_terminate_list(); *REG32(SCALER_DISPLIST0) = list_start; @@ -51,69 +79,152 @@ static int cmd_dpi_start(int argc, const cmd_args *argv) { // 0x200 means clock/2 +#ifdef HYPERPIXEL + *REG32(CM_DPIDIV) = CM_PASSWORD | (0xe00 << 4); + *REG32(CM_DPICTL) = CM_PASSWORD | CM_DPICTL_KILL_SET | CM_SRC_PLLC_CORE0; + while (*REG32(CM_DPICTL) & CM_DPICTL_BUSY_SET) {}; + *REG32(CM_DPICTL) = CM_PASSWORD | CM_DPICTL_ENAB_SET | CM_SRC_PLLC_CORE0; + while (*REG32(CM_DPICTL) & CM_DPICTL_BUSY_SET) {}; +#else *REG32(CM_DPIDIV) = CM_PASSWORD | (0xf00 << 4); *REG32(CM_DPICTL) = CM_PASSWORD | CM_DPICTL_KILL_SET | CM_SRC_OSC; while (*REG32(CM_DPICTL) & CM_DPICTL_BUSY_SET) {}; *REG32(CM_DPICTL) = CM_PASSWORD | CM_DPICTL_ENAB_SET | CM_SRC_OSC; while (*REG32(CM_DPICTL) & CM_DPICTL_BUSY_SET) {}; +#endif printf("DPI clock set\n"); int rate = measure_clock(17); printf("DPI clock measured at %d\n", rate); - struct pv_timings t; - t.vfp = 0; - t.vsync = 1; - t.vbp = 0; - t.vactive = 10; - t.hfp = 0; - t.hsync = 1; - t.hbp = 0; - t.hactive = 10; setup_pixelvalve(&t, 0); -#define FORMAT(n) ((n & 0x7) << 11) + int dpi_output_format; +#ifdef HYPERPIXEL + dpi_output_format = 0x7f226; +#else + dpi_output_format = 0x6; +#endif + int format = (dpi_output_format & 0xf) - 1; + int rgb_order = (dpi_output_format >> 4) & 0xf; - *REG32(DPI_C) = DPI_ENABLE | FORMAT(6) | DPI_OUTPUT_ENABLE_MODE; - //gpio_config(0, kBCM2708Pinmux_ALT2); // pixel-clock + int output_enable_mode = (dpi_output_format >> 8) & 0x1; + int invert_pixel_clock = (dpi_output_format >> 9) & 0x1; + + int hsync_disable = (dpi_output_format >> 12) & 0x1; + int vsync_disable = (dpi_output_format >> 13) & 0x1; + int output_enable_disable = (dpi_output_format >> 14) & 0x1; + + int hsync_polarity = (dpi_output_format >> 16) & 0x1; + int vsync_polarity = (dpi_output_format >> 17) & 0x1; + int output_enable_polarity = (dpi_output_format >> 18) & 0x1; + + int hsync_phase = (dpi_output_format >> 20) & 0x1; + int vsync_phase = (dpi_output_format >> 21) & 0x1; + int output_enable_phase = (dpi_output_format >> 22) & 0x1; + + uint32_t control_word = DPI_ENABLE; + + printf("format: %d\n", format); + control_word |= FORMAT(format); + + printf("rgb order: %d\n", rgb_order); + control_word |= ORDER(rgb_order); + + if (output_enable_mode) { + puts("output enable mode"); + control_word |= DPI_OUTPUT_ENABLE_MODE; + } + if (invert_pixel_clock) { + puts("invert pixel clock"); + control_word |= DPI_PIXEL_CLK_INVERT; + } + if (hsync_disable) { + puts("hsync disable"); + control_word |= DPI_HSYNC_DISABLE; + } + if (vsync_disable) { + puts("vsync disable"); + control_word |= DPI_VSYNC_DISABLE; + } + if (output_enable_disable) { + puts("output_enable_disable"); + } + if (hsync_polarity) { + puts("hsync polarity"); + } + if (vsync_polarity) { + puts("vsync polarity"); + } + if (output_enable_polarity) { + puts("output_enable_polarity"); + } + if (hsync_phase) { + puts("hsync_phase"); + } + if (vsync_phase) { + puts("vsync_phase"); + } + if (output_enable_phase) { + puts("output_enable_phase"); + } + + + *REG32(DPI_C) = control_word; +#ifdef HYPERPIXEL + for (int x=0; x<26; x++) { + if (x == 10) {} + else if (x == 11) {} + else if (x == 18) {} + else if (x == 19) {} + else gpio_config(x, kBCM2708Pinmux_ALT2); + } +#elif defined(AUTO) + for (int x=0; x<28; x++) { + if ((x == 2) && vsync_disable) {} + else if ((x == 3) && hsync_disable) {} + else if (x == 14) {} + else gpio_config(x, kBCM2708Pinmux_ALT2); + } +#else + gpio_config(0, kBCM2708Pinmux_ALT2); // pixel-clock gpio_config(2, kBCM2708Pinmux_ALT2); // vsync gpio_config(3, kBCM2708Pinmux_ALT2); // hsync gpio_config(4, kBCM2708Pinmux_ALT2); // D0 gpio_config(5, kBCM2708Pinmux_ALT2); // D1 +#endif return 0; } -uint8_t count; - static enum handler_return updater_entry(struct timer *t, lk_time_t now, void *arg) { for (int y=0; y +#include +#include +#include +#include +#include + +static int cmd_hvs_dance(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("dance", "make the HVS dance in another direction", &cmd_hvs_dance) +STATIC_COMMAND_END(hvs_dance); + +timer_t updater; +gfx_surface *fb; +unsigned int x, y; +signed int xd, yd; +unsigned int width, height; + +static enum handler_return updater_entry(struct timer *t, lk_time_t now, void *arg) { + int start = display_slot; + hvs_add_plane(fb, x, y); + hvs_terminate_list(); + *REG32(SCALER_DISPLIST1) = start; + + if (x > (0x500 - width)) xd *= -1; + if (y > (0x400 - height)) yd *= -1; + + x += xd; + y += yd; + + if (display_slot > 200) display_slot = 0; + return INT_NO_RESCHEDULE; +} + +static int cmd_hvs_dance(int argc, const cmd_args *argv) { + x = (unsigned int)rand() % 0x500; + y = (unsigned int)rand() % 0x400; + xd = rand() % 25; + yd = rand() % 25; + return 0; +} + +static void dance_init(struct app_descriptor *app) { + width = height = 10; + fb = gfx_create_surface(NULL, width, height, width, GFX_FORMAT_ARGB_8888); + fb->flush = 0; + timer_initialize(&updater); +} + +static void dance_entry(const struct app_descriptor *app, void *args) { + for (unsigned int i=0; i #include #include #include #include +#include // note, 4096 slots total volatile uint32_t* dlist_memory = REG32(SCALER_LIST_MEMORY); -volatile struct hvs_channel *hvs_channels = REG32(SCALER_DISPCTRL0); +volatile struct hvs_channel *hvs_channels = (volatile struct hvs_channel*)REG32(SCALER_DISPCTRL0); int display_slot = 0; static int cmd_hvs_dump(int argc, const cmd_args *argv); @@ -14,18 +16,33 @@ STATIC_COMMAND_START STATIC_COMMAND("hvs_dump", "dump hvs state", &cmd_hvs_dump) STATIC_COMMAND_END(hvs); -void hvs_add_plane(void *framebuffer) { +static uint32_t gfx_to_hvs_pixel_format(gfx_format fmt) { + switch (fmt) { + case GFX_FORMAT_RGB_565: + return HVS_PIXEL_FORMAT_RGB565; + case GFX_FORMAT_RGB_332: + return HVS_PIXEL_FORMAT_RGB332; + case GFX_FORMAT_ARGB_8888: + case GFX_FORMAT_RGB_x888: + return HVS_PIXEL_FORMAT_RGBA8888; + default: + printf("warning, unsupported pixel format: %d\n", fmt); + return 0; + } +} + +void hvs_add_plane(gfx_surface *fb, int x, int y) { dlist_memory[display_slot++] = CONTROL_VALID | CONTROL_WORDS(7) | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ARGB) | CONTROL_UNITY - | CONTROL_FORMAT(HVS_PIXEL_FORMAT_RGBA8888); - dlist_memory[display_slot++] = CONTROL0_X(0) | CONTROL0_Y(0); - dlist_memory[display_slot++] = CONTROL2_H(10) | CONTROL2_W(10); + | CONTROL_FORMAT(gfx_to_hvs_pixel_format(fb->format)); + dlist_memory[display_slot++] = CONTROL0_X(x) | CONTROL0_Y(y); + dlist_memory[display_slot++] = CONTROL2_H(fb->height) | CONTROL2_W(fb->width); dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state - dlist_memory[display_slot++] = framebuffer; + dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0xc0000000; dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state - dlist_memory[display_slot++] = 4 * 12; // stride + dlist_memory[display_slot++] = fb->stride * fb->pixelsize; } void hvs_terminate_list(void) { @@ -47,11 +64,14 @@ void hvs_initialize() { hvs_wipe_displaylist(); + *REG32(SCALER_DISPEOLN) = 0x40000000; +} + +void hvs_configure_channel(int channel, int width, int height) { hvs_channels[0].dispctrl = SCALER_DISPCTRLX_RESET; - hvs_channels[0].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(10) | SCALER_DISPCTRL_H(10); + hvs_channels[0].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(width) | SCALER_DISPCTRL_H(height); hvs_channels[0].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202; - *REG32(SCALER_DISPEOLN) = 0x40000000; } void hvs_wipe_displaylist(void) { @@ -65,7 +85,8 @@ static int cmd_hvs_dump(int argc, const cmd_args *argv) { printf("SCALER_DISPCTRL: 0x%x\n", *REG32(SCALER_DISPCTRL)); printf("SCALER_DISPEOLN: 0x%08x\n", *REG32(SCALER_DISPEOLN)); printf("SCALER_DISPLIST0: 0x%x\n", *REG32(SCALER_DISPLIST0)); - printf("SCALER_DISPLIST1: 0x%x\n", *REG32(SCALER_DISPLIST1)); + uint32_t list1 = *REG32(SCALER_DISPLIST1); + printf("SCALER_DISPLIST1: 0x%x\n", list1); printf("SCALER_DISPLIST2: 0x%x\n\n", *REG32(SCALER_DISPLIST2)); for (int i=0; i<3; i++) { printf("SCALER_DISPCTRL%d: 0x%x\n", i, hvs_channels[i].dispctrl); @@ -81,8 +102,13 @@ static int cmd_hvs_dump(int argc, const cmd_args *argv) { uint32_t base = hvs_channels[i].dispbase; printf("SCALER_DISPBASE%d: base 0x%x top 0x%x\n\n", i, base & 0xffff, base >> 16); } - for (int i=0; i<16; i++) { - printf("dlist[%d]: 0x%x\n", i, dlist_memory[i]); + for (uint32_t i=list1; i<(list1+16); i++) { + printf("dlist[%x]: 0x%x\n", i, dlist_memory[i]); } return 0; } + +__WEAK status_t display_get_framebuffer(struct display_framebuffer *fb) { + // TODO, have a base layer exposed via this + return -1; +} diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index 6b6d1f52a6..bd7749937b 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -1,5 +1,6 @@ #pragma once +#include #include #define SCALER_BASE (BCM_PERIPH_BASE_VIRT + 0x400000) @@ -84,7 +85,8 @@ enum hvs_pixel_format { extern int display_slot; extern volatile uint32_t* dlist_memory; -void hvs_add_plane(void *framebuffer); +void hvs_add_plane(gfx_surface *fb, int x, int y); void hvs_terminate_list(void); void hvs_wipe_displaylist(void); void hvs_initialize(void); +void hvs_configure_channel(int channel, int width, int height); diff --git a/platform/bcm28xx/hvs/rules.mk b/platform/bcm28xx/hvs/rules.mk index 0d5c63f751..7b445ecfee 100644 --- a/platform/bcm28xx/hvs/rules.mk +++ b/platform/bcm28xx/hvs/rules.mk @@ -3,6 +3,7 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) MODULE_DEPS += \ + lib/gfx \ MODULE_SRCS += \ $(LOCAL_DIR)/hvs.c diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 450e8f10e4..eaa87ff363 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -25,7 +25,7 @@ void print_timestamp(void); #define BCM_PERIPH_SIZE (0x01100000U) #if BCM2836 - #define BCM_PERIPH_BASE_VIRT (0xe0000000U) + #define BCM_PERIPH_BASE_VIRT (MMIO_BASE_VIRT) #elif BCM2837 #define BCM_PERIPH_BASE_VIRT (0xffffffffc0000000ULL) #define MEMORY_APERTURE_SIZE (1024 * 1024 * 1024) diff --git a/platform/bcm28xx/include/platform/bcm28xx/dpi.h b/platform/bcm28xx/include/platform/bcm28xx/dpi.h index 3b0d16bcc9..37a8109f1d 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/dpi.h +++ b/platform/bcm28xx/include/platform/bcm28xx/dpi.h @@ -1,11 +1,19 @@ #pragma once #include +#include + +int cmd_dpi_start(int argc, const cmd_args *argv); +int cmd_dpi_move(int argc, const cmd_args *argv); +int cmd_dpi_count(int argc, const cmd_args *argv); #define DPI_C (BCM_PERIPH_BASE_VIRT + 0x208000) #define BIT(b) (1 << b) +#define FORMAT(n) ((n & 0x7) << 11) +#define ORDER(n) ((n & 0x3) << 14) + // copied from linux/drivers/gpu/drm/vc4/vc4_dpi.c # define DPI_OUTPUT_ENABLE_MODE BIT(16) /* Reverses the polarity of the corresponding signal */ diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 06a48b47c2..85b820c74a 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -118,7 +118,7 @@ static pmm_arena_t arena = { #endif __WEAK uint32_t get_uart_base_freq() { - return 0; + return 48 * 1000 * 1000; } void platform_init_mmu_mappings(void) { diff --git a/platform/bcm28xx/pll/pll_control.c b/platform/bcm28xx/pll/pll_control.c index a3e1094d03..99b3f4af7a 100644 --- a/platform/bcm28xx/pll/pll_control.c +++ b/platform/bcm28xx/pll/pll_control.c @@ -1,6 +1,7 @@ -#include #include #include +#include +#include #include #include #include diff --git a/platform/bcm28xx/pll/pll_read.c b/platform/bcm28xx/pll/pll_read.c index dc5a9df1b2..324d74551b 100644 --- a/platform/bcm28xx/pll/pll_read.c +++ b/platform/bcm28xx/pll/pll_read.c @@ -22,7 +22,8 @@ uint32_t get_vpu_per_freq(void) { } uint32_t get_uart_base_freq() { - return clk_get_freq(CM_UARTDIV, CM_UARTCTL); + return measure_clock(28); + //return clk_get_freq(CM_UARTDIV, CM_UARTCTL); } uint32_t get_pll_freq(enum pll pll) { @@ -44,6 +45,7 @@ uint32_t get_pll_freq(enum pll pll) { uint32_t get_pll_chan_freq(enum pll_chan chan) { const struct pll_chan_def *def = &pll_chan_def[chan]; + printf("def is 0x%x\n", def); uint32_t ctrl_val = *def->ctrl; uint32_t div = ctrl_val & def->div_mask; if (BIT_SET(ctrl_val, def->chenb_bit) || div == 0) @@ -185,13 +187,17 @@ const char *clock_names[] = { static int cmd_measure_clock(int argc, const cmd_args *argv) { if (argc != 2) { puts("error, missing argument"); - // reg offset default-freq when netbooting + // A = default-freq when netbooting a custom bootcode.bin + // B = default when netbooting kernel.img under closed fw on a pi2 + // reg offset A B puts("1 - H264"); // CM_H264 0x28 puts("2 - ISP"); // CM_ISP 0x30 puts("3 - sdram"); // CM_SDC 0xa8 - puts("5 - VPU"); // CM_VPU 0x08 100,000khz - puts("6 - OTP"); // CM_OTP 0x90 4,800khz - puts("9 - ???"); // 500khz + puts("4 - V3D"); // 250mhz + puts("5 - VPU"); // CM_VPU 0x08 100,000khz 250mhz + puts("6 - OTP"); // CM_OTP 0x90 4,800khz 4.8mhz + puts("9 - ???"); // 500khz 500khz + puts("10 - ???"); // 1.92mhz puts("12 - dsi0p"); // CM_DSI0P 0x60 puts("13 - dsi1p"); // CM_DSI1P 0x160 puts("14 - cam0"); // CM_CAM0 0x40 @@ -200,17 +206,17 @@ static int cmd_measure_clock(int argc, const cmd_args *argv) { puts("18 - dsi0e"); // CM_DSI0E 0x58 puts("19 - dsi1e"); // CM_DSI1E 0x158 puts("20 - gp0"); // CM_GP0 0x70 - puts("21 - gp1"); // CM_GP1 0x78 25,000khz + puts("21 - gp1"); // CM_GP1 0x78 25mhz 25mhz puts("22 - hsm"); // CM_HSM 0x88 puts("23 - pcm"); // CM_PCM 0x98 puts("24 - pwm"); // CM_PWM 0xa0 puts("25 - slim"); // CM_SLIM 0xa8 puts("27 - smi"); // CM_SMI 0xb0 - puts("28 - uart"); // CM_UART 0xf0 1,916khz - puts("29 - vec"); // CM_VEC 0xf8 - puts("30 - ???"); // 44khz + puts("28 - uart"); // CM_UART 0xf0 1,916khz 48mhz + puts("29 - vec"); // CM_VEC 0xf8 108mhz + puts("30 - ???"); // 44khz 44khz puts("38 - aveo"); // CM_AVEO 0x1b8 - puts("39 - emmc"); // CM_EMMC 0x1c0 + puts("39 - emmc"); // CM_EMMC 0x1c0 200mhz puts("42 - emmc2"); // CM_EMMC2 0x1d0 return 0; } diff --git a/platform/bcm28xx/rpi-ddr2/autoram/autoram.c b/platform/bcm28xx/rpi-ddr2/autoram/autoram.c index 0cb8e948af..67bd603c4a 100644 --- a/platform/bcm28xx/rpi-ddr2/autoram/autoram.c +++ b/platform/bcm28xx/rpi-ddr2/autoram/autoram.c @@ -5,10 +5,10 @@ #define UNCACHED_RAM 0xc0000000 #define MB (1024*1024) -static void stage2_dram_init(uint level) { +static void autoram_dram_init(uint level) { sdram_init(); uint32_t start = UNCACHED_RAM | (1 * MB); uint32_t length = 10 * MB; novm_add_arena("dram", start, length); } -LK_INIT_HOOK(stage1, &stage2_dram_init, LK_INIT_LEVEL_PLATFORM_EARLY + 1); +LK_INIT_HOOK(autoram, &autoram_dram_init, LK_INIT_LEVEL_PLATFORM_EARLY + 1); diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index 6a0fbdfa00..d758f908cd 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -20,7 +20,6 @@ VideoCoreIV SDRAM initialization code. #include "ddr2.h" #include -#include #include #include #include @@ -97,12 +96,6 @@ static const char* lpddr2_manufacturer_name(uint32_t mr) { #define MR8_DENSITY_SHIFT 0x2 #define MR8_DENSITY_MASK (0xF << 0x2) -static int cmd_dram_init(int argc, const cmd_args *argv); - -STATIC_COMMAND_START -STATIC_COMMAND("dram_init", "initialize dram controller", &cmd_dram_init) -STATIC_COMMAND_END(dram); - static enum RamSize lpddr2_size(uint32_t mr) { switch (mr) { case 0x58: @@ -602,8 +595,3 @@ void sdram_init() { init_late(); selftest(); } - -static int cmd_dram_init(int argc, const cmd_args *argv) { - sdram_init(); - return 0; -} diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 74e6d46146..2f25a62038 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -65,16 +65,22 @@ GLOBAL_DEFINES += \ ARM_ARCH_WAIT_FOR_SECONDARIES=1 ifeq ($(TARGET),rpi2) -# put our kernel at 0x80000000 -KERNEL_BASE = 0x80000000 -KERNEL_LOAD_OFFSET := 0x00008000 -MEMSIZE ?= 0x10000000 # 256MB -SMP_CPU_ID_BITS := 8 -GLOBAL_DEFINES += \ - BCM2836=1 + ifeq ($(FORCENOMMU),1) + # put our kernel at 0x00000000 + KERNEL_BASE = 0x00000000 + MMIO_BASE_VIRT = 0x3f000000U + WITH_KERNEL_VM = 0 + else + # put our kernel at 0x80000000 + KERNEL_BASE = 0x80000000 + MMIO_BASE_VIRT = 0xe0000000U + endif + KERNEL_LOAD_OFFSET := 0x00008000 + MEMSIZE ?= 0x10000000 # 256MB + SMP_CPU_ID_BITS := 8 + GLOBAL_DEFINES += BCM2836=1 MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) -MODULE_SRCS += \ - $(LOCAL_DIR)/uart.c + MODULE_SRCS += $(LOCAL_DIR)/uart.c else ifeq ($(TARGET),rpi3) @@ -85,7 +91,7 @@ GLOBAL_DEFINES += \ MEMBASE=$(MEMBASE) \ MEMSIZE=$(MEMSIZE) \ MMU_WITH_TRAMPOLINE=1 \ - BCM2837=1 + BCM2837=1 MODULE_SRCS += \ $(LOCAL_DIR)/miniuart.c diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index a027c9fb00..d7ec1d633d 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -150,6 +150,7 @@ void uart_init(void) { void uart_init_early(void) { if (*REG32(CM_UARTDIV) == 0) { + puts("fixing divisor"); // CM_UARTDIV can range from 0 to 1023 with a fractional resolution of 1/4096th // on the rpi1-3, this sets the freq to 19.2 / (0x3900 / 0x1000) == ~5.3mhz // TODO, have a better default for other models? diff --git a/project/rpi2-test.mk b/project/rpi2-test.mk index c71a7e7c25..94483d7103 100644 --- a/project/rpi2-test.mk +++ b/project/rpi2-test.mk @@ -8,4 +8,6 @@ MODULES += \ app/tests \ lib/cksum \ lib/debugcommands \ - + platform/bcm28xx/pll \ + platform/bcm28xx/hvs-dance \ + lib/tga \ From d587d3b493332867f2221bd9af0967c6ad1f3e06 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 9 Oct 2020 08:30:19 -0300 Subject: [PATCH 066/100] build rpi2-test on hydra --- default.nix | 3 +++ lk.nix | 3 ++- release.nix | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/default.nix b/default.nix index c8c399b767..b5c3911cdb 100644 --- a/default.nix +++ b/default.nix @@ -22,6 +22,9 @@ in lib.fix (self: { arm7 = { inherit (arm7) littlekernel; }; + arm = { + rpi2-test = arm7.callPackage ./lk.nix { project = "rpi2-test"; }; + }; vc4 = { shell = vc4.littlekernel; rpi3.bootcode = vc4.callPackage ./lk.nix { project = "rpi3-bootcode"; }; diff --git a/lk.nix b/lk.nix index 9211fd2f8d..84f26cc40b 100644 --- a/lk.nix +++ b/lk.nix @@ -1,10 +1,11 @@ -{ stdenv, project }: +{ stdenv, project, which }: stdenv.mkDerivation { name = "littlekernel-${project}"; src = stdenv.lib.cleanSource ./.; makeFlags = [ "PROJECT=${project}" ]; hardeningDisable = [ "format" ]; + nativeBuildInputs = [ which ]; installPhase = '' mkdir -p $out/nix-support cp -r build-${project}/{config.h,lk.*} $out diff --git a/release.nix b/release.nix index a7243647e8..e8341c4040 100644 --- a/release.nix +++ b/release.nix @@ -1,6 +1,9 @@ let self = import ./.; in { + arm = { + inherit (self.arm) rpi2-test; + }; vc4 = { inherit (self.vc4) rpi3 rpi4 vc4; }; From 531aba79d24178e60aba295cab49c497eda70975 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 9 Oct 2020 19:26:31 -0300 Subject: [PATCH 067/100] implement image loading --- platform/bcm28xx/hvs-dance/dance.c | 38 +++++++++++------- platform/bcm28xx/hvs-dance/pi-logo.tga | Bin 0 -> 68891 bytes platform/bcm28xx/hvs-dance/rules.mk | 5 +++ platform/bcm28xx/hvs/hvs.c | 7 ++-- .../hvs/include/platform/bcm28xx/hvs.h | 24 ++++++++--- 5 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 platform/bcm28xx/hvs-dance/pi-logo.tga diff --git a/platform/bcm28xx/hvs-dance/dance.c b/platform/bcm28xx/hvs-dance/dance.c index 017ac02bf3..95590ae692 100644 --- a/platform/bcm28xx/hvs-dance/dance.c +++ b/platform/bcm28xx/hvs-dance/dance.c @@ -1,9 +1,12 @@ #include #include +#include #include #include +#include #include #include +#include static int cmd_hvs_dance(int argc, const cmd_args *argv); @@ -15,7 +18,6 @@ timer_t updater; gfx_surface *fb; unsigned int x, y; signed int xd, yd; -unsigned int width, height; static enum handler_return updater_entry(struct timer *t, lk_time_t now, void *arg) { int start = display_slot; @@ -23,8 +25,8 @@ static enum handler_return updater_entry(struct timer *t, lk_time_t now, void *a hvs_terminate_list(); *REG32(SCALER_DISPLIST1) = start; - if (x > (0x500 - width)) xd *= -1; - if (y > (0x400 - height)) yd *= -1; + if (x > (0x500 - fb->width)) xd *= -1; + if (y > (0x400 - fb->height)) yd *= -1; x += xd; y += yd; @@ -38,32 +40,38 @@ static int cmd_hvs_dance(int argc, const cmd_args *argv) { y = (unsigned int)rand() % 0x400; xd = rand() % 25; yd = rand() % 25; + if (x > (0x500 - fb->width)) x = 0x500 - fb->width; + if (y > (0x400 - fb->height)) y = 0x400 - fb->height; return 0; } static void dance_init(struct app_descriptor *app) { - width = height = 10; - fb = gfx_create_surface(NULL, width, height, width, GFX_FORMAT_ARGB_8888); - fb->flush = 0; timer_initialize(&updater); + fb = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); + if (!fb) { + fb = gfx_create_surface(NULL, 10, 10, 10, GFX_FORMAT_ARGB_8888); + for (unsigned int i=0; iwidth; i++) { + int r = 0; + if ((i%2) == 0) r = 255; + for (unsigned int j=0; jheight; j++) { + int g = 0; + if ((j%2) == 0) g = 255; + gfx_putpixel(fb, i, j, 0xff000000 | (g << 8) | r); + } + } + } + fb->flush = 0; } static void dance_entry(const struct app_descriptor *app, void *args) { - for (unsigned int i=0; i (0x500 - fb->width)) x = 0x500 - fb->width; + if (y > (0x400 - fb->height)) y = 0x400 - fb->height; timer_set_periodic(&updater, 20, updater_entry, NULL); } diff --git a/platform/bcm28xx/hvs-dance/pi-logo.tga b/platform/bcm28xx/hvs-dance/pi-logo.tga new file mode 100644 index 0000000000000000000000000000000000000000..9ec1ba9df6307a812986d358cc8760ff3ac8368b GIT binary patch literal 68891 zcma*QNvw0%xu&wW+?b8mgBqOQLMamgPp2Wm|4#%949aV!r2nxxU54bAI`5 zV6U^e*IMuQe$8t4CQsM>2VFVd-urj^{l8xGaX-#MoRc``=SH$V5y>*nS)7M)_WvA7 z_bLfly*Nj4PUBpt0uYPMorCw|qC1D=CnVJ9$2p2~9OsOzId}QQIgGP+Q6$}7oCk5v zKNiWlphBT1)UU@?7Mf+DRoorNX%L`?agO2~$2pZi!1x5%@TZYE)5g6|=Y)#VPnta+fmmI7jD4lA?#)IXjXuWDesT#%asl5?6xe)(DlxfbeOM zAn=3D>WWC#CnG@!Vl(G5a;UkC^WcY(bUz^B7(;Y@RwQIj;_PqEQTzpXd0`~!*KvI4 z%dgkPmDr8q?~G7bpNa(O<2aEHi&2~l34sB*eF;aLs`umX;>k$TLw$MZ3vo*Y4&(3g ziBez{7o#^K>Apd7B2L5%;~d91JuebPD%`olxq3Ph=|FYv*utNWE6F&BzsqMLQ6bDQ z=1edY;La${{>zbcFOi_qD9*(5{t!vRk03fe70F?o!#I0!atz{}ekT&K8^=XYGGB-*9n+u3 zpL8$Pd+(9~*Mm6GeD$+P1h9yUf$BaVS30I|$Dh`=zapd9W~qEWt>PT0o?0J;rtd@| zWHJwa!99xhNf6zSbBg@+-aq=M|9Jg3|JgrWe_5X*5v@1l zLdO(U)_aurj|YFZ#+NB^cn?MHA^{Y-tNSCVpr7W`2}Jyxd;ahBzc}}QUH|RB{;$># zs!Svj^+sIinBuMV2})3s8q^eq2=EC#L|_&dJ;}a<+7Rf)ITiR>MI<2q^3sF#KOOx` zi9YoY{%U=B6kDGvCI0PW|Ihk=y7~WH_y4#5ZcVNgh$15QdR*u*?kP(A-M{^>RfC$G zAPMsH^e1;_fI;Ql_O{+oaQKda>R+&LMEl!?FP(11PU z)8MP+UjLl98uF=sHYvyS#z@vu7I|Px${t+cB?jUmRwv*`UI{>Hut$90WxFUKrTz>F zQlE<%&1}5~0IFYz>U$;PFCnkv{<*pjAXb*peLg`3BYaUPkpS0!I+8T5$KDf#IyI0c z>^;!H5q`&&?-P!g(|lk+9lI&8QKT;&u0s@E46SGw=OKO3IL>Zzb0llo28xKHKkziA zD14EE62T=XHO6-kI6sX+Y4utsDaCD0+6subBZpXm*7(Utr2H`cE+M%-NhwN~nt0W{ zAjl{xSqf&!&p?NnIPMiAi2sSwvz7L*h$#)oHsBK+2E=1`ngl}~#5s*~NjJFu>*AL} z4Kes1MKKu!CzQ+>`4~m_APou4n>xH|b8&_7)Q@+RP&-vyL{>)1B0&3(MWSOei$CiO zaJOxO*W&?*DMQjESN$tY%&C}2d{4q04bTLQ$gO<_eX!=RtGGb;D9+yLNV=SpjpDVKZW=FH>C=S2g0> z0m1DH?MpyeZ$5oOcH#=X&kc~Zx_}z*2z7vgP&*;+yZt~71lX+Mq2X9;2=vwINY;C_ z5`?)9wFw4yIv_Zh%6-Wf6LFFulW)hB+bHGv1UGXohH3_!@zueh`#cH9_|ZseKq+#M z3^wOcro$T(83|xo&)Iq35nt|Wc2*l8Mb&Wj;RXV+AsdxGqNf>Jz;%;r0NtkqC9%vg zjn4DG(henE{KP2Rt=Q_mG&nLaRn{2KleCaNkFzHWT^Uz8rjNy+EfYu+{HQKPd1!eV zluw`~fW#5}Kh9lw%7%otn*j*&-pOK_qBC`~#Vtd?K+{+3#n>`E9m!gq%63hz9nr9{ z45V2u(IGA;V1)!&Qb)W!Edp2lJ>2L8su3M3QD6~gPqz77THROyG9f4F~g+;iV;jw^TGg?-wG4q%Y;a_r+CDF+F6v~Z|c#s^C> zRTdf6H#wf*3f8a(!M36+la6Pjt@QTn5aBY-XX8r8;JWy;K8dZdDK)V^5wv3=&*4Bc4v4}&3Ev{I zM6~!wX>mLSTUb+{nvH%Z=@yE9SO80?mBVVH5K3b$u0@tc1*%<+;@KaS%61}V6OnyN z0*Z^=*dXDd4odE-j~ax5R-N-PA>;0t+QtD<*!xI98uA~8pXg|TR@zKb&q;sk+n1`^ zs6hGw)1lh`e(H$6nAVK~<3B>aKoOxKtAm*vIN|9r@~E!Nbk3x!>S#eFFoS>8PVz~_8F16 zl>~s8GD_$;kZ^S~rIhM*#F()5=$1g&pt~b`5+Lgi>s~>pD@ktP$W!lrf~W_(;L8jM zKg9Bi)j|ASd38soEX#X={o=UB=m?9qE{w z4x(L_-dgoD{67HOx?*)1hPpeHhI(M2-HjbebpSwX4`s9>0#md=n`u_h)qyCbc+(iw@6{4!ovVwaoeBLh1lGTAG(U^?^)=x`vXm?B!Hp0odnwVXs z;6Sd!IjXz+6RY^t%}fo=Dz%*0MgdKsE|6zS|EDU@p}XnlXg)P2#!-!%C5)JD%-+iZ zZ00sj^V+HaJBcWM>a}9}5~FB=oT5ddvi&+Rg3*MIRL9UB#v~d1wGu8)t;X_2I%Hw3 zva@roCZLco#BVy5l^>n?i+*T5{TM(n=n*l3i7a|MRG6tQeYEa_FZLclc$x^(}THKPt|p*eumc41sk_|ju` z1Ch_xrEQt5ky|y=#2PEI-?&&ZBAF^AT4&ytU15qkY()(jyu9TjaE9i?O< zJ!7Mz<|JJ4C?}A0`U0ZRv5ZL8Ud=%SpwU*#AP_(T z5$z>IQ?;Bj&00bO69VS`hERx*Xdp#MU48~spQ)@4^^u+wtK3OyKss{u7b3#e{$>)< z%B2$IGt!Q)Xdlv1J{^b4FVULO>M-OoTwv z-5o-4gST}67U+qv*x|-*{OQ{VSyIoYsVkIxOq!B1($aoAtC&MifQT(BJu3Tg1wC!X zHTL_3>__yd!9#DcMQ>s;&QW)`r^B@Z_nKnp2AarqLk>C0jZW29**{9mMIGsn)nud`z@(8k&oitcF0~ej;i_ zk*o&FAxNf05U519PD)xi@KDYYj!@fKD~!C#01z^dix$<<$F#^pb7=oqv>1Mq7S230 zE$*vCZk*tsC6s267Mp8jo6B3Tv(!eh$P=Q)6)@V%(Tfj^5kC|q$jOPprrS6V zA<9+AV;9#1qoRTVO*guzy^7OMiYgtt*|oYlQE6JEKpW@%K$NiHRQ0&hy~bUxhiDoO zjuN)Ek?oa+j8;c+r}HvmkAXESsnOyj@74i|GqB21WayJjhAZ8ZlPE=L)ys#Fwm0ZV zvGO7LPzFgNT1r1ZCm|A3YyVMz72$!5Z zZn45hOLYRLXx_-7GJ=5w#KSvbP@2bcqDv=$yN=R*g?!Cd>)J~9jv)>LNWxU}LN?MQ zS1%F5gu5^U8m4DbW-euN5m@(8@%2k04it(VCH@T&C*Q=m(!FDd7ylR&bj~Ud#gb&d z#sL=J4B*)F+oFW)agiRgHuDR?Yi?#r*h=>rN~)*s4J2Wz=S>2uoo=X3a9$GuOpDQv z5_nNI0oDX)W4dm3(M`K_1xHD|013(0)iI)rJB)-YAd})p z60ZaYY<86itnW&HD&PRUkkmNfYto;R_|Uze?lmO*J`_DamJ+7+I~3TuNEjnp#KnoIyHZh<9`UA`FK-8Ql18Ab@6V!HY=kf(dvhVp=N6o@AF6=@ET z1w&N#vJY;FdcdM)PEq=;VDHav3C39HqZPlRf%tYu3MmWbO7}D=K~I;bCJ4s}p6K;3 zC8)mHgNEDd@^|UHDiCq25loYbD%hhMxs@oc0YO+&r=1B^;kiEX)?_6>z+qao&}_MN zHd6_BVu7AGz~!k4LM7l>3RMpnCpsluY<8RxtQkzMaSeoN0n*HONAo%xrj*OmM_>zK zN%Isu)8n#yW;XFYG;R6~1yTjUeB7Vs{i?0*?UkNDLPg6MsNuCrsJ4vL&*+#S=~!4O zhEj#xbTa$WL>@UtuYAm0AmwmT;E{(4tKMx9FZ)0;O6Dv;^|$z_2B-k~wn{<^^SG z(*`8;(EAP%pg%JKu5?d+=95P;Y8!`I5R;M^eoMHp^EGwcjH5J@)RSJq93(Kb>egC{ zGG>KUF~Ll%xNla-(>+BdrCgp8ctcove+_h`RJqiJ2`AUNyS>F5HRgg;pX!Z00>rBZ z0P)}LqQ#Y0C3!Eq4I7J^#-PJg2<;e30$rFQD!k)zv_zZRBos&sv$KW{7XTrC7bD_q3d#yRqMh1_>hOmms)(4zEB zQkqh9?|x*bdpk-~KC$FG8x?=Hf;SH*v#?x7l(Y)pAi=0!7C zU@S;C1M;vXFw_=MZeCW#o+=hoUM1n^bc2L*b#)SQ+0s|GO62%Ay&i>?a51%Dc+(th ze!SdjLIb^0=0_*;L?A~E=TWM)7)Zthoq8g&7m`I}kpl&T6)8x&iWyxedbphl+z0{u8wB9Oa()qnIdHgSoQPc=ktiOQ8o z&7-vIfdK7_NnVl}-53a+637hV+>k+obdT2R1}vIg(Ga;UDpn%SYpqB;wbrd9uxF>F zkkAtpzkTaUB|fT4E^7#Uu_2&5y*^ZXQ{iZ;p3{=i%?MV4V8w#xMosUPFPgQk@E3JT z0M109SjTx7zPf_wpmf_x+!&%V!8ydC-K``X6Hg%+(5nBS*1F;nS)y3z&Zy`;Ozt?Z zaYZ(HW0t^8B8vd%ivwQOVIrysln1fW!Bi7plrEu1xHqb)E|B&R;@-UY3U<^t%R*h@!%hNluC*bHUne(8hxA$n0VEwM~xy-3=;UJMLxL}bv z7$>>n4mp&-CY6b>w5|djTS=ZI=VWll8HXY#13>2kkWY{t6@ek1lqy`=aHTD@^@@>F z=)ASa(Bs_km5W|Kll9MBh9;VmzNrK#aY#}R3$(<*#!El>2<$T2*lSU6RI%ezH?zU< z`Fk%ukdunq(G^?m%148Pj|I*(F#K}4XWukQL+0rb&JUX-9A{y6~&$JYc1 zd)(r@(ttfRhyrxWy%|_{kZ{c1JJGtS_$PsucJOKxsL!&TM=1tkYZnDpar&$O0xh0j z2)Nm1{v+U;2MAalsqQr!GIh;+XCQY<5>)+n1NwV`VgiG5rF#vi$N)FGi&RO1YW>@Q z{zjnKPj=NdzwR9c1qBlv+zqgj0zB9AxCU6`rDhcdCe(DV0rn`h0Uq1~Fe9Oki57_s z=sRLd%Qq+{(7gs!T0)H|=nL;Y5V>^_=jteMeT78vDl_O_11v2;n%qyS1kiq*bAjf7 zYe0g{fL!UG8V3DZvXo692#D@M5&#e5Tq!*C9FyX>=vSyO0K#9uxxi9hK61k_p9v6s z_j?u>Jz;-2t|Xuzf4xPKuMwPs6fKevvf_oAI@6oNWE(!oQK zbPtnoEGLoFFXroouhc^DsYT7hU^(*mXJry_dZ_?W5+;sexT-r8SKVv(KpufhVtDHy ze?6j3ZZNI8Rj$$&JDV~AHE#j?UZcXBO7*R&A3#>mk91E!l*$hOP(VtcxN!eW5wz1+ zr}TQBh9_O=p0uM>_RIYiNUtre_h~N7!syR_nh}KYJl=7Yd5U*RQ!D%DIal3@|NOuF zFZyvF#5s<0dVVBx?oKy%$nn!rF(Dp$ac*`H;Yz%`rB=)*jpQayeF*@FFUG(QD;25bcq7?MC&cMF2I1hm8Aajsp zX7Q zYM}}}X8uMGK{$%Dmz{b)$gIwbWDRBSz3NK$N^9z!7nS@&hFo|vSP!P?YnKV)OD>JUZaCp9$uUKIK`Z^jC=UnDP zAi`w63!;|WB)3&SUlO1=Re`{=&1if8Pq8~pb_+3q)A$N(Nhe7!MDI;Q=qdb*^A}mq zKOUMIOiu@}f2vJC&~Y{-^rJFGi93%fK}T1WPyvnPR6#9)`1d}Vp-$`d49L~FK~v3` zQOEw4KA$f4(P!M~QR|TBUs6q7hPS~>KVCz)GUzb|>1mf@ggbabF+x20mBprDGf-3b z78xj#X?kIj)^t-6>(3U}3z*?&d2El-n%ni0W?*~HR44ASmeSXY6;{MZ^gLqa zg)$$D?Nm@5x|{&smc3eOm6>K*vYzghXtkGhU(8+xj$0C0|1NFYCm zb9GZBb?Zw{*VMRSNzWt`vl+G4_j?L?6%={=AmyS=r^lEI%~_H^Jcj&O^A{8v=2T){ zU7)&26-YBaG9GJ(Vi^|$tuayJAiXn7PgEtUVgq?69cZT#bHjk^zD2>nkCC^56XJ10oJ-)Pt~^s48J;+WTRg{i`DJ z5SOgyAIZ9E;V4FL+?6>o`CW{|409Cl9W}c zjX|;Q!RbiEZ$%`204w?ZXt0 z!~8cY6Ui#hah!f>2;D!L*UsRPeejkJsn<}pgI7P!*>59>iBw20yzUe)Z1#756HhwB zsqayS8p}AVtwt5I`ZA|0(_DIvYq>W9KsM>c-?3!xA%zxkKXUi52f>swXFNjJN?*d37bf z-B$dhU$^!)s$a9u?FYnM_Dh*xO~1n8ohTqZiE;n1Mr*Sznb~t`gJMi;o5i`zeUo9v zz*f6^Er4Zn>2DqJD&Bn|^>4V$qDCEo`l;8keUyezxE#b;cPysKWiy&U<5iO4|BYRU zcj9gVmwm2E++mWm&5-SmE~y;b$!E9YX;(7X>ECm*auA5CyO44U{kO*@I1r2H&=fmb z|2gpU757fjGAYGb#wZXxd!uKg*vqmot%+8g-kyZe9?Ky`*k2fLQ;)g@Gt5bgy@UPf z8S3=67at~?*`9<8R)#5@U~?6`PV%YfQHCtWrgcZzSH+!ttfO_*d1%-XK3}F7u3W@9 zxFQm%QUmYU=}M|{n892p&^r^Cmw`mWAkM|Dk;HO1Btw+W8S*!ZB0+5AT?I9FOZ?ZX+J(Mtnm2e;2gf%P8j;QqaI7gmxjPLz5@zbR!-f>Ly& z1m(5;Ql3eb+DwF$Kod#!Eh;^C;?AD z(c$W5?w=r#K_IvZ(OXnE5@NESI@rE+t2NfPe4~Lm>3gS@!ehCmS*L+p`>z|~L#!Kv zPEkX11-a%^q2;F~@EB!i)v5Lw>DOiEGU<;3 zPREO+*`ltC53x!MOG6AI_lPFe)K1MFs$u&daeoielvbWpm`MdnkcSF&sjTM<#5CKr zt5jiYCn8Ng&Z$w|+1va$OQXJbCtlcA!p|gfY`srJAp}u6rT9IMQ0FJQPuSP{D1BF> z0L@#yHxedN0Q*lx9#yoprws_j$1w`j4cF!Q;u*DC1B}n+{_`XpqiZ9Ho%*me(fvP&r1|L{hmv zDEYEe@=TNLP z6*pTxX(gq+uTp?xO6Tm}k;r%$!s<1v602jBpeOyZ?$g!K1dJ14RSB$IcjRYDz7NqM zxqU?ztEr)Aaj&-6L;2t<(B#-qrBk455!F3{1smG7gzc|IixSYH%eIdwDauX2& zyS6(0*Am&h29Y0gJS$cZGYI0a%cHU(fnZV)eov%IcOg;=6)OQ*O0{G(_rz`eI9D0L zXL=&kmwlfpqz(-RESj4X^h8SI2={*@vP7cE(ySg4S;}JBt7XARWTBi8`&k+e)35Ai zw7KbX|3K~k=|X5^AgqMA`B95#jK)U46Dge8y3fR*jdg_w`tBkEn=Rt>qPAGDPIX7> zyPn!1M%RLH6GI4hY!!n1_ae-FtYQ~pU6;phsOGtDK-bku`#knQJ2j9xjB{&sqe;$_ zkSgQpN?=;PBla;_1(7C2NAgGAL%8qJhN}XUO+u5LF}6>ty-8QBwELv`i9)Cs7bc{^ zL~HA<-i{FdQ@YJ$h#-@ORuUOiBF(dVy{)7;BH-%={X{YM_%@M+!H6Rh;mSQ0QS;|? zRqX<}!o4E2SKOtSaX=m8R?3!WVo)URt_-kTsn#)J5F+clAP^kKIgGQX*2ZJb{^kxj^L!VCnTFp5c?_Z) zqhrYKK>%CXnnchCA`ErkgPylmN+S_j5O?02(fd$c2wt8I7hUNd(KdkX>9TMso5h4=g@wb2mV%JtvWPkk?{Q@96Dzt0HS_evUx=gvGonodiGJ0{wemo-2gLbW>;qG&*f9LGuX;am`%YlSF{oGgm? zw|&Hl+Wz{AI=^afuOI1iT1N2jf~^hY;#04)166*KjE4}yF|g_=Tm`AZF@B(LsSDgT zU>T=eFHpy=kj<;-6oHeRu7!%wd#%pV6zr?X`+nGmHbsv&QUD#3GQamg41e~^iX^sL=MN;-~@RE_k4qD6&ycH z!PY7r_H%3m+Fald09?Y`Z^oz+=JzN`7-`m~#aI{jWI_#P3ha!Go z6w|T!`8DL@*E(SZ_Qoi(R&~#m(9w%^%A=1oQ1B%Cc`IOH_JoAN0Rj9bz|$0-7vc_U zMVv}ot?iP1U&QY<_vm>HPN!h-G8ynT7-G;$GhyvpTcZkIJL!O&wBS>NQ`oDX0)Cs! zLRAB&Hrf#qkq#}>Br5^m1M7@Ns|0g{V@<58J!bVeza^T~eM=k7T@8+z5_}|U2pj=+ zsH%B^5C1zN!`nbw*Qu>o3!p@xWjt>|=VB{oVNb0}6&H6Uuvf9gM7MK47Xl{Iu;B*r5mY2h>Qm$1V;n?^G1lwmu*0sEOiGMA$?hhVmf*?B=1ikgfP^& zrT$b=gVS-L8yJ0%!J&~F9Jb*8szW;28;QjnOuTF=%;?=vjD{Jdp<>^Acl0+YWY!9q z*-Wy2GJPzW(oMW6&EO1Mh9b8DY21dX|AlXwXJv4jl6D5w3Rt0fLj}m!1zwm-D>XKQ zHx51!?wwIx$H3sUQG=tyGm&MpV5sj39Q7&1DxpS~>)@9(&7>7DuBN#=S>jywzTB7) z@~ZLx!aOW@>n6K*uhA}rELtIM$#Rxoj15)ZyrC}>?(_4Y{ zMa5HT=Wl?a2Rb+f3(DP+g>+O#!fTR+RLaOe^`TGXZGXwrx?wQM(!lW+^_#bdz_}GJ zCt=Sg7@!+9S$4RC^K&wor{_kBiWy=#HlaaPJt$1i{W3D+e|HCcx@q8vMMNR;DukaZ z!pSKFC@sP{qFE7$rANmt3HPSzfuvP>^f!>uQ(Ry@);7y{4GpR3%k5m67ABlMEfG(ULmxIbD7!!?@L_bZOvdNif z6D30hh!RI6HU0D)%(M}kEAhH;%`Hv_toUEu(YEjbH1Gk@_eog= zYeThkMQWL{9%T{kE)AL>+#q78K+WsZ^hs>qT5Z#Us4h3iPXw=9EzUqZgsx6EQM$P4 z4GBa6%J~5+rJ+ZFXkn;%7WwjwTK-=kgcYW;6kzD1iLl;W!xm^Kvo~(h0FuHyYeX#c zOavQYH7kphB(iEPvl*o*@&yqA2#qw|&*$h6amPzO5%z6aq_{^jc0Egngcp=tQSY?e z!cjI{Nre&qwA2z_pOjkIt6b=Beb|of=g4Znq%4L z1w@_(;#?iSqB`hbdyUegT=AEME4C-Xz-w5wRrtlsgQ14xl>IH`5#iLUJr;ar#E-Q2 zP_i|9QP+f#y!(O~zb^zb!xr+$+toJGhsd#q7m83-+bA7|Iw)uxcdJu6y~EYv%@fb;+|q_Z8ZE`z}PH71|mWKr(+~0qW)H@ zqh3m~f5AQ33t(-^P;D*{T&%!2jK3?fkuQEKApE0lR!rKRPVeqSEhbxi;Sm1<8^qs* zSz!^`K@2dvLRQRvB_RZEW9UOl_?IWSa12#d)Zz_7Gg~E7xg2k?h1R1d@XwfXs~6|o zafB6!m1-B_NF9el^Vb5TR086D{pb0PPFyMuAR#@j6~MNn5G^)?>2w68x)_O*MsaS}2iB4TRs`Q3cFz5C)Ck=pM0@AXFHr zK2NZunrvkttYCX!F$1BhfKsglTLCr&=W3E-_=Ug}Qu;Iv9dqW4s~&&5?*ZuNC# zQrs4Tli{f@_zV_JFq%pCxron|hU+0nYB1ENpoJ`W7EZy6*p!oCMi9ZP(Lk~Ihcp@P zaoqk%_aG{y+k z0_15jqdp^r>-k?N;SiX+0%GWkE|Opj%^g2iq{-Nqlpwh6-}j|8Bn6(a;8`0OXzl0D zQAzDXav3mnOf4LJl5M_hP#c^yv|N1jf#kx^_wbWvcX%M>Eknf4zs^;Q@_>m`JU!z| z(W74W&jKej1ti;9V1jGn>U980(t2oLYgE$D6nCuFbPR17EQo?;SsOpDwm?i^fzXk_ zbg99)uQ|K!gP206EKIvANa#EIac*8K#7LOOY@xs%SzX%Ng}BwiA@rdvfVQ+0yIM;= z*&>DdTkR4W#X7&OmuqRQ(^SF20Jbo$Buw)tjjfggPp@XVf~W5XxW6cLIdV8As-OFo zUPgiIAjiH^!dwYLecVSePK-wrjQ^+`7SYl(qfYm+qQXZaFGD8B=HKvwuSyy*9fQ?y zgpP@G)e6RkT4bo^m2i<@D4I}6nM&xT2!uy3&XqO6E}xTks>jepLiWgjnuVtk&Q=A2 z)T?Mfw6CBzY9t>>Q%OeptV&gd8lP2Q4HK?(-vaq)fpWN1#o7pz3DAu$!C$zUAdtha z66K`uDzQgNtA!q|P0`1BI}DKPsX3LtaFhY!{5xx(;4+Qv5Fh|)-dBqOy_}_R)iS`V zI}Egx(%9}jBfK#^p20|}ivcWVt#r}WYZ#V*3C|>*pirKrL)6l_(vF>6o}o}Y;8$Ni zj&zQpC4r_&4$O=*fx8HbZwbWU7D$G+MzdKt6asxJO;gzB4KJLi3hGlap%mLJi5d1dTYh-jljkh3RoEC~bP2Y8FIcx;j6uxn2P9OSKk~_Aw-792p(g zn;vd(g*2wnk5vs_ERk-+j|PBBiHA~65|O%j^M>YSdH}d^8uB=4=b?)Q0WU$>GpPAw zm`K*e2;=bUCu*n|&_W3T3r(YL3C*S>p&mv9X{~X>PnF8dBiGdaB6CWe+o&j~3NDA% z3Kap{p4l5%7$50aJ$b%K9)wS;qU2nJdK}(_5<6F*={Uk$^kXH$(Gt1xvo0K;s!dyI za~lp_To}jK_VgF@!`?g6a*2`>`%>*fYnS?A^BsvACbx{40jr6r=D~~=e#h{Z)|jCC z7w}Th=4mKKb79((x3qJR6tWH3-cy`N+HDe)X34;moC}Ip{c1-)O+~DQA-39aYwnT5 ziuI$$mPGuQHuR5irL?J~QDj$IwmU~4MKq#T<7&4-g6czRc|28?3iMwRYx17>e#BHLCqp}q7rHr$(2Pm{`2q0om({3;-_l*(PBM~&0gCf z+e-8sD+FIEIg)-UabzVaVtQ4{o#@caO6J?iz|2+>?JbfbDbhdsmm)X+7X~~01(8Ir zwM>K8p@B*7=Jg*!E~WJ)=$vBGz7>RIrRGT8X@JCnrDa4ND-BjD&0mI0X@{1^Ol(Km zRs#gy>z;I;hFlF>TWXP;f)=e>b7x@jI~2+3w<^f%xSV6|$hcG0uuID5OOLaQ=^TxE zI(D24;~}@MPSw7T71Ua-6|@OL{9!?GmXD-N#j~JnWHm!pvqp{8X04!UwVDePSG$6U zrqcvh?T9tatnRt1HC-!XWf?@%aWV`A$!jDd2RLW&QOZcT0UFZ{<(~cGqxd^;%wfGV z3k1Ug(|Q(2Fj^py%t`roAzAnu4F-YhUE0K1^oaZz~aCpO)^FXSgpxqvX! zj|K(apjg?DXe3gg*v3!C5V_mzjzh+3ri;UkOrK(8wQM1i>xY^cVpr7$*)z$ijCWD0 zz7)O((0qvVuKIGQm;k~|ssSELtbx(gz}P`LXSCfb#&9=q)r_)#0T|^C%$1Fau=@oH zpI?hDxn@i5M}vB&0XMy;x)6F$c-&j*9uBiy;^B;V&Y+q>@y5FVr1k>Nt+HPU9E#pr z#mIH8l`X=iH8{=GYeEWJTa5Won)PjgRuWvD5mbX;%{4N1d`Bo;JtAaO(VGwIN~|8a zu8RsgbhnVn74nYaFr!!WOE`YR1529)68}Evc*GARu#L1&b3Z0@F!l0MgsmU&x`{2jg)hNH5xu-XJ4^M4foL=a7PrMZo`bWO%0VmY}eL-@GUy z^jcUxZ?G6T1dBoIR*ajMbFuI>k^q{mj_yc)j{E8A*O8w4!K_V$aCGh*QVN zg0X{(VV`RwYpsCzp&*O6=eeKazAt5gb$MzUBikOLXihqY7KL?O45wTdS+?B|8c{ED zKSh04qHvMRQ&Sj%M9M@WBI#KQWi17(sa7_ZWh3e9NYZBKYm$N*UVTv08&er;h#JS4 zv*DEk0xP&Emh>uuII>HM{a%iW{tDNt62*N_#;N7qKE$V1!);NUR#aKhCAc~f^gU@s zbt2=Nh{~tXuQVFF4z(>3@+q>nEplRGR(2TvCZJ`o@1()LEpdc2I(?%N=kf@#I7-QC ztetXxh-Eo80a@9huOKoSzAdo;em5%kp~*`UNo=9L7X=9N<}j^5svt50vWV6!}fTbD!A$zVh%dcU}-341b&GAk5qC=}W|pC+0-GMMEw%9u{%iqG#2&u7W|OL5lvmL<5RZ-;`*8(ePR2p+9## zVdu(Nluz*rDJX1<_pDE0cZr%QWllg6MX@Ml)ivcS>R)b@ z)*3*2aem+ll4jKBz%u!5IuO)$IimG$I4H2F^`vmQk2y54IP#TT)!oNb@Iy!S>grNq zeZMf!2;TRBulePT+}GAmdU|JTcJrVNBe*cWyH^A;1NY~tIBIBa)qE{XBU`?Xj}jWO z8iq@AqC{f7Z*z6s@5o)Ca#?omEM zupG@=;hJA3BS&LpgYjjN#Fi$BWs{`;kx-J{xL8h+M%c{j7;FKF2ab@`Bs+fwUo|MB zZ*X9DS+M!}ezgUCUkKG66+y!1ddWnw>f&=TUJ~56nCNj~Eb$Nk8QaxLfTOnvrVHIb zv6UQ0U6I2s;9e^QQI!q>GLKP46ZPvv5MQMQ{cokjGKzJZMhvtGV#`MW5J6xyzm@h_ z$1X0`RTrlv4G3zqM}EipN=O{}#|%$O2I}GgDWN5hEXjb(grFy$N%p{6U<+5^>M;R9 z2t74;sGc)zY(}J%=Ez8X%yZD?Na{h>z+B7hvk1Ns*DHhApYFOs{tzVtz6WDMdKKuo1Vvsw98Ku-LG!J-1j)Wh=#pf8=CaRnhYofwWw~+lYv4FQ& zWKdNm#r*!?-ePk}3T!>C#`>-@ORIQAY|tEO8IAcBW4}R({ENf{D{9V&0Y-XtSqUFE zKY9t!#VI5^Hrsq#?7DBxtuDy=+BU5TUt$Sd5a{$~K_eu*G2t-NRTK2qNHPPjL@uQ{}09Y2?z4e1V zJiUzyBU+rlFvP{+zDU+52^9hm8iXa4F90<6I%pU;252?x?Bza?aA-UZmYSZnB4rqm zweN(q=_g5*a50h(6puh7Sp8}KPd9|A-FonqAiT&PqrC%BE!S1zHtvJ0&D@SIPRCRR z)#|h~ehs$y&r}ffQWUKNjgq)j1 z=^mu%IYLLd2Zc^CZ0oHK6sGu1{dQjAfBR9*yU9{*!>qH!Ae`b#>tmlN+u zg@jl&59vy#w(GQ#NeRIS7Bl4RVH5)LIn z38q>)13G%tDbu608iydaB!J{jks|o(k+jlvNCr|foh~Izok3@Gj|vm<534Y6Lf43= z`I@@5jJZcu0kaB(0jUCy3=DOJndUI?dQjk83EZQz zjVag^+`8IAMhka{AU`2woPA9})(??)f{$C>${BP4iZPj-uyIgBO6Z!1Xehi@NT5F{ zbgmLzU-7EwQ)l3tx*aUz3j{er_w0<3MBSa*!c#(rm_V2yRN&ER0Wd7s>G)Cm#B$sg zDBb?eDh$!5)6@otjCqUPcLs7FrEu<$D46R=VanJ%05#PPAcrF5*q;Kp%`1Xa-3Mg!BM&{l%}!BHnMh}v54Jda6Jf*Ob>Y4WDtRx%razajG@ zKdJYHnZP5hTO?aCmB4BrJHRfBuU}4J-wTR!yj~giDzE}8fz>>AfEoY%bV0kB>Sq#o zBw!^-*sR8hV*4KTjss=ZZ-6i9Z9Ez z3;!nsnb%GRliaO|T6LU&)f2sneG_y1?Z|Bne5+=ujYWpPTp)Ifm)%q(pOKX+DnwHTws2$fK#b%)U@!kww>1z$+ zA7W`wyTU=CAFVN7)T4w$YQXiFleV)iTMHz}v52F61H;klb z5wH>@Y`(1p0R@bv5N?$8U0c9}vw#%{-)-3TThPs;O1v!4T#GxzxxWQW=y}754DEb7 zHlRmy_s<-0v3bu4FDVkWWDr|51&_}d#CUWyEuN;E{v9Up{NPt%qOdi;oY5K&R;=^= z5|i*09Z9k$l1czQa0ZSL$<*HMhWL^8Mklb?l&Joy5*!?nIiox6lyI?mZ32&&J6A@} z(b@AXR55p~@_mI4g%jDoBbCTgXW$aWxWd6r6Qhf_ktt%{Oq)>F=-hXhK=cOaCi=kW zP!YN;g8?i75J~W)nfQ|g1>Ec6PSr%83S9|emd?Ok3VC_d$Z2yUBl6Oy;s3w66f%ZO zdHoQ(`2$0H;e-0QE2jcgG#H)qUeWJt;yMuuPI{DwH= zl0=@j$U`Hexj93_$OM3py<$TxBO_eMX^2S+s(lpi7#I|&9Yc5-iy?ODaxak&g{%aN ztegQ!$3ItYNNEToS3?jCHUwHGvR3q6B5TuW16t{#s%+qOJu)Uiqqaf=H}TeMDQ~_% z0;VbB4pWA_(7h*tFdGB%e)>g`^xcX{Wu?4{3WOWEMg=w$vbRwXX=GZukcYm*6M-t(GBma`D9$t}ihm$=Ynvw5OmRq>;GhNF*cinP zS|bjC_XP@onQ~=NOp>6z7IZTWs3F0XJ7hxpPk`oE1Pn|GM+8?1JZFX2r3w1>JRHpy zYsv(g`eD64iZS;M%#|58p>`->B}iB}5>Tp|!Hl{02Y~|MF_kNWVx(j{XhFwj3oEw_ zRP$(!8GhH8!N6yTge7}OU9#Q0)=4Z@GZ>ga^8+TB8MHrZPL_ZcGWs1TzGb`DXhWiGqrRSI7EhKbNR;Y{EuTjre-E;iAJrOg~` zo{kJ}_DOXuE9vJQ?!@BjXw$Au`YrGg#)zofcLKLADsymm)b5mUF_JPl zEP5voA%6ZvkBN}SWhkry7*kJg`Z|;;p91FhfUAUyxdmV&yy^WfDiCD#y_JU%AdAs1 z5F$@$&($Ff6$wdCS3%tB$GO=Oq-Yg{{*@N5UWXN4{Bcg9HLf=YdwzTw1legsIsf zv^ynSY<9#^zCOKpG&1}j$k3QPOn4Q-@?Sk65MmEdRs!YUY)dI{PKizl7gP8DfNG~) zRiBIu|MxMB1~mETg<$QKo<-1ehgMDrs6l{$d6@b_a-T;n?u$f;&R!+LEgJN~WPsE2 zfEU2I5LCSr{KwVe_!HqURU zuje=ZJ)y|(p11qnqF)m6KU97Q0FH^~l=)0You4*$Ka9++&2v8l!PZzyXy~zsvnMbN zt3%Ia>(Jt7tJrM|5gh5Ptu@)9*nS`&C24zeL@;jEvpczP3lRZ+tcX2S0XD-&NR@!r zkJCSdtd|nh{mSfqN`O24u#N7H085||k?w!p4v_qJRa~s|&Fm)#`f9ps$dozdNLpNi zP3DnVzY;n0gp=q&KlRs|HA+7L3AcS{nP}6;KvTlS=nIi}kL)o~!fsng*hf!mHQw_{ zdQf%xIH?jYjHK8gj2;mht`nLjRtkPSRZcAvZT18pN`xjG=hqk>5*j)SP2;zs!Rq5r znM2$hCTB57R^DMxo;=?g-rzpweN? zQ~-r&;6ewEL3Q|CB;D6YIHqz)^L?~ysNB3K_kI-IyoAMYj^JC56tYR9B(Xb?fal{% z$Dy1gDF8rBBWCjoAocv^Gf2}H`K?y$c@b6g9)tIHiPv+ucNR9r3Y=h5mlIPw3ZhI- zsheaJ(C7kWRg5x=vnQsEa2>aXajp~v&G$(${S|=ZKL|n~v5ZaEr?^5iccBA6PPyw8 zl=;Nmg0ZsszeU9wF3%K6!APc3XWflq*DS>;$zMVdHq)u0}|bUN8>^O(b~N} ztB}|w0(IiKeFL^&+=J431GZSZSeRL0eYG9(SIR)hK^?pZGeud3AfE1CBH{3h#^=XX z`}JMS{ix8mLNbQMWK3{tS#&}2WnxKLOjk^dbT6Z#(mc+d1b;oQ($`Bhp_6e(WFZZC zfHjym{!Rj?ipeRDI8N%FOT|-MmAfS{sq49Q$QpkG4oZqICx3!N{vTbes7a09&&2|W zdWSO9P(yn;F1lApxHXJ(`I|`UH|?l~c{G!6{>S4lC>Lip{wArCWFjfeE6G~eYv~4y zpG1wy;#&Z`N>W%XeioG%k9o`<=KFKrjA|e-w#_HyHe~sr+5#MM6jn_|$!m1nK=ar*A}3m#yB`#FVrY z6qRHu55FHt_c}>d2C7zmPm=Kgae%LCWt8aNAlZ+zALk^_l_k*1h^5~PfGecG6a@q@ zi;Lk8BI&TD0ML6B=Yp`PU7t7pVSwxC?AC}wIO6(0jHLT9NnwEpHvhJVDpdUd78=Rb zQ)~kqyhYugl5iYqtx(^B-KQoeozpW>AnEs1=Vw&Hc!M~XjDDt0{7b4Iyt{m_;%b% z<_o4*-VOYaO0J3NJP<`Lu|E1$B%PANd?I4IZ^)wW!%Ysm6%4Uri`cp{>l!OToakv7lG+4&YmhUKBdf=Yo__nmrQiLBT9*_9H&ZDbO?ZW z5a&{*s$jPehD}-sG6gY?i(bl&4;vVoJx4E2{qOR%=H9YfZKfLJkSMze<{WCRNzNuA zvmfVN61|c~k+Y=@VW@cx#n9$J80W>6G0x?ROsV9e1XDJG>~pYFLXD$_wPLnfje0qgsW!PJ${XTiTmdnRb1rFu_(QS);^xTAAQ_3pC*qbNKF(D_ zNSYvi*FfAvaY_-}hl02?t_(5ZDj_6I5Wi_4ZlpM|1jIN_2m0l4WthvjN*GBL%)1SY zCdR;EkHa_(^U1g}%oSV}n3<%io2}0&vB~umrxY-@$*1GW5TD|T%zm7D1Ij}?q4u`e zFiz2Uu8RVK!NG?4Y+M=UGh9KH7#YX8a`6(izW_=qCd@QSIZm#OE5qmtHlsKf*K#|@ ztDgyij{h3&Z=1KTe&p)7ZJ4XLqQD?d2A42R)qUCxVAvpC&B;7CL13T6j! zN|AF^8Bf;-bb8VP`lZM?rx17KWlt!^#g~=&}TZb5?N<)G%m6h7cH; zf-re}g*w{H&&Ni`z|fivLyM|Rs(tXB_q728*es)TWkbJW81X7>^v1S#Fj2@mx+sL# zj)9?vGmHTFG(F8N?F|w+b@vo2rKc(rx@1ELj89YCU#HDqRqVirsRb@n7~-M6Ov@l+ z2!ZiwOe|FhZFlC5&}rpG0)$6_SzH-HV0`lTqqH|fbZB!0t99d=P|oK_hT3BoZ#f_cc?!S6!QZ^2^1(o zPOmGri*;?KHDCVBo^Ta49KlR+499FphhC6sp|s=GK&i7uIOev;?xnVDB~UUC;#_H< z(Xy8)#_TspNt{nhr-^zbiPBRk$&}4d0tKoc=RzZ=zQ@ZLP7DJ=llVN4xs)dd=V+Lu zHVV7XW)^E`CXzZP__prwP#LB`bNVR^LdqRVz#I{{C}$wm7))&~Mgrk5jC1A5D9z@4 zYU|Zk--}#rmiUQ?>?jbb;^7%H?i|NFay%TjEQMLSIu4oq9d1)`5~m~ik+^bERVt{H zx4F$HxH~51apj_qaz*Aa&c)9nQPEXg9IBN*9#<~<7*`ZMjC1u?Bq}MbSZ=^Y2EIMeX^o#4Q(n zmMe-5jt_nH@yddQc?!eK5_apIk(V8pRs!BipstQ4nQXqAp zDp $@ + +GLOBAL_INCLUDES += $(BUILDDIR)/$(LOCAL_DIR) + include make/module.mk diff --git a/platform/bcm28xx/hvs/hvs.c b/platform/bcm28xx/hvs/hvs.c index ec91536662..b4cc4b9fae 100644 --- a/platform/bcm28xx/hvs/hvs.c +++ b/platform/bcm28xx/hvs/hvs.c @@ -34,11 +34,12 @@ static uint32_t gfx_to_hvs_pixel_format(gfx_format fmt) { void hvs_add_plane(gfx_surface *fb, int x, int y) { dlist_memory[display_slot++] = CONTROL_VALID | CONTROL_WORDS(7) - | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ARGB) + | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) +// | CONTROL0_VFLIP | CONTROL_UNITY | CONTROL_FORMAT(gfx_to_hvs_pixel_format(fb->format)); - dlist_memory[display_slot++] = CONTROL0_X(x) | CONTROL0_Y(y); - dlist_memory[display_slot++] = CONTROL2_H(fb->height) | CONTROL2_W(fb->width); + dlist_memory[display_slot++] = POS0_X(x) | POS0_Y(y) | POS0_ALPHA(0xff); + dlist_memory[display_slot++] = POS2_H(fb->height) | POS2_W(fb->width); dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0xc0000000; dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index bd7749937b..385452def3 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -45,11 +45,12 @@ extern volatile struct hvs_channel *hvs_channels; #define CONTROL_END (1<<31) #define CONTROL_VALID (1<<30) #define CONTROL_WORDS(n) ((n & 0x3f) << 24) +#define CONTROL0_FIXED_ALPHA (1<<19) +#define CONTROL0_HFLIP (1<<16) +#define CONTROL0_VFLIP (1<<15) #define CONTROL_PIXEL_ORDER(n) ((n & 3) << 13) #define CONTROL_UNITY (1<<4) -#define HVS_PIXEL_ORDER_ARGB 2 - enum hvs_pixel_format { /* 8bpp */ HVS_PIXEL_FORMAT_RGB332 = 0, @@ -76,11 +77,22 @@ enum hvs_pixel_format { HVS_PIXEL_FORMAT_YCBCR_10BIT = 17, }; -#define CONTROL0_X(n) (n & 0xfff) -#define CONTROL0_Y(n) ((n & 0xfff) << 12) +#define HVS_PIXEL_ORDER_RGBA 0 +#define HVS_PIXEL_ORDER_BGRA 1 +#define HVS_PIXEL_ORDER_ARGB 2 +#define HVS_PIXEL_ORDER_ABGR 3 + +#define HVS_PIXEL_ORDER_XBRG 0 +#define HVS_PIXEL_ORDER_XRBG 1 +#define HVS_PIXEL_ORDER_XRGB 2 +#define HVS_PIXEL_ORDER_XBGR 3 + +#define POS0_X(n) (n & 0xfff) +#define POS0_Y(n) ((n & 0xfff) << 12) +#define POS0_ALPHA(n) ((n & 0xff) << 24) -#define CONTROL2_W(n) (n & 0xffff) -#define CONTROL2_H(n) ((n & 0xffff) << 16) +#define POS2_W(n) (n & 0xffff) +#define POS2_H(n) ((n & 0xffff) << 16) extern int display_slot; extern volatile uint32_t* dlist_memory; From e9db3ab3865c9d179d04985f1803ce614c1ef090 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 11 Oct 2020 09:21:17 -0300 Subject: [PATCH 068/100] partially fix pi1, start pi4, overhaul many things --- arch/arm/arm/arch.c | 2 +- arch/{vc4 => vpu}/arch.c | 0 arch/{vc4 => vpu}/include/arch/arch_ops.h | 0 arch/{vc4 => vpu}/include/arch/arch_thread.h | 0 arch/{vc4 => vpu}/include/arch/aspace.h | 0 arch/{vc4 => vpu}/include/arch/defines.h | 0 arch/{vc4 => vpu}/include/arch/spinlock.h | 0 arch/{vc4 => vpu}/include/arch/vc4_pcb.h | 0 arch/{vc4 => vpu}/include/arch/vc4_traps.h | 0 arch/{vc4 => vpu}/intc.c | 0 arch/{vc4 => vpu}/interrupt.S | 0 arch/{vc4 => vpu}/rules.mk | 4 +- arch/{vc4 => vpu}/start.S | 0 arch/{vc4 => vpu}/startup.c | 0 arch/{vc4 => vpu}/thread.c | 0 arch/{vc4 => vpu}/thread_asm.S | 0 default.nix | 19 +++- dev/timer/vc4/rules.mk | 9 ++ {arch => dev/timer}/vc4/timer.c | 30 +++--- lib/elf/elf.c | 2 +- lib/libc/string/arch/{vc4 => vpu}/rules.mk | 0 platform/bcm28xx/gpio.c | 2 +- .../bcm28xx/hvs-dance/RPi-Logo-Reg-SCREEN.png | Bin 0 -> 14507 bytes platform/bcm28xx/hvs-dance/pi-logo.tga | Bin 68891 -> 0 bytes platform/bcm28xx/hvs-dance/rules.mk | 5 +- platform/bcm28xx/include/platform/bcm28xx.h | 7 +- platform/bcm28xx/intc.c | 8 +- platform/bcm28xx/mailbox.c | 6 ++ platform/bcm28xx/platform.c | 9 +- platform/bcm28xx/rules.mk | 93 +++++++++--------- .../bcm28xx/{ => sdhost}/block_device.hpp | 0 platform/bcm28xx/sdhost/rules.mk | 9 ++ platform/bcm28xx/{ => sdhost}/sd_proto.hpp | 0 platform/bcm28xx/{ => sdhost}/sdhost_impl.cpp | 0 project/rpi1-test.mk | 13 +++ release.nix | 2 +- target/rpi1/rules.mk | 14 +++ target/rpi2/rules.mk | 3 + target/rpi3-vpu/rules.mk | 3 +- target/rpi3/rules.mk | 3 + target/rpi4-vpu/rules.mk | 3 +- target/rpi4/rules.mk | 6 ++ 42 files changed, 178 insertions(+), 74 deletions(-) rename arch/{vc4 => vpu}/arch.c (100%) rename arch/{vc4 => vpu}/include/arch/arch_ops.h (100%) rename arch/{vc4 => vpu}/include/arch/arch_thread.h (100%) rename arch/{vc4 => vpu}/include/arch/aspace.h (100%) rename arch/{vc4 => vpu}/include/arch/defines.h (100%) rename arch/{vc4 => vpu}/include/arch/spinlock.h (100%) rename arch/{vc4 => vpu}/include/arch/vc4_pcb.h (100%) rename arch/{vc4 => vpu}/include/arch/vc4_traps.h (100%) rename arch/{vc4 => vpu}/intc.c (100%) rename arch/{vc4 => vpu}/interrupt.S (100%) rename arch/{vc4 => vpu}/rules.mk (89%) rename arch/{vc4 => vpu}/start.S (100%) rename arch/{vc4 => vpu}/startup.c (100%) rename arch/{vc4 => vpu}/thread.c (100%) rename arch/{vc4 => vpu}/thread_asm.S (100%) create mode 100644 dev/timer/vc4/rules.mk rename {arch => dev/timer}/vc4/timer.c (77%) rename lib/libc/string/arch/{vc4 => vpu}/rules.mk (100%) create mode 100644 platform/bcm28xx/hvs-dance/RPi-Logo-Reg-SCREEN.png delete mode 100644 platform/bcm28xx/hvs-dance/pi-logo.tga rename platform/bcm28xx/{ => sdhost}/block_device.hpp (100%) create mode 100644 platform/bcm28xx/sdhost/rules.mk rename platform/bcm28xx/{ => sdhost}/sd_proto.hpp (100%) rename platform/bcm28xx/{ => sdhost}/sdhost_impl.cpp (100%) create mode 100644 project/rpi1-test.mk create mode 100644 target/rpi1/rules.mk create mode 100644 target/rpi4/rules.mk diff --git a/arch/arm/arm/arch.c b/arch/arm/arm/arch.c index ce955c015f..4241706a3a 100644 --- a/arch/arm/arm/arch.c +++ b/arch/arm/arm/arch.c @@ -242,7 +242,7 @@ static void arm_basic_setup(void) { #endif /* set the vector base to our exception vectors so we don't need to double map at 0 */ -#if ARM_ISA_ARMV7 +#if ARM_ISA_ARMV7 || ARM_ISA_ARMV6K arm_write_vbar(KERNEL_BASE + KERNEL_LOAD_OFFSET); #endif } diff --git a/arch/vc4/arch.c b/arch/vpu/arch.c similarity index 100% rename from arch/vc4/arch.c rename to arch/vpu/arch.c diff --git a/arch/vc4/include/arch/arch_ops.h b/arch/vpu/include/arch/arch_ops.h similarity index 100% rename from arch/vc4/include/arch/arch_ops.h rename to arch/vpu/include/arch/arch_ops.h diff --git a/arch/vc4/include/arch/arch_thread.h b/arch/vpu/include/arch/arch_thread.h similarity index 100% rename from arch/vc4/include/arch/arch_thread.h rename to arch/vpu/include/arch/arch_thread.h diff --git a/arch/vc4/include/arch/aspace.h b/arch/vpu/include/arch/aspace.h similarity index 100% rename from arch/vc4/include/arch/aspace.h rename to arch/vpu/include/arch/aspace.h diff --git a/arch/vc4/include/arch/defines.h b/arch/vpu/include/arch/defines.h similarity index 100% rename from arch/vc4/include/arch/defines.h rename to arch/vpu/include/arch/defines.h diff --git a/arch/vc4/include/arch/spinlock.h b/arch/vpu/include/arch/spinlock.h similarity index 100% rename from arch/vc4/include/arch/spinlock.h rename to arch/vpu/include/arch/spinlock.h diff --git a/arch/vc4/include/arch/vc4_pcb.h b/arch/vpu/include/arch/vc4_pcb.h similarity index 100% rename from arch/vc4/include/arch/vc4_pcb.h rename to arch/vpu/include/arch/vc4_pcb.h diff --git a/arch/vc4/include/arch/vc4_traps.h b/arch/vpu/include/arch/vc4_traps.h similarity index 100% rename from arch/vc4/include/arch/vc4_traps.h rename to arch/vpu/include/arch/vc4_traps.h diff --git a/arch/vc4/intc.c b/arch/vpu/intc.c similarity index 100% rename from arch/vc4/intc.c rename to arch/vpu/intc.c diff --git a/arch/vc4/interrupt.S b/arch/vpu/interrupt.S similarity index 100% rename from arch/vc4/interrupt.S rename to arch/vpu/interrupt.S diff --git a/arch/vc4/rules.mk b/arch/vpu/rules.mk similarity index 89% rename from arch/vc4/rules.mk rename to arch/vpu/rules.mk index d1b0d66c65..afc37f7f17 100644 --- a/arch/vc4/rules.mk +++ b/arch/vpu/rules.mk @@ -14,7 +14,6 @@ $(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/start.ld ARCH_LDFLAGS += -L/nix/store/cwpy4q0qvdwdif1zfwnfg5gi50c6j9w8-vc4-elf-stage-final-gcc-debug-6.5.0/lib/gcc/vc4-elf/6.2.1/ MODULE_SRCS += \ - $(LOCAL_DIR)/timer.c \ $(LOCAL_DIR)/arch.c \ $(LOCAL_DIR)/thread.c \ $(LOCAL_DIR)/intc.c \ @@ -22,6 +21,7 @@ MODULE_SRCS += \ $(LOCAL_DIR)/thread_asm.S \ $(LOCAL_DIR)/interrupt.S \ -GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1 +MODULE_DEPS += dev/timer/vc4 +GLOBAL_DEFINES += VC4_TIMER_CHANNEL=0 include make/module.mk diff --git a/arch/vc4/start.S b/arch/vpu/start.S similarity index 100% rename from arch/vc4/start.S rename to arch/vpu/start.S diff --git a/arch/vc4/startup.c b/arch/vpu/startup.c similarity index 100% rename from arch/vc4/startup.c rename to arch/vpu/startup.c diff --git a/arch/vc4/thread.c b/arch/vpu/thread.c similarity index 100% rename from arch/vc4/thread.c rename to arch/vpu/thread.c diff --git a/arch/vc4/thread_asm.S b/arch/vpu/thread_asm.S similarity index 100% rename from arch/vc4/thread_asm.S rename to arch/vpu/thread_asm.S diff --git a/default.nix b/default.nix index b5c3911cdb..84799bdc1c 100644 --- a/default.nix +++ b/default.nix @@ -7,7 +7,7 @@ let name = "littlekernel"; src = lib.cleanSource ./.; #nativeBuildInputs = [ x86_64.uart-manager ]; - nativeBuildInputs = [ x86_64.python ]; + nativeBuildInputs = [ x86_64.python x86_64.imagemagick x86_64.qemu ]; hardeningDisable = [ "format" ]; }; uart-manager = self.stdenv.mkDerivation { @@ -19,11 +19,28 @@ let x86_64 = pkgs.extend overlay; arm7 = pkgs.pkgsCross.arm-embedded.extend overlay; in lib.fix (self: { + shell = pkgs.stdenv.mkDerivation { + name = "shell"; + buildInputs = with pkgs; [ + pkgsCross.arm-embedded.stdenv.cc + pkgsCross.i686-embedded.stdenv.cc + pkgsCross.vc4.stdenv.cc + pkgsCross.aarch64-embedded.stdenv.cc + pkgsCross.riscv32-embedded.stdenv.cc + pkgsCross.riscv64-embedded.stdenv.cc + python + ]; + ARCH_x86_TOOLCHAIN_PREFIX = "i686-elf-"; + ARCH_x86_TOOLCHAIN_INCLUDED = true; + ARCH_arm64_TOOLCHAIN_PREFIX = "aarch64-none-elf-"; + }; arm7 = { inherit (arm7) littlekernel; }; arm = { + rpi1-test = arm7.callPackage ./lk.nix { project = "rpi1-test"; }; rpi2-test = arm7.callPackage ./lk.nix { project = "rpi2-test"; }; + rpi3-test = pkgs.pkgsCross.callPackage ./lk.nix { project = "rpi3-test"; }; }; vc4 = { shell = vc4.littlekernel; diff --git a/dev/timer/vc4/rules.mk b/dev/timer/vc4/rules.mk new file mode 100644 index 0000000000..bedd03f803 --- /dev/null +++ b/dev/timer/vc4/rules.mk @@ -0,0 +1,9 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += $(LOCAL_DIR)/timer.c + +GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1 + +include make/module.mk diff --git a/arch/vc4/timer.c b/dev/timer/vc4/timer.c similarity index 77% rename from arch/vc4/timer.c rename to dev/timer/vc4/timer.c index d5e74e1a73..87215949e3 100644 --- a/arch/vc4/timer.c +++ b/dev/timer/vc4/timer.c @@ -1,13 +1,15 @@ -#include -#include -#include -#include +#include #include +#include +#include #include -#include +#include static enum handler_return timer0_irq(void *arg); +static platform_timer_callback timer_cb = 0;; +static void *timer_arg = 0;; + lk_bigtime_t current_time_hires(void) { //TODO, deal with rollover return ( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO); @@ -17,25 +19,31 @@ lk_time_t current_time(void) { return current_time_hires(); } -static platform_timer_callback timer_cb = 0;; -static void *timer_arg = 0;; - status_t platform_set_oneshot_timer (platform_timer_callback callback, void *arg, lk_time_t interval) { timer_cb = callback; timer_arg = arg; + //printf("platform_set_oneshot_timer(..., ..., %d)\n", interval); +#if VC4_TIMER_CHANNEL == 0 *REG32(ST_C0) = *REG32(ST_CLO) + (interval * 1000); register_int_handler(0, timer0_irq, NULL); unmask_interrupt(0); +#elif VC4_TIMER_CHANNEL == 1 + *REG32(ST_C1) = *REG32(ST_CLO) + (interval * 1000); + register_int_handler(1, timer0_irq, NULL); + unmask_interrupt(1); +#else +#error unsupported timer channel +#endif return NO_ERROR; } +void platform_stop_timer(void) { +} + static enum handler_return timer0_irq(void *arg) { uint32_t cs = *REG32(ST_CS); *REG32(ST_CS) = cs; // ack the event so the irq signal clears assert(timer_cb); return timer_cb(timer_arg, current_time()); } - -void platform_stop_timer(void) { -} diff --git a/lib/elf/elf.c b/lib/elf/elf.c index 6de7220edc..d4c1825224 100644 --- a/lib/elf/elf.c +++ b/lib/elf/elf.c @@ -154,7 +154,7 @@ static int verify_eheader(const void *header) { #elif ARCH_MICROBLAZE if (eheader->e_machine != EM_MICROBLAZE) return ERR_NOT_FOUND; -#elif ARCH_VC4 +#elif ARCH_VPU printf("%d %d\n", eheader->e_machine, EM_VC4); if (eheader->e_machine != EM_VC4) return ERR_NOT_FOUND; diff --git a/lib/libc/string/arch/vc4/rules.mk b/lib/libc/string/arch/vpu/rules.mk similarity index 100% rename from lib/libc/string/arch/vc4/rules.mk rename to lib/libc/string/arch/vpu/rules.mk diff --git a/platform/bcm28xx/gpio.c b/platform/bcm28xx/gpio.c index b263d87012..055826edee 100644 --- a/platform/bcm28xx/gpio.c +++ b/platform/bcm28xx/gpio.c @@ -175,7 +175,7 @@ static int cmd_gpio_dump_state(int argc, const cmd_args *argv) { static int cmd_gpio_test(int argc, const cmd_args *argv) { uint8_t pins[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }; - for (int i=0; iwAp$i7{e=z(-O;`Ru z{6tCd|MWTyDA}~inN>*|ScYk@aO4b7mePQx>qG?;w$@C6?mUr7k2CO(hWg ztVAA-#}k0dK_f=ug3WA&#X!!5ua7~kf=>QlhJ^Ik;%Fq?DEL^U=nTl%WQgdfn8=t2 z$p2;D=^buk?wfrC(AKeiE^js6ueXi{dLoXbSqo*knD>q}-)k)!Fan04M*ZsLP>0x&J_T>38E=tL^@6DFo^bd^&^PbJT^ z#N&YK>uYpPq-Nb=fUEJ>ydtamH^Wo8Ly|l2AVbEC1;FbdJ!6~bzu(1K)I3)kgsWf5 zC(q}q#Mreb|6ac|+c+slnhpkT?9<;pi)kZ|XLT}KR+%2%LGPPR<8KgYT5q-N^Vju4 zatwD{$un|;a-H-K81xx-Vzn7vF@2LZ%pF2{uY3_4L}+^c_F?!r5-o+TW^@e6SjlJu>@2?~#eQx%no{ zp2#mSC}@Ms<`O0X-_8YDy`U1S^UZrAv43dS6fMRECmZ$@k=d~qkoW~{bdpn@O}*VD zQYE~J>I^=;aj*~ppMx;K6!0YIlY)3+LE{siv+~t_?TvzJDYF! z_4P@3EOGwZI*6HFx4{l67IBvr+4<-r60PXzebZbf%LEJ93|Xs#neCLBeb}E|F&;@5 zs=;X?!Z|<54O)16^hU$Jw{Q#ENT)kJV;RYrY!?2b_n;Kp?%J5}fb}xXk8`@DmNme) z=?2g1K*Ha)ewm8b-Ag_NX6tBZ2%!4Xm(zYS(>K#l@Qo{j9`tPgu43DXYIAxOBuwS> z_pCt-RlV17DG1_1Kol?H{1tq{tl|` zP~GCqhj)B7p{99vQ{O7c$0U1mTU(ndd3e8(_PHQDn)CX^RFO+&M)COy6|3+Q`|B^= zSsqEhj47M~O(`61MuNtj-V;E|{LJf?k=@1K>tiJae zarF7?+o@#Vzb#8DkVK*0v;>+>B6tJmC9pA1vE;04gQIJeD6z2m^wT~r=`5?+L|Lf) zUIT@VfuEq+h6w@v%`nMfZ@Xr%_!52yfSrO!>9bhjWOsO?-|$_?_l3;+*Wsl{j+cdi z=H)57A$Mh+_-eG(S72Kh>V5Ru*{9I2&ZT=c zU#sN8VX%Aeu3l7l(ctnhu+ksrC7M9DLzjzO7q1MM5yk2&EOcBd1VDP~)0#-=*E45) zbyq;SfhTAH=Ynkat$1J<8`s?7@eNV!IH;^_!@5o2WnQH&`1HnS&N~ zC2r!P4tq!8>GK;~Z#PQDpfn{4sSA3ed1)Q$(cRaD)i{iD1=NK(rro^UHMAGueB=CuNr3oXHf)vEIGGdmFg*%_^gty zU=4wd-DTZq~$r4NhwY zD~;ma-QJm0G3St)&3YUCZx`oQ=BCh$)@u?){V!I)mR_3*Q;(sH0MiVGm;skhQ2}?B zjizs^4-u3SzRrK?!f)ku)ODOoQg-ivaR-jd+_*^@lW zuH=^a`dN^>Y?&nQ$~{-i?Yf!?W&sZV&iJf6$maGlvXG3#Do7WH$;7qmj) zCUtXM6Q%Zl6~%_UA`h42{T`oye_?YrEfSgF1-hb! zN4JZP?6i}*o?n0vVdboX%<*=)CF7@%liH>wX8}q~{UqQ|m*HvO`I8RY^N&AHxV-aq zE8D;He)IU5%E~!-_Ma=5G7n> z6LWVO(Ro7qU$vmbF8|165nx=ksOrMf)+pZoH>@GY85?|;f}VPm<%qIkljBx|z{_sU zbzi%&$i!H&x~&*TAODt>rtIVEBEXJ|EYt5oCQ9R`BSEu$mK8r?&t zk*=G5*)eTh7lsDsv`sjZ9gaTd279r9l)%8BL8Y05KaTB)HlwC<^)CT3W=%lx!iFz{m z_t|s5zMQ`>0(FqJS=%Nsm3H3lA|+BggBDuTh2y?CpK`SPEv@5j`&Kw7z94x?-?;QV z&e~HgW4vwne4m$qE{v^}lL>xKb%7P?7{QYYYOe$i>k#auXR}BAdhvC$@V2)}Ewo%ZA;_r3`JfHPwZ#p)bz+u&fYQw+bv!^FVpBSjTq3$L2R`+ z1;zQH$*JcO_|~|sfYo)Yhr7Rh$e+LW0mudd?D`y@aZiYB?6&PLYd6+bsb38B$wpoK zmj^^H-6)(fuwiOr;!FtZ3Mkt4f^RQ* zxL~}po#}M7-0?zxJt92x%A5mn$L70_i;TH>Wycd6&9*DhsBX=ZEbSJO0AdM(KchRi z(G)wPeNB{uv4O@P-)fk6)&&(s(16k>ixv}rlD>=TBha2z&EKj3CH%dLb zez`0j!Qb=DDehSgZwL!?QOlu{o#pN#9mtM}L0H1CI(9kd*Lb_fjDq3(6XLuNAKN+S z0FD7tvYb!D>6eFk6c+{Gs&NU-PJ`yjuC~%0Ai8Tn^V)N{S#l zOA-duuZ;M<|L}K`+x*vzx zxqyO=0KEN005|z+=mqBtsXIZOx~ml1RtX5@ycU7E>4w8gP}av*wux+`!WOr64U+)4 zmtm*StH%Kl8xSD%p*+Q$KCRU@Y2~fq&lL|y_*Ggh`e3BVP#A7!MwLYAo89Z$&c)|c z=lQS0SKcx*)O$G8?{?L~i082{w1?E|23VG;#giKq0mkZRG1E@KcR!EAycL_A7^e0D;wT^bS+iBHCL^%2?d>sb*wNK$d&qz!NUxzYyZ;+@o3LbozZp?^EUM1w3!k>wl zi}}z?H_qT#Peth*bpcLQr`5aTU4GTacMglBCY!B`M_w4+ZkwcxGb!h&7E}f$HXeg? z9E7c)^t%oW*FBZBCKy6#S81~b_tn|6w zwTigw49V!DJnpZHaGhY9U2I2WR7R+eFWtS%;xiboawu()?-JaUl7PEvJ zp+r{v5t7RgjZg#5iWyGGYKjsv-dPuGHD7*Ub`8V_@ZkH2b;y*hWrhmA{cEGLQLhLs zB<<(Ra$P5SM_su36qSiZiTd{rD$z>pc2MJZ+e}3?Ynlq={=Ib@j3vOZYp$Tst+tVP zjy?<`JLO;qb=$YZ=;gWgwI(_zvO2OQa(1+8G?G%xy>nZH9Mo@>8`X}kesT=(>W;t> zDE$e4GfoBXHy{(>jCV3f{N&w-y)JO2z`M^%(xfn5@?T7>3v#jkpcBgFGmP0Z!jIJf zzMH$nK^GsF?E=AYyzNnfR%l=kOs5e$zKPE#U~At^tI@S~4NDO9%*;BaCBSnx$kAG@ zb*y6EF6f7JX7A>>jKRgyfLBF%ICRlMtk;9LNP+Y&%wE3vSUkX`;MiEH2FvYck2vm8 zaN{teztmCbWT=Ia-Jsdw)801*K<5JXl;@=3L)V!J!iYWy@JVEq*`0Wh@xFP=MMJY~ z!OO`~FCzInRxXglp%)Tmn^!Vf>Rzk-y{k1=U_U(%nbhtjzoM#?de3F z#*1yCPBj%qGv4*Xhe{jaZ7 zrr)f#Om|Q@6SE{oPQc8-3vnmpcn--Jp}V&6jul(x~ky_<*pYjdS)` z8JsZqc6YOKmH7T-gL+=6qI^E6;K)yj#=g@yeA^IY^Y7*TPCfqL^Yd)*%fCHNfZOIi zm2)0Eugu@DQFzGaJ=`?zrRJst+`l)hcNJ;CmS@1z{c2VpfVxJ=+2Zj%;Q*)k`uyp( ze|z{`WF>*FtmK?6B;IqZX>uH=4SV$w2cGgi^Z_S=To!BB5<=ZZPl^;l6xf#d`;i>d zzv}q%09f9qnx%#bwJeIXEaq&bJ-LjtI+{}Q|9oYi7OgIi?m;o(J;qwr4Ok#=7YJsd$oWL z@9Nw;Abik5AouE2C-*4U{PeLw6SK7t?%%gp^P<)3<}~Rv|K(243*6;dU)7+X3$2}- zSkH@hVH?xUYNF(Su=%&^>+lQW^Bbr1k1k_ti^8i3k?2+HE2%jt5>&`@UagzXZ!hTX zvYqmUM@Q?N+KRR`Ra@GBsiPc&;l`w1WV6jd!Z{u*<@YsoG5{)_%6+Y}5>}mI8i~uh zxHUmdq_clP60hyw);ec6F}!^ml{~4xOOxQb?Bpk9POLOIf886)6nwg;17Q1!)0;PK zakNFImkdk$XB;TmQH+R|Fvf}5?QZUtEI<6SWrk!vq>Rt^-*XyInc^?FjPAzdpTGGg zAABL+g|`;!Hyq8xysso7lx&*+_HX;b+9O)1R(8NAbwR6r17;z%R`Hav>N|G=t6@L@ zq;Zp*^RlSOy)+2!O9*^0zuda#FgD?NzxE#T?AlhQv~Q93w`$IsrZmr7Iq7>fhm|$3 zoQ2&>X4jJ9fjGb4Z+6tamWNlT7szWv`JeX-3!`;&qwgE6zyABXJt03`9Iuw4MT+zm zM1~^Gr|CTtXw@?GvB&KP%~;As?(1e1HzfLBUsc=L#g0E^!n4;^IM9LW`kCQHWAm^! zjK>JNN!DVq=Vya>E&+6@mkJbB{6EZ`FLQ=5W%b6A3n4zSo+s*Sdsnvwk%i)8;)5GrZ zA;~Nd$xgP(M~h0A4dQuBq0@9av9d|8ose(J4Eb^jxj_8xTF}roX`H>lxmtqee{d@! z-y}HB<3C}GI_O#8d3*a$y#!bg<2UzpPBE$Y$@jFTNQdZ&(`iDoRA2ssL9=j!&<99$ zlEu)Ztzr;;^4HDrmLo`nopR~UlaGLAg7Fm_zpcrc2TM)rdyc!ALJ;58Ap)A>JUv>1 z_;@NPhsnv$$xQ3Q?lI+UyFVu0fykY;K&@OV=S%SX`i1p`&6u(5z}s%AGJW-FgrQoa z&R?B_=&XE|A^kwI2^qq<)8Vp2Hi>i*`W;N_9}IyA+vTLi93u}dQNfsAG;tnR^tyAS zv3{)Y9DGh3B%3&uLuH&V9|+rqvtsU1nO`EmUTIF*UL44le@Yxj9lOX)azhQdPt8V? zhi{01Q3}bu^wYKWTW(O|I?@|x_&klgCA>u0$i3cprbk9tjhw~#lE17l2|y)rUjEFv zpv08&M@Xcv2r4rJ`%}vwPd=Dzx zz}b$;u~^-QJ8#(8Rh4`b+H$IZJaWj*Rc%zcDq0x=IKFs0Bz=Ae7K?oQ!S|Gc2>xc5 zDwj}^F~G=;1}elq9oap9s0KTyzr6^~;96^-U=@|xpnrS>%7!QHUS;kWwI#+bdELGL z;BV@h8$IWtChIB|Z&iNse`7JBFW~)0T7Mn>ZbZPW}`H_mVgTn&{IM~cB!s5Ms3eUF=(y)cL2{(Iejc^}s5 zFEUTAwg^{e6KAgr+n`G6_^eG?pfuIODfjmL#Cs!0_=usU7KH+Tp9I`w^qyzbhr;J! zr2hQW|9($(aVL1WhM-o71uwAQ0YJ%Jm*-U!QE>HG2fm+?AfA|`^|Bav4`?`-Zj4!# zv2_5lXGR+SX*a%;>=NU8hJZp2f1j4-Lqc*dDF!QD|55h;etj{|Bgw{KU!VKg&ljX4 zB`7j#!UuY-epqS0kPMdayDF3n{`T)aGn!s+?@t^<|DCVTK~SgcU>SbQ{kUExcN#w<^p-Yu03PrROVt zTU3U21H%WzGwB_VhKhjb0ubt0Ow0@vlm}zBP)8NguQU0HSYXFl34f&jY;H{c=D)#? zn)8ET*NN3#TDYx>uJa5)O&w?~C=|d8w&pVXUMI1x8l9F~4DBknH$PIzGu>mYm*Y(@D%Q&{0Zxs`Dvkn>Pt z^&(amW7V<4H;uSXw+dfjY?D&4o_R3WC#O{UX zlG5uexJM^IF0RlT!gH7t8gPQMwhI)wT-A(#su-M#QUzr_;UF2M~G4jzpjy_j7 z2DOm7r>C9=!3)%YtsfrOA9X^gC2%Eofqw25dsDG%EI}aG$!No`%+c9N_lnAssx)1J z!{j-V`ngb{oN!TAp?o`(N6_o^hAifxG^$Z)+-Ev>^EhYYN3z1BD zQ`+l_xz=WW6%J?_;oe#tFBL}Sk9GPQdQnjz3E%uo3(@8;1ax{yLd}6#$@UZo&Au(W zO1;akLRdY{X7#P^-$DQBDrGT)&js#8SicUu=lbTP0poG58F&o3l#!k~Nf)%^Xhy9$ zw7_XPQ5r)%I#o($$V`&#UC@sSd2n2u0W(p{0m0ZD_5d%-P$Zkpz!DWN!AThI_Q4)5 z=39-uI?>q|?BsltX`T^`6WV<399$T}3YCI4!g-W&$Jr!5GX3?&Pk4<3)9yAcG*^kg z;{;HT>OY2O90RzN7oP^$35yk%I#;Mp7sUV{fU3;*8p9qa1NVVg3&SEN$Ek>-La#wj?h<%FWkeY5++U$LTsgtoZ@!oTD-o7%l0n`PeO?5}HPAz3z=N zy10d;u4Ay1h$G8Dim!^7%^ z_X!oc(^-mYKofQo5RcN-v*J;N9XZR)qIm>cbjTEBB=D`V`nv#+LXj~nIa{dR$O3`2e`KAudEa))QexSH>I>nP? zZG!c0Un&I_G@}w^+JT`CZ1fTE=J&qFmB83Tnghewrf7vA-k5e*WGM zkl1|o4I#(hOXM{J+X`?2_6|CS^&dTA9SwOB570lZBl|Y0+o|mn0$p%G#c)?=HN3&} z(#Y{ezZR&`4tH8TtU;=N6@gYbpkz3A*8}bcd<|sO(+6_LAqJ3krq{JnTEQ$$l3-)^EB|@@}4n zbG~y?X4LWvV#yZNMy56H2IL5hQ$`NZ$=97u4tg|5Tt8!>3%Xgi>*eltAa(;=#09T* zA*GZy{siAoA>V~K!!-F%jVEKfQIkv8oruDzrKeWC@_6LgJdE3_6Epf_Y#X!96+zq9 z8eI5xjt0&8CKjS~1jT*bX?Z$NWvJ0?E^HHv6LCfCI+gLZJ7)K0G5gI!`ud;s5tXu{ zY6{#P0wk@Y&#+ln$4-CQ@t0$?)hwm24Vc>XI-B9GDvD~i#A0@=Ap{+eu<=M}--#3R z?p@@Kf?A{F$j3sui*3jJ4B9I=1TfI{gDIqPmqAlsc`!RzKYHf{Xu9qJmqHWoN8np4 zYaC@RG7n83*quPJ!xZuAtYLjE6((B?N1=x5?vS22@m{$@$@hi%iYyQD7Crr*bA}z? zLu_)7hk3?xm_}l#z|v>q+HL=JuDzMkPr$vPs__Wb^pg9o23xHmUT7TE=d6cfd`}Ur z(nK|U3Nk^j)ue~~1RRG}MLvNtp0=7mPwk@i;*-8zprS^gMVTjdWy*x<^5&2D$=ttU z(9n!TqX~IStT%s)6v6f*LTKOevepF-@xE?A*>~^FudSIbf!hkIS`|DKrl>-Xo{B%m z#9BW+4asS0;k(b8MjV~Qm~?-o!{-vxDlP>T{->oX_W5HB`8))nb`MhBq25(bmQ7V2 zBvMcjTJ?TcERek<-bkQcgyLUJew<3)ID+ySriH+b-qPA82IJSb+dKPw#MTY8!RIdE zLeBG~)thokgEP_-ZO?hMh3L3B7s-bqM=pB_H$&Iu>X$OH`6a@fLyj0XzExDOFcTx? z!()MG-~!N3eov*+x$x^22ja(05yg<~lMJwMsFZ;$!O^$qVW6j-T9+|$xQC(qH%bt? zNAr4&t#GMOijK7C-hHEq3_lFzJZi0HRp&jn=*&~y4>7Jv0J8>R*Ui7*cPCtJ-V|7GANF@!Bd-+yh!}3Wcv31BoCRQG8#6`93r!QsDaQ}Uwm+tZ zvOK-el#*Q`%z#qo!527@Fiek-%J`5Peo_AsQ{>YFNM|hgs9Ox&&j%MqQ|wc@1g{#B zAV7*CvFFf>OAH_MCr@L+IOK4B`j2~3#nYE_(yB;Ll}d*YdUiM7X1rkWc@N&5kDp7> ztIkvy2G$5dQ}5lg;=XU#2oqv^X`7*VSr(_RxLBdL))h>_t&~b6U$bmA(+O2th`o9Y zcq&>@$xY|$!!tjv{{kl|eE{W7r|I%mpfy)o31Okf7u%&qyh{T5OlsSoHB+p%iOZb1TGf*H}`b@1F!gP@YNP2NZV#LG((DxZ?f4Y ziSK#0MXj|}GVoj#W|$Id>y4SB5NuDo$b`bzQ4A1yvvrj7)&WE*ZB7ZS z^8R3m*;2aSwao5B+B9NPzNML@Pi{re9q1s++?(PSPaXAG$B&=7&R+{b$1wl=yhg93 zq~J&>*Ch8-wd5pPfhCB)2~5+!C3f=pTLEF8WN1kTL7z9{e8kI2*k5hk>0O%VRb2yd z7ITzGTAcpGh1rD`tWmOucdmJq@4nYG-4S z1w4&fPNJ53WbU}Qmvws*GsRAFOjOeGE^dG4%xa|>sv}10(5QLe(3~EIWqGi` zv$;`$h}0S%kDZhd*lGoJuqN?h@;C2vDK2AO%nYWkK)z9VmJ`2Dw{-3C;?nF%FSfAG z1}{i{9ML9=e>ix~?lYXM)JLKOka!a3d^6;x~=>LdE)Sl6vSRV=@pb9kC>(hYLl+y=!ZI(q&t##o{H^KlH>}wb0r4kNpa@D)_t$-f{8EtJfA=)T6DSwOdKJgS1gS6 z?#NuPPWuIK0W&hY_h)C5m>xGiofgD~Sb} zBkL-^oJp{F^)JWA2?LW%OI#$pg#nLKq1lYeCeDq5=+DcriKsTGrbI$?6W>5)-o$O5 zI9jF&X@Sk}6w>~5#kkt#g(U~EO8nE2kN^>~MpAmHYw192E;3DPuN}u6_A@c^XKK7e z=CahqvlLQ@^U7Hq8z>A*hsH1wx7zX-L3#>Hr&`JQ%Lj!)zR{aYeKY+fuQKCtgz>)Q z93~E;^tVLi*t&5F)T`edkmow^p9P}w4w>Q9fHNHew+#D&2eCS>)kujjJawFB>=KAEVe52#I*^n=+1GViGUoMi%q50I^e-7!JRO2 z6j{D@^}?CrI{Q$&SMje%Aisi&HEPyYcUy+mNFKJ>KL#gDNm2hPhJsul4qnFH2;f@g6{bwu+MePlZ}hK+OKU*~GezQjm|$G)+M41s^gRQAjo4#dBthvaxiDYUVv_W87KL=oK3JZj-A*+W-v}TQaX-QZK}hH>j`PM_ zNa{b$2;)zrkXaMN1P|oi*SG+vca{?(2|N6@aG@oC`8sqtS6;9mhpoHyK(p zqXrK|`oTPqDJL05hl-!{>Pdc5#O}U)brlH$oG7_DYuwX&`RX|+#!b6KFqV(NmH3V? z)lbBpm2=pb;Tsp8@5a)IXK`dCEH_I2dxX%S1q)9lKT||!vn2v&bbOzZ;lN_7fwXjgO&kxZ+KO9X%?0>ITP-IblAIzs~)k3ok(Za*y-k%#x!d-uoCa=U1k+R;S z(4i!2)Ao}kcc4GSWo{ed-@lAaxb&J+$o&(OX1skcf%nHau;VSSC_V#uh;Og<8^aI! zgI76Pt{!aiA6AvWv1roL?yl+Q6nZ>wq`J`} zynneZ;CfD#0`gUgpEO69gRfdDfh!jZoyrYz2MruFC~K#u)vM}WXA+$3aKmSL7<0`P zJsQ@0JVVX<1etR%vI?MX>j`CEtNK`%?!F z?tri?{(X8wu6W0z_ul?aza>VTf53qfQ?P|D!QrF@IfkIo7tg&@uaAzccpWYiip07B z5q}gph~0PXA_&IRpVnnUUBV2Z2YvDu49Z6n)BX9|d>_Sinc+%J+qPv^G*$*>$Q}BS z#M_6c_mj8Zyd0!pP=!G|`;ZhJa>JyBEb?eSV+-q)HC$iE3>!|Y90801DS^d! zDGGJ&yZDTbU@`A6ZR(igiSbE%v)!#c(LCPzodm4q5G==3{C3PJiWlvGjEtFTa4ez_ zU$U~bu#1g-n>SxjSCh6+VTliq8--vqD%OUxV-~b?If>L`?N-9tME_jWFW#b~<&VvF zr9ug4IUR40kMWMUXqu!W(>q2ESVlk8!;@mjvrl|eSzNyU29?_Ua8W&0%%I~kosoLl zA+7+EfzN%8np;m{ZqMK_2hhfQT3?au(mu>&Fe_dhq(i(2yzT7gl5`dvAgelK^>9(( zDK+4qqy?iVXwP=5k9&lenuYy%s0Fu&0wRWo8LNjw2!FYTb&(3emf0FOI61ddjn!?T zVuQU3QW#tA^Loo6*$zQ zv36UC4%n_#XLbh?5rB@#=#g|5!Li&6XuZfYD%Aoc>2%e|{NQH@AM>n~^OWavL&6?#BG&X0P5xHWBYL>`ou$ z-8CB16Vyl5OW%$0eNBa-M4D0zid21v7xi;+}Nuk z5_xjR!F1f1-ow0{{NZjVC2t5%JRicX=b{Jc<5KgNIW?xjHaHBWy65-|h*YE*{8B$n zU96EJlUtf)%;nF5o6J%cLEIm_ms;qEbn0YFB{4z7kgu~DCS;DEa)c5D+qhosbSUYu(?x!zGzGY7I&Pk66&WQbIk4tL6T^)W~cV` z#JaVuhI?=S!L?&4EhtPm!_w^m6OZ|_O*cSI%u8M!Q1nN4(iojJ;Y0zoj=wF5Z5S3e z+spe0#Wxniw=7L{9lxXi*ympL`@MqarC503?n7$1p5o?_0?7)guHAsPG>9a6OAmdu=&kQlwXe49y+U&P7lUEiWn(q@u9=^iE`%` z{!uB+oAhgenDT71V}5h!BaAU#)#8dzX&a@=eWv|_ zLHV=h5KQGNwZ|xu@XnB zm5>dZr;z#2_p1RWbFCyHnfS0wMCNuj#9n~L;4{KoEXz(eQw~=UBiaI!HuZ~BjhRH5 zo2_2u;Grz0UOj?i+@#4m-W}{0%`#zwvNPYj&VL+6ycj@2CrRS0F?>@7X*k~Ci@U=o zJ0?k`%>HtDU!E!3>6{y8{P{Psw%aX|dEM5&_6NJLCYwKk%pJahDrPR_hO%QK0{^&p zDPi%=nNHH9qTp+^c1cNV_2HKf)4@#An<+?_$EK3-wS{j!$dQE?Lw({`mcvcUdh?>6 zn9afv`)*(K8BijgheY{1Baj22?d)INRxn`bD(GDKj<rVTbFb9?5Z`u|*R9mUd zI}8^#$e();P$0MjG8zkU{QytgX5tQb@6DCz7=xY#;+P#s&qdsk-?`nms9)z?+kxmN zS!)~cDgA*dhQr8HvF$5`&(G60ni9q3uy=IB>xBw?#p<>w6zF-#h5<;-)!a8YO;-~h zq^AM<>>Hd_HD+~QB(A4(s(OJ#sCP#x5)Rg0ZPB`YSJJwL=@<-P&rp&V<~4ZMLhr&J zP*s}>HgTQ(6PosQoa*ve9=>!T=(GC<_k6ykQRFDf&s)u=0Ut>H(&2G{b_wm)I?k+o zn|XX(jiEx>^f(Q4AUjP?Td2>E?=ah5bD>dld~_@gRLI=wE3Z#C1TmTyeggNUk#~jw z5Ki^?f3RS}{_CNC*>^bfJ+keCE`_l|pJBzr7VR9fh8R1hJ{j4G%l5&b_`O?$dwIn4{B1cleYPM0IS|Ncm{ z?7)+Co$09Mg$QiHwv#+(enRXUleZ2IW>?S-@&v(;m;xD>3)QMyPO|IC750swAuN%n zw133rHxyQMaY`4$gfN5)4uRQF5|?w6Djt+1Q5<9!)WsPKy6+IDupENpw`wJwze{9T zuW~H6Is>aC*^n2h!w)g!$q;gB13ykjA)*rv;Z%1W+Hdnx_-Ak_lc7x5@zw35!#wMl!{bH~pL z5pVLkRAJQx4=@x#RC1T#f_x808!V;znZLXN$Dl{%tpnlT;FDe~3FN@OW(V^h;>dvo zl~;#ZH#cHf_8#m)B3Tb>5@T&a-WAcdJp|6Du|BK+12}jrkf4 z@D)0Jych|OU8pyr#9W@!Vqc2FHfKHQoUGx3xzrk-t-Y@^4FEnIyUB3Uj PI)qb}*O051u?YJ=`E{Xx literal 0 HcmV?d00001 diff --git a/platform/bcm28xx/hvs-dance/pi-logo.tga b/platform/bcm28xx/hvs-dance/pi-logo.tga deleted file mode 100644 index 9ec1ba9df6307a812986d358cc8760ff3ac8368b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68891 zcma*QNvw0%xu&wW+?b8mgBqOQLMamgPp2Wm|4#%949aV!r2nxxU54bAI`5 zV6U^e*IMuQe$8t4CQsM>2VFVd-urj^{l8xGaX-#MoRc``=SH$V5y>*nS)7M)_WvA7 z_bLfly*Nj4PUBpt0uYPMorCw|qC1D=CnVJ9$2p2~9OsOzId}QQIgGP+Q6$}7oCk5v zKNiWlphBT1)UU@?7Mf+DRoorNX%L`?agO2~$2pZi!1x5%@TZYE)5g6|=Y)#VPnta+fmmI7jD4lA?#)IXjXuWDesT#%asl5?6xe)(DlxfbeOM zAn=3D>WWC#CnG@!Vl(G5a;UkC^WcY(bUz^B7(;Y@RwQIj;_PqEQTzpXd0`~!*KvI4 z%dgkPmDr8q?~G7bpNa(O<2aEHi&2~l34sB*eF;aLs`umX;>k$TLw$MZ3vo*Y4&(3g ziBez{7o#^K>Apd7B2L5%;~d91JuebPD%`olxq3Ph=|FYv*utNWE6F&BzsqMLQ6bDQ z=1edY;La${{>zbcFOi_qD9*(5{t!vRk03fe70F?o!#I0!atz{}ekT&K8^=XYGGB-*9n+u3 zpL8$Pd+(9~*Mm6GeD$+P1h9yUf$BaVS30I|$Dh`=zapd9W~qEWt>PT0o?0J;rtd@| zWHJwa!99xhNf6zSbBg@+-aq=M|9Jg3|JgrWe_5X*5v@1l zLdO(U)_aurj|YFZ#+NB^cn?MHA^{Y-tNSCVpr7W`2}Jyxd;ahBzc}}QUH|RB{;$># zs!Svj^+sIinBuMV2})3s8q^eq2=EC#L|_&dJ;}a<+7Rf)ITiR>MI<2q^3sF#KOOx` zi9YoY{%U=B6kDGvCI0PW|Ihk=y7~WH_y4#5ZcVNgh$15QdR*u*?kP(A-M{^>RfC$G zAPMsH^e1;_fI;Ql_O{+oaQKda>R+&LMEl!?FP(11PU z)8MP+UjLl98uF=sHYvyS#z@vu7I|Px${t+cB?jUmRwv*`UI{>Hut$90WxFUKrTz>F zQlE<%&1}5~0IFYz>U$;PFCnkv{<*pjAXb*peLg`3BYaUPkpS0!I+8T5$KDf#IyI0c z>^;!H5q`&&?-P!g(|lk+9lI&8QKT;&u0s@E46SGw=OKO3IL>Zzb0llo28xKHKkziA zD14EE62T=XHO6-kI6sX+Y4utsDaCD0+6subBZpXm*7(Utr2H`cE+M%-NhwN~nt0W{ zAjl{xSqf&!&p?NnIPMiAi2sSwvz7L*h$#)oHsBK+2E=1`ngl}~#5s*~NjJFu>*AL} z4Kes1MKKu!CzQ+>`4~m_APou4n>xH|b8&_7)Q@+RP&-vyL{>)1B0&3(MWSOei$CiO zaJOxO*W&?*DMQjESN$tY%&C}2d{4q04bTLQ$gO<_eX!=RtGGb;D9+yLNV=SpjpDVKZW=FH>C=S2g0> z0m1DH?MpyeZ$5oOcH#=X&kc~Zx_}z*2z7vgP&*;+yZt~71lX+Mq2X9;2=vwINY;C_ z5`?)9wFw4yIv_Zh%6-Wf6LFFulW)hB+bHGv1UGXohH3_!@zueh`#cH9_|ZseKq+#M z3^wOcro$T(83|xo&)Iq35nt|Wc2*l8Mb&Wj;RXV+AsdxGqNf>Jz;%;r0NtkqC9%vg zjn4DG(henE{KP2Rt=Q_mG&nLaRn{2KleCaNkFzHWT^Uz8rjNy+EfYu+{HQKPd1!eV zluw`~fW#5}Kh9lw%7%otn*j*&-pOK_qBC`~#Vtd?K+{+3#n>`E9m!gq%63hz9nr9{ z45V2u(IGA;V1)!&Qb)W!Edp2lJ>2L8su3M3QD6~gPqz77THROyG9f4F~g+;iV;jw^TGg?-wG4q%Y;a_r+CDF+F6v~Z|c#s^C> zRTdf6H#wf*3f8a(!M36+la6Pjt@QTn5aBY-XX8r8;JWy;K8dZdDK)V^5wv3=&*4Bc4v4}&3Ev{I zM6~!wX>mLSTUb+{nvH%Z=@yE9SO80?mBVVH5K3b$u0@tc1*%<+;@KaS%61}V6OnyN z0*Z^=*dXDd4odE-j~ax5R-N-PA>;0t+QtD<*!xI98uA~8pXg|TR@zKb&q;sk+n1`^ zs6hGw)1lh`e(H$6nAVK~<3B>aKoOxKtAm*vIN|9r@~E!Nbk3x!>S#eFFoS>8PVz~_8F16 zl>~s8GD_$;kZ^S~rIhM*#F()5=$1g&pt~b`5+Lgi>s~>pD@ktP$W!lrf~W_(;L8jM zKg9Bi)j|ASd38soEX#X={o=UB=m?9qE{w z4x(L_-dgoD{67HOx?*)1hPpeHhI(M2-HjbebpSwX4`s9>0#md=n`u_h)qyCbc+(iw@6{4!ovVwaoeBLh1lGTAG(U^?^)=x`vXm?B!Hp0odnwVXs z;6Sd!IjXz+6RY^t%}fo=Dz%*0MgdKsE|6zS|EDU@p}XnlXg)P2#!-!%C5)JD%-+iZ zZ00sj^V+HaJBcWM>a}9}5~FB=oT5ddvi&+Rg3*MIRL9UB#v~d1wGu8)t;X_2I%Hw3 zva@roCZLco#BVy5l^>n?i+*T5{TM(n=n*l3i7a|MRG6tQeYEa_FZLclc$x^(}THKPt|p*eumc41sk_|ju` z1Ch_xrEQt5ky|y=#2PEI-?&&ZBAF^AT4&ytU15qkY()(jyu9TjaE9i?O< zJ!7Mz<|JJ4C?}A0`U0ZRv5ZL8Ud=%SpwU*#AP_(T z5$z>IQ?;Bj&00bO69VS`hERx*Xdp#MU48~spQ)@4^^u+wtK3OyKss{u7b3#e{$>)< z%B2$IGt!Q)Xdlv1J{^b4FVULO>M-OoTwv z-5o-4gST}67U+qv*x|-*{OQ{VSyIoYsVkIxOq!B1($aoAtC&MifQT(BJu3Tg1wC!X zHTL_3>__yd!9#DcMQ>s;&QW)`r^B@Z_nKnp2AarqLk>C0jZW29**{9mMIGsn)nud`z@(8k&oitcF0~ej;i_ zk*o&FAxNf05U519PD)xi@KDYYj!@fKD~!C#01z^dix$<<$F#^pb7=oqv>1Mq7S230 zE$*vCZk*tsC6s267Mp8jo6B3Tv(!eh$P=Q)6)@V%(Tfj^5kC|q$jOPprrS6V zA<9+AV;9#1qoRTVO*guzy^7OMiYgtt*|oYlQE6JEKpW@%K$NiHRQ0&hy~bUxhiDoO zjuN)Ek?oa+j8;c+r}HvmkAXESsnOyj@74i|GqB21WayJjhAZ8ZlPE=L)ys#Fwm0ZV zvGO7LPzFgNT1r1ZCm|A3YyVMz72$!5Z zZn45hOLYRLXx_-7GJ=5w#KSvbP@2bcqDv=$yN=R*g?!Cd>)J~9jv)>LNWxU}LN?MQ zS1%F5gu5^U8m4DbW-euN5m@(8@%2k04it(VCH@T&C*Q=m(!FDd7ylR&bj~Ud#gb&d z#sL=J4B*)F+oFW)agiRgHuDR?Yi?#r*h=>rN~)*s4J2Wz=S>2uoo=X3a9$GuOpDQv z5_nNI0oDX)W4dm3(M`K_1xHD|013(0)iI)rJB)-YAd})p z60ZaYY<86itnW&HD&PRUkkmNfYto;R_|Uze?lmO*J`_DamJ+7+I~3TuNEjnp#KnoIyHZh<9`UA`FK-8Ql18Ab@6V!HY=kf(dvhVp=N6o@AF6=@ET z1w&N#vJY;FdcdM)PEq=;VDHav3C39HqZPlRf%tYu3MmWbO7}D=K~I;bCJ4s}p6K;3 zC8)mHgNEDd@^|UHDiCq25loYbD%hhMxs@oc0YO+&r=1B^;kiEX)?_6>z+qao&}_MN zHd6_BVu7AGz~!k4LM7l>3RMpnCpsluY<8RxtQkzMaSeoN0n*HONAo%xrj*OmM_>zK zN%Isu)8n#yW;XFYG;R6~1yTjUeB7Vs{i?0*?UkNDLPg6MsNuCrsJ4vL&*+#S=~!4O zhEj#xbTa$WL>@UtuYAm0AmwmT;E{(4tKMx9FZ)0;O6Dv;^|$z_2B-k~wn{<^^SG z(*`8;(EAP%pg%JKu5?d+=95P;Y8!`I5R;M^eoMHp^EGwcjH5J@)RSJq93(Kb>egC{ zGG>KUF~Ll%xNla-(>+BdrCgp8ctcove+_h`RJqiJ2`AUNyS>F5HRgg;pX!Z00>rBZ z0P)}LqQ#Y0C3!Eq4I7J^#-PJg2<;e30$rFQD!k)zv_zZRBos&sv$KW{7XTrC7bD_q3d#yRqMh1_>hOmms)(4zEB zQkqh9?|x*bdpk-~KC$FG8x?=Hf;SH*v#?x7l(Y)pAi=0!7C zU@S;C1M;vXFw_=MZeCW#o+=hoUM1n^bc2L*b#)SQ+0s|GO62%Ay&i>?a51%Dc+(th ze!SdjLIb^0=0_*;L?A~E=TWM)7)Zthoq8g&7m`I}kpl&T6)8x&iWyxedbphl+z0{u8wB9Oa()qnIdHgSoQPc=ktiOQ8o z&7-vIfdK7_NnVl}-53a+637hV+>k+obdT2R1}vIg(Ga;UDpn%SYpqB;wbrd9uxF>F zkkAtpzkTaUB|fT4E^7#Uu_2&5y*^ZXQ{iZ;p3{=i%?MV4V8w#xMosUPFPgQk@E3JT z0M109SjTx7zPf_wpmf_x+!&%V!8ydC-K``X6Hg%+(5nBS*1F;nS)y3z&Zy`;Ozt?Z zaYZ(HW0t^8B8vd%ivwQOVIrysln1fW!Bi7plrEu1xHqb)E|B&R;@-UY3U<^t%R*h@!%hNluC*bHUne(8hxA$n0VEwM~xy-3=;UJMLxL}bv z7$>>n4mp&-CY6b>w5|djTS=ZI=VWll8HXY#13>2kkWY{t6@ek1lqy`=aHTD@^@@>F z=)ASa(Bs_km5W|Kll9MBh9;VmzNrK#aY#}R3$(<*#!El>2<$T2*lSU6RI%ezH?zU< z`Fk%ukdunq(G^?m%148Pj|I*(F#K}4XWukQL+0rb&JUX-9A{y6~&$JYc1 zd)(r@(ttfRhyrxWy%|_{kZ{c1JJGtS_$PsucJOKxsL!&TM=1tkYZnDpar&$O0xh0j z2)Nm1{v+U;2MAalsqQr!GIh;+XCQY<5>)+n1NwV`VgiG5rF#vi$N)FGi&RO1YW>@Q z{zjnKPj=NdzwR9c1qBlv+zqgj0zB9AxCU6`rDhcdCe(DV0rn`h0Uq1~Fe9Oki57_s z=sRLd%Qq+{(7gs!T0)H|=nL;Y5V>^_=jteMeT78vDl_O_11v2;n%qyS1kiq*bAjf7 zYe0g{fL!UG8V3DZvXo692#D@M5&#e5Tq!*C9FyX>=vSyO0K#9uxxi9hK61k_p9v6s z_j?u>Jz;-2t|Xuzf4xPKuMwPs6fKevvf_oAI@6oNWE(!oQK zbPtnoEGLoFFXroouhc^DsYT7hU^(*mXJry_dZ_?W5+;sexT-r8SKVv(KpufhVtDHy ze?6j3ZZNI8Rj$$&JDV~AHE#j?UZcXBO7*R&A3#>mk91E!l*$hOP(VtcxN!eW5wz1+ zr}TQBh9_O=p0uM>_RIYiNUtre_h~N7!syR_nh}KYJl=7Yd5U*RQ!D%DIal3@|NOuF zFZyvF#5s<0dVVBx?oKy%$nn!rF(Dp$ac*`H;Yz%`rB=)*jpQayeF*@FFUG(QD;25bcq7?MC&cMF2I1hm8Aajsp zX7Q zYM}}}X8uMGK{$%Dmz{b)$gIwbWDRBSz3NK$N^9z!7nS@&hFo|vSP!P?YnKV)OD>JUZaCp9$uUKIK`Z^jC=UnDP zAi`w63!;|WB)3&SUlO1=Re`{=&1if8Pq8~pb_+3q)A$N(Nhe7!MDI;Q=qdb*^A}mq zKOUMIOiu@}f2vJC&~Y{-^rJFGi93%fK}T1WPyvnPR6#9)`1d}Vp-$`d49L~FK~v3` zQOEw4KA$f4(P!M~QR|TBUs6q7hPS~>KVCz)GUzb|>1mf@ggbabF+x20mBprDGf-3b z78xj#X?kIj)^t-6>(3U}3z*?&d2El-n%ni0W?*~HR44ASmeSXY6;{MZ^gLqa zg)$$D?Nm@5x|{&smc3eOm6>K*vYzghXtkGhU(8+xj$0C0|1NFYCm zb9GZBb?Zw{*VMRSNzWt`vl+G4_j?L?6%={=AmyS=r^lEI%~_H^Jcj&O^A{8v=2T){ zU7)&26-YBaG9GJ(Vi^|$tuayJAiXn7PgEtUVgq?69cZT#bHjk^zD2>nkCC^56XJ10oJ-)Pt~^s48J;+WTRg{i`DJ z5SOgyAIZ9E;V4FL+?6>o`CW{|409Cl9W}c zjX|;Q!RbiEZ$%`204w?ZXt0 z!~8cY6Ui#hah!f>2;D!L*UsRPeejkJsn<}pgI7P!*>59>iBw20yzUe)Z1#756HhwB zsqayS8p}AVtwt5I`ZA|0(_DIvYq>W9KsM>c-?3!xA%zxkKXUi52f>swXFNjJN?*d37bf z-B$dhU$^!)s$a9u?FYnM_Dh*xO~1n8ohTqZiE;n1Mr*Sznb~t`gJMi;o5i`zeUo9v zz*f6^Er4Zn>2DqJD&Bn|^>4V$qDCEo`l;8keUyezxE#b;cPysKWiy&U<5iO4|BYRU zcj9gVmwm2E++mWm&5-SmE~y;b$!E9YX;(7X>ECm*auA5CyO44U{kO*@I1r2H&=fmb z|2gpU757fjGAYGb#wZXxd!uKg*vqmot%+8g-kyZe9?Ky`*k2fLQ;)g@Gt5bgy@UPf z8S3=67at~?*`9<8R)#5@U~?6`PV%YfQHCtWrgcZzSH+!ttfO_*d1%-XK3}F7u3W@9 zxFQm%QUmYU=}M|{n892p&^r^Cmw`mWAkM|Dk;HO1Btw+W8S*!ZB0+5AT?I9FOZ?ZX+J(Mtnm2e;2gf%P8j;QqaI7gmxjPLz5@zbR!-f>Ly& z1m(5;Ql3eb+DwF$Kod#!Eh;^C;?AD z(c$W5?w=r#K_IvZ(OXnE5@NESI@rE+t2NfPe4~Lm>3gS@!ehCmS*L+p`>z|~L#!Kv zPEkX11-a%^q2;F~@EB!i)v5Lw>DOiEGU<;3 zPREO+*`ltC53x!MOG6AI_lPFe)K1MFs$u&daeoielvbWpm`MdnkcSF&sjTM<#5CKr zt5jiYCn8Ng&Z$w|+1va$OQXJbCtlcA!p|gfY`srJAp}u6rT9IMQ0FJQPuSP{D1BF> z0L@#yHxedN0Q*lx9#yoprws_j$1w`j4cF!Q;u*DC1B}n+{_`XpqiZ9Ho%*me(fvP&r1|L{hmv zDEYEe@=TNLP z6*pTxX(gq+uTp?xO6Tm}k;r%$!s<1v602jBpeOyZ?$g!K1dJ14RSB$IcjRYDz7NqM zxqU?ztEr)Aaj&-6L;2t<(B#-qrBk455!F3{1smG7gzc|IixSYH%eIdwDauX2& zyS6(0*Am&h29Y0gJS$cZGYI0a%cHU(fnZV)eov%IcOg;=6)OQ*O0{G(_rz`eI9D0L zXL=&kmwlfpqz(-RESj4X^h8SI2={*@vP7cE(ySg4S;}JBt7XARWTBi8`&k+e)35Ai zw7KbX|3K~k=|X5^AgqMA`B95#jK)U46Dge8y3fR*jdg_w`tBkEn=Rt>qPAGDPIX7> zyPn!1M%RLH6GI4hY!!n1_ae-FtYQ~pU6;phsOGtDK-bku`#knQJ2j9xjB{&sqe;$_ zkSgQpN?=;PBla;_1(7C2NAgGAL%8qJhN}XUO+u5LF}6>ty-8QBwELv`i9)Cs7bc{^ zL~HA<-i{FdQ@YJ$h#-@ORuUOiBF(dVy{)7;BH-%={X{YM_%@M+!H6Rh;mSQ0QS;|? zRqX<}!o4E2SKOtSaX=m8R?3!WVo)URt_-kTsn#)J5F+clAP^kKIgGQX*2ZJb{^kxj^L!VCnTFp5c?_Z) zqhrYKK>%CXnnchCA`ErkgPylmN+S_j5O?02(fd$c2wt8I7hUNd(KdkX>9TMso5h4=g@wb2mV%JtvWPkk?{Q@96Dzt0HS_evUx=gvGonodiGJ0{wemo-2gLbW>;qG&*f9LGuX;am`%YlSF{oGgm? zw|&Hl+Wz{AI=^afuOI1iT1N2jf~^hY;#04)166*KjE4}yF|g_=Tm`AZF@B(LsSDgT zU>T=eFHpy=kj<;-6oHeRu7!%wd#%pV6zr?X`+nGmHbsv&QUD#3GQamg41e~^iX^sL=MN;-~@RE_k4qD6&ycH z!PY7r_H%3m+Fald09?Y`Z^oz+=JzN`7-`m~#aI{jWI_#P3ha!Go z6w|T!`8DL@*E(SZ_Qoi(R&~#m(9w%^%A=1oQ1B%Cc`IOH_JoAN0Rj9bz|$0-7vc_U zMVv}ot?iP1U&QY<_vm>HPN!h-G8ynT7-G;$GhyvpTcZkIJL!O&wBS>NQ`oDX0)Cs! zLRAB&Hrf#qkq#}>Br5^m1M7@Ns|0g{V@<58J!bVeza^T~eM=k7T@8+z5_}|U2pj=+ zsH%B^5C1zN!`nbw*Qu>o3!p@xWjt>|=VB{oVNb0}6&H6Uuvf9gM7MK47Xl{Iu;B*r5mY2h>Qm$1V;n?^G1lwmu*0sEOiGMA$?hhVmf*?B=1ikgfP^& zrT$b=gVS-L8yJ0%!J&~F9Jb*8szW;28;QjnOuTF=%;?=vjD{Jdp<>^Acl0+YWY!9q z*-Wy2GJPzW(oMW6&EO1Mh9b8DY21dX|AlXwXJv4jl6D5w3Rt0fLj}m!1zwm-D>XKQ zHx51!?wwIx$H3sUQG=tyGm&MpV5sj39Q7&1DxpS~>)@9(&7>7DuBN#=S>jywzTB7) z@~ZLx!aOW@>n6K*uhA}rELtIM$#Rxoj15)ZyrC}>?(_4Y{ zMa5HT=Wl?a2Rb+f3(DP+g>+O#!fTR+RLaOe^`TGXZGXwrx?wQM(!lW+^_#bdz_}GJ zCt=Sg7@!+9S$4RC^K&wor{_kBiWy=#HlaaPJt$1i{W3D+e|HCcx@q8vMMNR;DukaZ z!pSKFC@sP{qFE7$rANmt3HPSzfuvP>^f!>uQ(Ry@);7y{4GpR3%k5m67ABlMEfG(ULmxIbD7!!?@L_bZOvdNif z6D30hh!RI6HU0D)%(M}kEAhH;%`Hv_toUEu(YEjbH1Gk@_eog= zYeThkMQWL{9%T{kE)AL>+#q78K+WsZ^hs>qT5Z#Us4h3iPXw=9EzUqZgsx6EQM$P4 z4GBa6%J~5+rJ+ZFXkn;%7WwjwTK-=kgcYW;6kzD1iLl;W!xm^Kvo~(h0FuHyYeX#c zOavQYH7kphB(iEPvl*o*@&yqA2#qw|&*$h6amPzO5%z6aq_{^jc0Egngcp=tQSY?e z!cjI{Nre&qwA2z_pOjkIt6b=Beb|of=g4Znq%4L z1w@_(;#?iSqB`hbdyUegT=AEME4C-Xz-w5wRrtlsgQ14xl>IH`5#iLUJr;ar#E-Q2 zP_i|9QP+f#y!(O~zb^zb!xr+$+toJGhsd#q7m83-+bA7|Iw)uxcdJu6y~EYv%@fb;+|q_Z8ZE`z}PH71|mWKr(+~0qW)H@ zqh3m~f5AQ33t(-^P;D*{T&%!2jK3?fkuQEKApE0lR!rKRPVeqSEhbxi;Sm1<8^qs* zSz!^`K@2dvLRQRvB_RZEW9UOl_?IWSa12#d)Zz_7Gg~E7xg2k?h1R1d@XwfXs~6|o zafB6!m1-B_NF9el^Vb5TR086D{pb0PPFyMuAR#@j6~MNn5G^)?>2w68x)_O*MsaS}2iB4TRs`Q3cFz5C)Ck=pM0@AXFHr zK2NZunrvkttYCX!F$1BhfKsglTLCr&=W3E-_=Ug}Qu;Iv9dqW4s~&&5?*ZuNC# zQrs4Tli{f@_zV_JFq%pCxron|hU+0nYB1ENpoJ`W7EZy6*p!oCMi9ZP(Lk~Ihcp@P zaoqk%_aG{y+k z0_15jqdp^r>-k?N;SiX+0%GWkE|Opj%^g2iq{-Nqlpwh6-}j|8Bn6(a;8`0OXzl0D zQAzDXav3mnOf4LJl5M_hP#c^yv|N1jf#kx^_wbWvcX%M>Eknf4zs^;Q@_>m`JU!z| z(W74W&jKej1ti;9V1jGn>U980(t2oLYgE$D6nCuFbPR17EQo?;SsOpDwm?i^fzXk_ zbg99)uQ|K!gP206EKIvANa#EIac*8K#7LOOY@xs%SzX%Ng}BwiA@rdvfVQ+0yIM;= z*&>DdTkR4W#X7&OmuqRQ(^SF20Jbo$Buw)tjjfggPp@XVf~W5XxW6cLIdV8As-OFo zUPgiIAjiH^!dwYLecVSePK-wrjQ^+`7SYl(qfYm+qQXZaFGD8B=HKvwuSyy*9fQ?y zgpP@G)e6RkT4bo^m2i<@D4I}6nM&xT2!uy3&XqO6E}xTks>jepLiWgjnuVtk&Q=A2 z)T?Mfw6CBzY9t>>Q%OeptV&gd8lP2Q4HK?(-vaq)fpWN1#o7pz3DAu$!C$zUAdtha z66K`uDzQgNtA!q|P0`1BI}DKPsX3LtaFhY!{5xx(;4+Qv5Fh|)-dBqOy_}_R)iS`V zI}Egx(%9}jBfK#^p20|}ivcWVt#r}WYZ#V*3C|>*pirKrL)6l_(vF>6o}o}Y;8$Ni zj&zQpC4r_&4$O=*fx8HbZwbWU7D$G+MzdKt6asxJO;gzB4KJLi3hGlap%mLJi5d1dTYh-jljkh3RoEC~bP2Y8FIcx;j6uxn2P9OSKk~_Aw-792p(g zn;vd(g*2wnk5vs_ERk-+j|PBBiHA~65|O%j^M>YSdH}d^8uB=4=b?)Q0WU$>GpPAw zm`K*e2;=bUCu*n|&_W3T3r(YL3C*S>p&mv9X{~X>PnF8dBiGdaB6CWe+o&j~3NDA% z3Kap{p4l5%7$50aJ$b%K9)wS;qU2nJdK}(_5<6F*={Uk$^kXH$(Gt1xvo0K;s!dyI za~lp_To}jK_VgF@!`?g6a*2`>`%>*fYnS?A^BsvACbx{40jr6r=D~~=e#h{Z)|jCC z7w}Th=4mKKb79((x3qJR6tWH3-cy`N+HDe)X34;moC}Ip{c1-)O+~DQA-39aYwnT5 ziuI$$mPGuQHuR5irL?J~QDj$IwmU~4MKq#T<7&4-g6czRc|28?3iMwRYx17>e#BHLCqp}q7rHr$(2Pm{`2q0om({3;-_l*(PBM~&0gCf z+e-8sD+FIEIg)-UabzVaVtQ4{o#@caO6J?iz|2+>?JbfbDbhdsmm)X+7X~~01(8Ir zwM>K8p@B*7=Jg*!E~WJ)=$vBGz7>RIrRGT8X@JCnrDa4ND-BjD&0mI0X@{1^Ol(Km zRs#gy>z;I;hFlF>TWXP;f)=e>b7x@jI~2+3w<^f%xSV6|$hcG0uuID5OOLaQ=^TxE zI(D24;~}@MPSw7T71Ua-6|@OL{9!?GmXD-N#j~JnWHm!pvqp{8X04!UwVDePSG$6U zrqcvh?T9tatnRt1HC-!XWf?@%aWV`A$!jDd2RLW&QOZcT0UFZ{<(~cGqxd^;%wfGV z3k1Ug(|Q(2Fj^py%t`roAzAnu4F-YhUE0K1^oaZz~aCpO)^FXSgpxqvX! zj|K(apjg?DXe3gg*v3!C5V_mzjzh+3ri;UkOrK(8wQM1i>xY^cVpr7$*)z$ijCWD0 zz7)O((0qvVuKIGQm;k~|ssSELtbx(gz}P`LXSCfb#&9=q)r_)#0T|^C%$1Fau=@oH zpI?hDxn@i5M}vB&0XMy;x)6F$c-&j*9uBiy;^B;V&Y+q>@y5FVr1k>Nt+HPU9E#pr z#mIH8l`X=iH8{=GYeEWJTa5Won)PjgRuWvD5mbX;%{4N1d`Bo;JtAaO(VGwIN~|8a zu8RsgbhnVn74nYaFr!!WOE`YR1529)68}Evc*GARu#L1&b3Z0@F!l0MgsmU&x`{2jg)hNH5xu-XJ4^M4foL=a7PrMZo`bWO%0VmY}eL-@GUy z^jcUxZ?G6T1dBoIR*ajMbFuI>k^q{mj_yc)j{E8A*O8w4!K_V$aCGh*QVN zg0X{(VV`RwYpsCzp&*O6=eeKazAt5gb$MzUBikOLXihqY7KL?O45wTdS+?B|8c{ED zKSh04qHvMRQ&Sj%M9M@WBI#KQWi17(sa7_ZWh3e9NYZBKYm$N*UVTv08&er;h#JS4 zv*DEk0xP&Emh>uuII>HM{a%iW{tDNt62*N_#;N7qKE$V1!);NUR#aKhCAc~f^gU@s zbt2=Nh{~tXuQVFF4z(>3@+q>nEplRGR(2TvCZJ`o@1()LEpdc2I(?%N=kf@#I7-QC ztetXxh-Eo80a@9huOKoSzAdo;em5%kp~*`UNo=9L7X=9N<}j^5svt50vWV6!}fTbD!A$zVh%dcU}-341b&GAk5qC=}W|pC+0-GMMEw%9u{%iqG#2&u7W|OL5lvmL<5RZ-;`*8(ePR2p+9## zVdu(Nluz*rDJX1<_pDE0cZr%QWllg6MX@Ml)ivcS>R)b@ z)*3*2aem+ll4jKBz%u!5IuO)$IimG$I4H2F^`vmQk2y54IP#TT)!oNb@Iy!S>grNq zeZMf!2;TRBulePT+}GAmdU|JTcJrVNBe*cWyH^A;1NY~tIBIBa)qE{XBU`?Xj}jWO z8iq@AqC{f7Z*z6s@5o)Ca#?omEM zupG@=;hJA3BS&LpgYjjN#Fi$BWs{`;kx-J{xL8h+M%c{j7;FKF2ab@`Bs+fwUo|MB zZ*X9DS+M!}ezgUCUkKG66+y!1ddWnw>f&=TUJ~56nCNj~Eb$Nk8QaxLfTOnvrVHIb zv6UQ0U6I2s;9e^QQI!q>GLKP46ZPvv5MQMQ{cokjGKzJZMhvtGV#`MW5J6xyzm@h_ z$1X0`RTrlv4G3zqM}EipN=O{}#|%$O2I}GgDWN5hEXjb(grFy$N%p{6U<+5^>M;R9 z2t74;sGc)zY(}J%=Ez8X%yZD?Na{h>z+B7hvk1Ns*DHhApYFOs{tzVtz6WDMdKKuo1Vvsw98Ku-LG!J-1j)Wh=#pf8=CaRnhYofwWw~+lYv4FQ& zWKdNm#r*!?-ePk}3T!>C#`>-@ORIQAY|tEO8IAcBW4}R({ENf{D{9V&0Y-XtSqUFE zKY9t!#VI5^Hrsq#?7DBxtuDy=+BU5TUt$Sd5a{$~K_eu*G2t-NRTK2qNHPPjL@uQ{}09Y2?z4e1V zJiUzyBU+rlFvP{+zDU+52^9hm8iXa4F90<6I%pU;252?x?Bza?aA-UZmYSZnB4rqm zweN(q=_g5*a50h(6puh7Sp8}KPd9|A-FonqAiT&PqrC%BE!S1zHtvJ0&D@SIPRCRR z)#|h~ehs$y&r}ffQWUKNjgq)j1 z=^mu%IYLLd2Zc^CZ0oHK6sGu1{dQjAfBR9*yU9{*!>qH!Ae`b#>tmlN+u zg@jl&59vy#w(GQ#NeRIS7Bl4RVH5)LIn z38q>)13G%tDbu608iydaB!J{jks|o(k+jlvNCr|foh~Izok3@Gj|vm<534Y6Lf43= z`I@@5jJZcu0kaB(0jUCy3=DOJndUI?dQjk83EZQz zjVag^+`8IAMhka{AU`2woPA9})(??)f{$C>${BP4iZPj-uyIgBO6Z!1Xehi@NT5F{ zbgmLzU-7EwQ)l3tx*aUz3j{er_w0<3MBSa*!c#(rm_V2yRN&ER0Wd7s>G)Cm#B$sg zDBb?eDh$!5)6@otjCqUPcLs7FrEu<$D46R=VanJ%05#PPAcrF5*q;Kp%`1Xa-3Mg!BM&{l%}!BHnMh}v54Jda6Jf*Ob>Y4WDtRx%razajG@ zKdJYHnZP5hTO?aCmB4BrJHRfBuU}4J-wTR!yj~giDzE}8fz>>AfEoY%bV0kB>Sq#o zBw!^-*sR8hV*4KTjss=ZZ-6i9Z9Ez z3;!nsnb%GRliaO|T6LU&)f2sneG_y1?Z|Bne5+=ujYWpPTp)Ifm)%q(pOKX+DnwHTws2$fK#b%)U@!kww>1z$+ zA7W`wyTU=CAFVN7)T4w$YQXiFleV)iTMHz}v52F61H;klb z5wH>@Y`(1p0R@bv5N?$8U0c9}vw#%{-)-3TThPs;O1v!4T#GxzxxWQW=y}754DEb7 zHlRmy_s<-0v3bu4FDVkWWDr|51&_}d#CUWyEuN;E{v9Up{NPt%qOdi;oY5K&R;=^= z5|i*09Z9k$l1czQa0ZSL$<*HMhWL^8Mklb?l&Joy5*!?nIiox6lyI?mZ32&&J6A@} z(b@AXR55p~@_mI4g%jDoBbCTgXW$aWxWd6r6Qhf_ktt%{Oq)>F=-hXhK=cOaCi=kW zP!YN;g8?i75J~W)nfQ|g1>Ec6PSr%83S9|emd?Ok3VC_d$Z2yUBl6Oy;s3w66f%ZO zdHoQ(`2$0H;e-0QE2jcgG#H)qUeWJt;yMuuPI{DwH= zl0=@j$U`Hexj93_$OM3py<$TxBO_eMX^2S+s(lpi7#I|&9Yc5-iy?ODaxak&g{%aN ztegQ!$3ItYNNEToS3?jCHUwHGvR3q6B5TuW16t{#s%+qOJu)Uiqqaf=H}TeMDQ~_% z0;VbB4pWA_(7h*tFdGB%e)>g`^xcX{Wu?4{3WOWEMg=w$vbRwXX=GZukcYm*6M-t(GBma`D9$t}ihm$=Ynvw5OmRq>;GhNF*cinP zS|bjC_XP@onQ~=NOp>6z7IZTWs3F0XJ7hxpPk`oE1Pn|GM+8?1JZFX2r3w1>JRHpy zYsv(g`eD64iZS;M%#|58p>`->B}iB}5>Tp|!Hl{02Y~|MF_kNWVx(j{XhFwj3oEw_ zRP$(!8GhH8!N6yTge7}OU9#Q0)=4Z@GZ>ga^8+TB8MHrZPL_ZcGWs1TzGb`DXhWiGqrRSI7EhKbNR;Y{EuTjre-E;iAJrOg~` zo{kJ}_DOXuE9vJQ?!@BjXw$Au`YrGg#)zofcLKLADsymm)b5mUF_JPl zEP5voA%6ZvkBN}SWhkry7*kJg`Z|;;p91FhfUAUyxdmV&yy^WfDiCD#y_JU%AdAs1 z5F$@$&($Ff6$wdCS3%tB$GO=Oq-Yg{{*@N5UWXN4{Bcg9HLf=YdwzTw1legsIsf zv^ynSY<9#^zCOKpG&1}j$k3QPOn4Q-@?Sk65MmEdRs!YUY)dI{PKizl7gP8DfNG~) zRiBIu|MxMB1~mETg<$QKo<-1ehgMDrs6l{$d6@b_a-T;n?u$f;&R!+LEgJN~WPsE2 zfEU2I5LCSr{KwVe_!HqURU zuje=ZJ)y|(p11qnqF)m6KU97Q0FH^~l=)0You4*$Ka9++&2v8l!PZzyXy~zsvnMbN zt3%Ia>(Jt7tJrM|5gh5Ptu@)9*nS`&C24zeL@;jEvpczP3lRZ+tcX2S0XD-&NR@!r zkJCSdtd|nh{mSfqN`O24u#N7H085||k?w!p4v_qJRa~s|&Fm)#`f9ps$dozdNLpNi zP3DnVzY;n0gp=q&KlRs|HA+7L3AcS{nP}6;KvTlS=nIi}kL)o~!fsng*hf!mHQw_{ zdQf%xIH?jYjHK8gj2;mht`nLjRtkPSRZcAvZT18pN`xjG=hqk>5*j)SP2;zs!Rq5r znM2$hCTB57R^DMxo;=?g-rzpweN? zQ~-r&;6ewEL3Q|CB;D6YIHqz)^L?~ysNB3K_kI-IyoAMYj^JC56tYR9B(Xb?fal{% z$Dy1gDF8rBBWCjoAocv^Gf2}H`K?y$c@b6g9)tIHiPv+ucNR9r3Y=h5mlIPw3ZhI- zsheaJ(C7kWRg5x=vnQsEa2>aXajp~v&G$(${S|=ZKL|n~v5ZaEr?^5iccBA6PPyw8 zl=;Nmg0ZsszeU9wF3%K6!APc3XWflq*DS>;$zMVdHq)u0}|bUN8>^O(b~N} ztB}|w0(IiKeFL^&+=J431GZSZSeRL0eYG9(SIR)hK^?pZGeud3AfE1CBH{3h#^=XX z`}JMS{ix8mLNbQMWK3{tS#&}2WnxKLOjk^dbT6Z#(mc+d1b;oQ($`Bhp_6e(WFZZC zfHjym{!Rj?ipeRDI8N%FOT|-MmAfS{sq49Q$QpkG4oZqICx3!N{vTbes7a09&&2|W zdWSO9P(yn;F1lApxHXJ(`I|`UH|?l~c{G!6{>S4lC>Lip{wArCWFjfeE6G~eYv~4y zpG1wy;#&Z`N>W%XeioG%k9o`<=KFKrjA|e-w#_HyHe~sr+5#MM6jn_|$!m1nK=ar*A}3m#yB`#FVrY z6qRHu55FHt_c}>d2C7zmPm=Kgae%LCWt8aNAlZ+zALk^_l_k*1h^5~PfGecG6a@q@ zi;Lk8BI&TD0ML6B=Yp`PU7t7pVSwxC?AC}wIO6(0jHLT9NnwEpHvhJVDpdUd78=Rb zQ)~kqyhYugl5iYqtx(^B-KQoeozpW>AnEs1=Vw&Hc!M~XjDDt0{7b4Iyt{m_;%b% z<_o4*-VOYaO0J3NJP<`Lu|E1$B%PANd?I4IZ^)wW!%Ysm6%4Uri`cp{>l!OToakv7lG+4&YmhUKBdf=Yo__nmrQiLBT9*_9H&ZDbO?ZW z5a&{*s$jPehD}-sG6gY?i(bl&4;vVoJx4E2{qOR%=H9YfZKfLJkSMze<{WCRNzNuA zvmfVN61|c~k+Y=@VW@cx#n9$J80W>6G0x?ROsV9e1XDJG>~pYFLXD$_wPLnfje0qgsW!PJ${XTiTmdnRb1rFu_(QS);^xTAAQ_3pC*qbNKF(D_ zNSYvi*FfAvaY_-}hl02?t_(5ZDj_6I5Wi_4ZlpM|1jIN_2m0l4WthvjN*GBL%)1SY zCdR;EkHa_(^U1g}%oSV}n3<%io2}0&vB~umrxY-@$*1GW5TD|T%zm7D1Ij}?q4u`e zFiz2Uu8RVK!NG?4Y+M=UGh9KH7#YX8a`6(izW_=qCd@QSIZm#OE5qmtHlsKf*K#|@ ztDgyij{h3&Z=1KTe&p)7ZJ4XLqQD?d2A42R)qUCxVAvpC&B;7CL13T6j! zN|AF^8Bf;-bb8VP`lZM?rx17KWlt!^#g~=&}TZb5?N<)G%m6h7cH; zf-re}g*w{H&&Ni`z|fivLyM|Rs(tXB_q728*es)TWkbJW81X7>^v1S#Fj2@mx+sL# zj)9?vGmHTFG(F8N?F|w+b@vo2rKc(rx@1ELj89YCU#HDqRqVirsRb@n7~-M6Ov@l+ z2!ZiwOe|FhZFlC5&}rpG0)$6_SzH-HV0`lTqqH|fbZB!0t99d=P|oK_hT3BoZ#f_cc?!S6!QZ^2^1(o zPOmGri*;?KHDCVBo^Ta49KlR+499FphhC6sp|s=GK&i7uIOev;?xnVDB~UUC;#_H< z(Xy8)#_TspNt{nhr-^zbiPBRk$&}4d0tKoc=RzZ=zQ@ZLP7DJ=llVN4xs)dd=V+Lu zHVV7XW)^E`CXzZP__prwP#LB`bNVR^LdqRVz#I{{C}$wm7))&~Mgrk5jC1A5D9z@4 zYU|Zk--}#rmiUQ?>?jbb;^7%H?i|NFay%TjEQMLSIu4oq9d1)`5~m~ik+^bERVt{H zx4F$HxH~51apj_qaz*Aa&c)9nQPEXg9IBN*9#<~<7*`ZMjC1u?Bq}MbSZ=^Y2EIMeX^o#4Q(n zmMe-5jt_nH@yddQc?!eK5_apIk(V8pRs!BipstQ4nQXqAp zDp $@ +$(BUILDDIR)/$(LOCAL_DIR)/pi-logo.tga: $(LOCAL_DIR)/RPi-Logo-Reg-SCREEN.png + convert $< -compress RLE $@ + GLOBAL_INCLUDES += $(BUILDDIR)/$(LOCAL_DIR) include make/module.mk diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index eaa87ff363..d441cb7177 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -16,7 +16,7 @@ void print_timestamp(void); #endif #define SDRAM_BASE 0 -#ifdef VPU +#ifdef ARCH_VPU #define BCM_PERIPH_BASE_PHYS (0x7e000000U) #else /* Note: BCM2836/BCM2837 use different peripheral base than BCM2835 */ @@ -24,12 +24,12 @@ void print_timestamp(void); #endif #define BCM_PERIPH_SIZE (0x01100000U) -#if BCM2836 +#ifdef MMIO_BASE_VIRT #define BCM_PERIPH_BASE_VIRT (MMIO_BASE_VIRT) #elif BCM2837 #define BCM_PERIPH_BASE_VIRT (0xffffffffc0000000ULL) #define MEMORY_APERTURE_SIZE (1024 * 1024 * 1024) -#elif VPU +#elif ARCH_VPU #define BCM_PERIPH_BASE_VIRT (0x7e000000U) #else #error Unknown BCM28XX Variant @@ -70,6 +70,7 @@ void print_timestamp(void); #define ST_CLO (ST_BASE + 0x4) #define ST_CHI (ST_BASE + 0x8) #define ST_C0 (ST_BASE + 0xc) +#define ST_C1 (ST_BASE + 0x10) #define IC0_C (IC0_BASE + 0x0) #define IC0_S (IC0_BASE + 0x4) diff --git a/platform/bcm28xx/intc.c b/platform/bcm28xx/intc.c index 3f944cbcbb..6dacff5ca9 100644 --- a/platform/bcm28xx/intc.c +++ b/platform/bcm28xx/intc.c @@ -16,7 +16,7 @@ #include #include -#if defined (BCM2836) +#if defined(BCM2836) || defined(BCM2835) #include typedef struct arm_iframe arm_platform_iframe_t; #elif defined (BCM2837) @@ -24,7 +24,7 @@ typedef struct arm64_iframe_long arm_platform_iframe_t; #elif defined BCM2XXX_VPU #else -#error Unknown BCM28XX Variant + #error Unknown BCM28XX Variant #endif @@ -168,6 +168,7 @@ enum handler_return platform_irq(arm_platform_iframe_t *frame) { THREAD_STATS_INC(interrupts); // see what kind of irq it is +#if BCM2835 != 1 uint32_t pend = *REG32(INTC_LOCAL_IRQ_PEND0 + cpu * 4); pend &= ~(1 << (INTERRUPT_ARM_LOCAL_GPU_FAST % 32)); // mask out gpu interrupts @@ -178,6 +179,9 @@ enum handler_return platform_irq(arm_platform_iframe_t *frame) { vector = ARM_IRQ_LOCAL_BASE + ctz(pend); goto decoded; } +#else + uint32_t pend; +#endif // XXX disable for now, since all of the interesting irqs are mirrored into the other banks #if 0 diff --git a/platform/bcm28xx/mailbox.c b/platform/bcm28xx/mailbox.c index cc84be22ab..b671132637 100644 --- a/platform/bcm28xx/mailbox.c +++ b/platform/bcm28xx/mailbox.c @@ -120,6 +120,12 @@ void dispflush(void) { } +#ifndef WITH_KERNEL_VM +inline void *paddr_to_kvaddr(paddr_t x) { + return x; +} +#endif + /* LK display (lib/gfx.h) calls this function */ status_t display_get_framebuffer(struct display_framebuffer *fb) { // VideoCore returns 32-bit bus address, which needs to be converted to kernel virtual diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 85b820c74a..0338b45077 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -17,7 +17,7 @@ #include #include -#ifndef VPU +#ifdef HAVE_ARM_TIMER #include #endif @@ -27,7 +27,7 @@ #include #include -#if BCM2836 +#if BCM2836 || BCM2835 #include #include @@ -99,7 +99,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { #elif VPU #define DEBUG_UART 0 #else -#error Unknown BCM28XX Variant + #error Unknown BCM28XX Variant #endif extern void intc_init(void); @@ -162,7 +162,8 @@ void platform_early_init(void) { } #endif -#if BCM2837 +#if BCM2835 +#elif BCM2837 arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 0); /* look for a flattened device tree just before the kernel */ diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 2f25a62038..a765243ce4 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -6,34 +6,25 @@ WITH_SMP := 1 #LK_HEAP_IMPLEMENTATION ?= dlmalloc # 1st pass to set arch -ifeq ($(TARGET),rpi2) +ifeq ($(TARGET),rpi1) + ARCH := arm + ARM_CPU := arm1176jzf-s + HAVE_ARM_TIMER = 0 +else ifeq ($(TARGET),rpi2) ARCH := arm ARM_CPU := cortex-a7 - GLOBAL_DEFINES += CRYSTAL=19200000 + HAVE_ARM_TIMER = 1 else ifeq ($(TARGET),rpi3) ARCH := arm64 ARM_CPU := cortex-a53 - GLOBAL_DEFINES += CRYSTAL=19200000 + HAVE_ARM_TIMER = 1 else ifeq ($(TARGET),rpi3-vpu) - GLOBAL_DEFINES += CRYSTAL=19200000 + ARCH := vpu else ifeq ($(TARGET),rpi4-vpu) - ARCH ?= vc4 - GLOBAL_DEFINES += CRYSTAL=54000000 endif -ifeq ($(ARCH),arm) -MEMBASE := 0x00000000 -MODULE_DEPS += \ - dev/timer/arm_generic \ - lib/cbuf -MODULE_SRCS += \ - $(LOCAL_DIR)/mailbox.c \ - $(LOCAL_DIR)/intc.c \ - -LINKER_SCRIPT += \ - $(BUILDDIR)/system-onesegment.ld -else # VPU +ifeq ($(ARCH),vpu) MODULE_DEPS += platform/bcm28xx/pll ifeq ($(BOOTCODE),1) MEMBASE := 0x80000000 # in the 8 alias @@ -44,6 +35,21 @@ else # VPU MEMSIZE ?= 0x01400000 # 20MB LINKER_SCRIPT += $(LOCAL_DIR)/start.ld endif +else # VPU + ifeq ($(HAVE_ARM_TIMER),1) + MODULE_DEPS += dev/timer/arm_generic + GLOBAL_DEFINES += HAVE_ARM_TIMER=1 + else + MODULE_DEPS += dev/timer/vc4 + GLOBAL_DEFINES += VC4_TIMER_CHANNEL=1 + endif + MEMBASE := 0x00000000 + MODULE_DEPS += lib/cbuf + MODULE_SRCS += \ + $(LOCAL_DIR)/mailbox.c \ + $(LOCAL_DIR)/intc.c \ + + LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld endif @@ -64,42 +70,41 @@ MODULE_SRCS += \ GLOBAL_DEFINES += \ ARM_ARCH_WAIT_FOR_SECONDARIES=1 -ifeq ($(TARGET),rpi2) - ifeq ($(FORCENOMMU),1) - # put our kernel at 0x00000000 - KERNEL_BASE = 0x00000000 - MMIO_BASE_VIRT = 0x3f000000U - WITH_KERNEL_VM = 0 - else - # put our kernel at 0x80000000 - KERNEL_BASE = 0x80000000 - MMIO_BASE_VIRT = 0xe0000000U - endif +ifeq ($(TARGET),rpi1) + KERNEL_BASE = 0x00000000 + MMIO_BASE_VIRT = 0x20000000U + KERNEL_LOAD_OFFSET := 0x00000000 + MEMSIZE ?= 0x10000000 # 256MB + WITH_SMP = 0 + GLOBAL_DEFINES += BCM2835=1 MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) TARGET_HAS_DEBUG_LED=1 + MODULE_SRCS += $(LOCAL_DIR)/uart.c +else ifeq ($(TARGET),rpi2) + # put our kernel at 0x80000000 + KERNEL_BASE = 0x80000000 + MMIO_BASE_VIRT = 0xe0000000U KERNEL_LOAD_OFFSET := 0x00008000 MEMSIZE ?= 0x10000000 # 256MB SMP_CPU_ID_BITS := 8 GLOBAL_DEFINES += BCM2836=1 MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) MODULE_SRCS += $(LOCAL_DIR)/uart.c - else ifeq ($(TARGET),rpi3) + KERNEL_LOAD_OFFSET := 0x00080000 + MEMSIZE ?= 0x40000000 # 1GB -KERNEL_LOAD_OFFSET := 0x00080000 -MEMSIZE ?= 0x40000000 # 1GB - -GLOBAL_DEFINES += \ - MEMBASE=$(MEMBASE) \ - MEMSIZE=$(MEMSIZE) \ - MMU_WITH_TRAMPOLINE=1 \ - BCM2837=1 + GLOBAL_DEFINES += \ + MEMBASE=$(MEMBASE) \ + MEMSIZE=$(MEMSIZE) \ + MMU_WITH_TRAMPOLINE=1 \ + BCM2837=1 -MODULE_SRCS += \ - $(LOCAL_DIR)/miniuart.c + MODULE_SRCS += \ + $(LOCAL_DIR)/miniuart.c -MODULE_DEPS += \ - app/shell \ - app/tests \ - lib/fdt + MODULE_DEPS += \ + app/shell \ + app/tests \ + lib/fdt else ifeq ($(TARGET),rpi3-vpu) GLOBAL_DEFINES += \ MEMSIZE=$(MEMSIZE) \ diff --git a/platform/bcm28xx/block_device.hpp b/platform/bcm28xx/sdhost/block_device.hpp similarity index 100% rename from platform/bcm28xx/block_device.hpp rename to platform/bcm28xx/sdhost/block_device.hpp diff --git a/platform/bcm28xx/sdhost/rules.mk b/platform/bcm28xx/sdhost/rules.mk new file mode 100644 index 0000000000..2e796422d5 --- /dev/null +++ b/platform/bcm28xx/sdhost/rules.mk @@ -0,0 +1,9 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += $(LOCAL_DIR)/sdhost_impl.cpp + +MODULES += lib/bio + +include make/module.mk diff --git a/platform/bcm28xx/sd_proto.hpp b/platform/bcm28xx/sdhost/sd_proto.hpp similarity index 100% rename from platform/bcm28xx/sd_proto.hpp rename to platform/bcm28xx/sdhost/sd_proto.hpp diff --git a/platform/bcm28xx/sdhost_impl.cpp b/platform/bcm28xx/sdhost/sdhost_impl.cpp similarity index 100% rename from platform/bcm28xx/sdhost_impl.cpp rename to platform/bcm28xx/sdhost/sdhost_impl.cpp diff --git a/project/rpi1-test.mk b/project/rpi1-test.mk new file mode 100644 index 0000000000..3b1495bfef --- /dev/null +++ b/project/rpi1-test.mk @@ -0,0 +1,13 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +TARGET := rpi1 + +MODULES += \ + app/shell \ + app/stringtests \ + app/tests \ + lib/cksum \ + lib/debugcommands \ + platform/bcm28xx/pll \ + platform/bcm28xx/hvs-dance \ + lib/tga \ diff --git a/release.nix b/release.nix index e8341c4040..bfa6e45091 100644 --- a/release.nix +++ b/release.nix @@ -2,7 +2,7 @@ let self = import ./.; in { arm = { - inherit (self.arm) rpi2-test; + inherit (self.arm) rpi1-test rpi2-test rpi3-test; }; vc4 = { inherit (self.vc4) rpi3 rpi4 vc4; diff --git a/target/rpi1/rules.mk b/target/rpi1/rules.mk new file mode 100644 index 0000000000..0ae00c435b --- /dev/null +++ b/target/rpi1/rules.mk @@ -0,0 +1,14 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +GLOBAL_INCLUDES += \ + $(LOCAL_DIR)/include + +PLATFORM := bcm28xx +ARCH ?= arm + +GLOBAL_DEFINES += CRYSTAL=19200000 BCM2835=1 + +#include make/module.mk + +ENABLE_THUMB := false +ARM_WITHOUT_VFP_NEON := true diff --git a/target/rpi2/rules.mk b/target/rpi2/rules.mk index fe10d50d72..8ad31c0035 100644 --- a/target/rpi2/rules.mk +++ b/target/rpi2/rules.mk @@ -5,5 +5,8 @@ GLOBAL_INCLUDES += \ PLATFORM := bcm28xx +GLOBAL_DEFINES += CRYSTAL=19200000 BCM2836=1 +ARCH ?= arm + #include make/module.mk diff --git a/target/rpi3-vpu/rules.mk b/target/rpi3-vpu/rules.mk index 4faae1f4a9..d45fc25c36 100644 --- a/target/rpi3-vpu/rules.mk +++ b/target/rpi3-vpu/rules.mk @@ -3,9 +3,10 @@ LOCAL_DIR := $(GET_LOCAL_DIR) GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include -GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 VPU=1 MODEL=3 +GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 CRYSTAL=54000000 PLATFORM := bcm28xx +ARCH ?= vpu #include make/module.mk diff --git a/target/rpi3/rules.mk b/target/rpi3/rules.mk index fe10d50d72..c17348e3b1 100644 --- a/target/rpi3/rules.mk +++ b/target/rpi3/rules.mk @@ -4,6 +4,9 @@ GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include PLATFORM := bcm28xx +ARCH ?= arm64 + +GLOBAL_DEFINES += CRYSTAL=19200000 BCM2837=1 #include make/module.mk diff --git a/target/rpi4-vpu/rules.mk b/target/rpi4-vpu/rules.mk index d4586a2f10..e7b77f1f09 100644 --- a/target/rpi4-vpu/rules.mk +++ b/target/rpi4-vpu/rules.mk @@ -3,9 +3,10 @@ LOCAL_DIR := $(GET_LOCAL_DIR) GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include -GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 VPU=1 MODEL=4 +GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 CRYSTAL=54000000 PLATFORM := bcm28xx +ARCH := vpu #include make/module.mk diff --git a/target/rpi4/rules.mk b/target/rpi4/rules.mk new file mode 100644 index 0000000000..9063edee6c --- /dev/null +++ b/target/rpi4/rules.mk @@ -0,0 +1,6 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +GLOBAL_DEFINES += CRYSTAL=54000000 + +PLATFORM := bcm28xx +ARCH ?= arm64 From 79eb9294fa259055d902f11d87f0958b0b018214 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Tue, 13 Oct 2020 04:43:26 -0300 Subject: [PATCH 069/100] it can now render 13 at once, and the glitch near the top is fixed --- platform/bcm28xx/hvs-dance/dance.c | 99 ++++++++++++++----- platform/bcm28xx/hvs-dance/rules.mk | 3 +- .../bcm28xx/include/platform/bcm28xx/pv.h | 11 --- .../pixelvalve/include/platform/bcm28xx/pv.h | 41 ++++++++ platform/bcm28xx/pixelvalve/pv.c | 62 ++++++++---- platform/bcm28xx/pixelvalve/rules.mk | 2 + 6 files changed, 159 insertions(+), 59 deletions(-) delete mode 100644 platform/bcm28xx/include/platform/bcm28xx/pv.h create mode 100644 platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h diff --git a/platform/bcm28xx/hvs-dance/dance.c b/platform/bcm28xx/hvs-dance/dance.c index 95590ae692..4546a6a3ca 100644 --- a/platform/bcm28xx/hvs-dance/dance.c +++ b/platform/bcm28xx/hvs-dance/dance.c @@ -1,10 +1,10 @@ #include -#include #include #include #include #include #include +#include #include #include @@ -14,39 +14,73 @@ STATIC_COMMAND_START STATIC_COMMAND("dance", "make the HVS dance in another direction", &cmd_hvs_dance) STATIC_COMMAND_END(hvs_dance); -timer_t updater; gfx_surface *fb; -unsigned int x, y; -signed int xd, yd; -static enum handler_return updater_entry(struct timer *t, lk_time_t now, void *arg) { +struct item { + int x, y; + signed int xd, yd; +}; + +#define ITEMS 13 +struct item items[ITEMS]; + +void do_frame_update(void) { + int start = display_slot; - hvs_add_plane(fb, x, y); + for (int i=0; ix > (0x500 - fb->width)) it->xd *= -1; + if (it->y > (0x400 - fb->height)) it->yd *= -1; + it->x += it->xd; + it->y += it->yd; + + if (it->x < 0) { + it->x = it->x * -1; + it->xd *= -1; + } + if (it->y < 0) { + it->y = it->y * -1; + it->yd *= -1; + } + hvs_add_plane(fb, it->x, it->y); + } hvs_terminate_list(); - *REG32(SCALER_DISPLIST1) = start; - if (x > (0x500 - fb->width)) xd *= -1; - if (y > (0x400 - fb->height)) yd *= -1; + *REG32(SCALER_DISPLIST1) = start; - x += xd; - y += yd; + if (display_slot > 4000) { + display_slot = 0; + puts("dlist loop"); + } +} - if (display_slot > 200) display_slot = 0; +static enum handler_return pv_irq(void *pvnr) { + struct pixel_valve *rawpv = getPvAddr(pvnr); + uint32_t stat = rawpv->int_status; + if (stat & PV_INTEN_VFP_START) { + rawpv->int_status = PV_INTEN_VFP_START; + struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); + uint32_t stat1 = hvs_channels[1].dispstat; + do_frame_update(); + printf("line: %d frame: %d start: %d\n", stat1 & 0xfff, (stat1 >> 12) & 0x3f, *REG32(SCALER_DISPLIST1)); + } return INT_NO_RESCHEDULE; } static int cmd_hvs_dance(int argc, const cmd_args *argv) { - x = (unsigned int)rand() % 0x500; - y = (unsigned int)rand() % 0x400; - xd = rand() % 25; - yd = rand() % 25; - if (x > (0x500 - fb->width)) x = 0x500 - fb->width; - if (y > (0x400 - fb->height)) y = 0x400 - fb->height; + for (int i=0; ix = (unsigned int)rand() % 0x500; + it->y = (unsigned int)rand() % 0x400; + it->xd = rand() % 25; + it->yd = rand() % 25; + if (it->x > (0x500 - fb->width)) it->x = 0x500 - fb->width; + if (it->y > (0x400 - fb->height)) it->y = 0x400 - fb->height; + } return 0; } static void dance_init(struct app_descriptor *app) { - timer_initialize(&updater); fb = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); if (!fb) { fb = gfx_create_surface(NULL, 10, 10, 10, GFX_FORMAT_ARGB_8888); @@ -66,13 +100,26 @@ static void dance_init(struct app_descriptor *app) { static void dance_entry(const struct app_descriptor *app, void *args) { gfx_flush(fb); srand(*REG32(ST_CLO)); - x = (unsigned int)rand() % 0x500; - y = (unsigned int)rand() % 0x400; - xd = rand() % 25; - yd = rand() % 25; - if (x > (0x500 - fb->width)) x = 0x500 - fb->width; - if (y > (0x400 - fb->height)) y = 0x400 - fb->height; - timer_set_periodic(&updater, 20, updater_entry, NULL); + for (int i=0; ix = (unsigned int)rand() % 0x500; + it->y = (unsigned int)rand() % 0x400; + it->xd = rand() % 25; + it->yd = rand() % 25; + if (it->x > (0x500 - fb->width)) it->x = 0x500 - fb->width; + if (it->y > (0x400 - fb->height)) it->y = 0x400 - fb->height; + } + + { + puts("setting up pv interrupt"); + int pvnr = 2; + struct pixel_valve *rawpv = getPvAddr(pvnr); + rawpv->int_enable = 0; + rawpv->int_status = 0xff; + setup_pv_interrupt(pvnr, pv_irq, pvnr); + rawpv->int_enable = PV_INTEN_VFP_START; + puts("done"); + } } APP_START(hvs_dance) diff --git a/platform/bcm28xx/hvs-dance/rules.mk b/platform/bcm28xx/hvs-dance/rules.mk index 2924535bf7..80b982066e 100644 --- a/platform/bcm28xx/hvs-dance/rules.mk +++ b/platform/bcm28xx/hvs-dance/rules.mk @@ -3,7 +3,8 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) MODULE_DEPS += \ - platform/bcm28xx/hvs + platform/bcm28xx/hvs \ + platform/bcm28xx/pixelvalve MODULE_SRCS += \ $(LOCAL_DIR)/dance.c diff --git a/platform/bcm28xx/include/platform/bcm28xx/pv.h b/platform/bcm28xx/include/platform/bcm28xx/pv.h deleted file mode 100644 index 4acd4b899f..0000000000 --- a/platform/bcm28xx/include/platform/bcm28xx/pv.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -struct pv_timings { - uint16_t vfp, vsync, vbp, vactive; - uint16_t hfp, hsync, hbp, hactive; -}; - -void setup_pixelvalve(struct pv_timings *timings, int pvnr); - -#define PV_CONTROL_FIFO_CLR (1<<1) -#define PV_CONTROL_EN (1<<0) diff --git a/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h b/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h new file mode 100644 index 0000000000..1ee3e8a982 --- /dev/null +++ b/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +struct pv_timings { + uint16_t vfp, vsync, vbp, vactive; + uint16_t hfp, hsync, hbp, hactive; +}; + +struct pixel_valve { + volatile uint32_t c; + volatile uint32_t vc; + volatile uint32_t vsyncd_even; + volatile uint32_t horza; + volatile uint32_t horzb; + volatile uint32_t verta; + volatile uint32_t vertb; + volatile uint32_t verta_even; + volatile uint32_t vertb_even; + volatile uint32_t int_enable; + volatile uint32_t int_status; + volatile uint32_t h_active; +}; + +void setup_pixelvalve(struct pv_timings *timings, int pvnr); +void setup_pv_interrupt(int pvnr, int_handler handler, void *arg); +struct pixel_valve *getPvAddr(int pvnr); + +#define PV_CONTROL_FIFO_CLR (1<<1) +#define PV_CONTROL_EN (1<<0) + +#define PV_INTEN_HSYNC_START (1<<0) +#define PV_INTEN_HBP_START (1<<1) +#define PV_INTEN_HACT_START (1<<2) +#define PV_INTEN_HFP_START (1<<3) +#define PV_INTEN_VSYNC_START (1<<4) +#define PV_INTEN_VBP_START (1<<5) +#define PV_INTEN_VACT_START (1<<6) +#define PV_INTEN_VFP_START (1<<7) +#define PV_INTEN_VFP_END (1<<8) +#define PV_INTEN_IDLE (1<<9) diff --git a/platform/bcm28xx/pixelvalve/pv.c b/platform/bcm28xx/pixelvalve/pv.c index c5f6993e40..505453fcb0 100644 --- a/platform/bcm28xx/pixelvalve/pv.c +++ b/platform/bcm28xx/pixelvalve/pv.c @@ -1,35 +1,47 @@ -#include -#include +#include #include +#include #include +#include #define BV(b) (1 << b) -struct pixel_valve { - volatile uint32_t c; - volatile uint32_t vc; - volatile uint32_t vsyncd_even; - volatile uint32_t horza; - volatile uint32_t horzb; - volatile uint32_t verta; - volatile uint32_t vertb; - volatile uint32_t verta_even; - volatile uint32_t vertb_even; - volatile uint32_t int_enable; - volatile uint32_t int_status; - volatile uint32_t h_active; -}; - -void setup_pixelvalve(struct pv_timings *t, int pvnr) { +struct pixel_valve *getPvAddr(int pvnr) { uint32_t addr; + assert(pvnr <= 2); switch (pvnr) { case 0: addr = BCM_PERIPH_BASE_VIRT + 0x206000; break; + case 1: + addr = BCM_PERIPH_BASE_VIRT + 0x207000; + break; + case 2: + addr = BCM_PERIPH_BASE_VIRT + 0x807000; + break; + default: + return NULL; + } + struct pixel_valve *rawpv = addr; + return rawpv; +} + +unsigned int getPvIrq(int pvnr) { + assert(pvnr <= 2); + switch (pvnr) { + case 0: + return 45; + case 1: + return 46; + case 2: + return 42; default: - return; + return -1; } - volatile struct pixel_valve *rawpv = addr; +} + +void setup_pixelvalve(struct pv_timings *t, int pvnr) { + struct pixel_valve *rawpv = getPvAddr(pvnr); // reset the PV fifo rawpv->c = 0; @@ -46,7 +58,7 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { # define PV_CONTROL_CLK_SELECT_DSI 0 # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 # define PV_CONTROL_CLK_SELECT_VEC 2 -#define PIXEL_REP(n) ((n & 0x3) << 4) +#define PIXEL_REP(n) (((n) & 0x3) << 4) #define FIFO_LEVEL(n) ((n & 0x3f) << 15) rawpv->vc = BV(0) | // video enable @@ -66,3 +78,11 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { BV(14) | // clear at start FIFO_LEVEL(fifo_len_bytes); } + +void setup_pv_interrupt(int pvnr, int_handler handler, void *arg) { + struct pixel_valve *rawpv = getPvAddr(pvnr); + unsigned int irq = getPvIrq(pvnr); + + register_int_handler(irq, handler, arg); + unmask_interrupt(irq); +} diff --git a/platform/bcm28xx/pixelvalve/rules.mk b/platform/bcm28xx/pixelvalve/rules.mk index e2e38965f7..176a226187 100644 --- a/platform/bcm28xx/pixelvalve/rules.mk +++ b/platform/bcm28xx/pixelvalve/rules.mk @@ -5,4 +5,6 @@ MODULE := $(LOCAL_DIR) MODULE_SRCS += \ $(LOCAL_DIR)/pv.c \ +GLOBAL_INCLUDES += $(LOCAL_DIR)/include + include make/module.mk From 6aed09c1f6d3eec18331845be205a0d61e17d4de Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:30:48 -0300 Subject: [PATCH 070/100] fix rpi3-test on CI --- default.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 84799bdc1c..122b7124ec 100644 --- a/default.nix +++ b/default.nix @@ -29,6 +29,8 @@ in lib.fix (self: { pkgsCross.riscv32-embedded.stdenv.cc pkgsCross.riscv64-embedded.stdenv.cc python + qemu + imagemagick ]; ARCH_x86_TOOLCHAIN_PREFIX = "i686-elf-"; ARCH_x86_TOOLCHAIN_INCLUDED = true; @@ -40,7 +42,7 @@ in lib.fix (self: { arm = { rpi1-test = arm7.callPackage ./lk.nix { project = "rpi1-test"; }; rpi2-test = arm7.callPackage ./lk.nix { project = "rpi2-test"; }; - rpi3-test = pkgs.pkgsCross.callPackage ./lk.nix { project = "rpi3-test"; }; + rpi3-test = pkgs.pkgsCross.aarch64-embedded.callPackage ./lk.nix { project = "rpi3-test"; }; }; vc4 = { shell = vc4.littlekernel; From 8f27630b82750de20907a8d2d8d5bea2812ec23d Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:33:24 -0300 Subject: [PATCH 071/100] missed a platform change --- platform/bcm28xx/rules.mk | 60 ++++++++++++++------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index a765243ce4..63ce8739c0 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -35,7 +35,8 @@ ifeq ($(ARCH),vpu) MEMSIZE ?= 0x01400000 # 20MB LINKER_SCRIPT += $(LOCAL_DIR)/start.ld endif -else # VPU + GLOBAL_DEFINES += SMP_MAX_CPUS=1 +else # it must be arm32 or arm64 ifeq ($(HAVE_ARM_TIMER),1) MODULE_DEPS += dev/timer/arm_generic GLOBAL_DEFINES += HAVE_ARM_TIMER=1 @@ -44,18 +45,17 @@ else # VPU GLOBAL_DEFINES += VC4_TIMER_CHANNEL=1 endif MEMBASE := 0x00000000 - MODULE_DEPS += lib/cbuf MODULE_SRCS += \ $(LOCAL_DIR)/mailbox.c \ $(LOCAL_DIR)/intc.c \ LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld + GLOBAL_DEFINES += \ + ARM_ARCH_WAIT_FOR_SECONDARIES=1 endif -#lib/bio \ - lib/cbuf \ - lib/minip \ +# lib/minip \ dev/interrupt/arm_gic \ dev/timer/arm_cortex_a9 @@ -66,17 +66,13 @@ MODULE_SRCS += \ #$(LOCAL_DIR)/i2c.c \ - -GLOBAL_DEFINES += \ - ARM_ARCH_WAIT_FOR_SECONDARIES=1 - ifeq ($(TARGET),rpi1) KERNEL_BASE = 0x00000000 MMIO_BASE_VIRT = 0x20000000U KERNEL_LOAD_OFFSET := 0x00000000 MEMSIZE ?= 0x10000000 # 256MB WITH_SMP = 0 - GLOBAL_DEFINES += BCM2835=1 MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) TARGET_HAS_DEBUG_LED=1 + GLOBAL_DEFINES += MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) TARGET_HAS_DEBUG_LED=1 MODULE_SRCS += $(LOCAL_DIR)/uart.c else ifeq ($(TARGET),rpi2) # put our kernel at 0x80000000 @@ -85,7 +81,7 @@ else ifeq ($(TARGET),rpi2) KERNEL_LOAD_OFFSET := 0x00008000 MEMSIZE ?= 0x10000000 # 256MB SMP_CPU_ID_BITS := 8 - GLOBAL_DEFINES += BCM2836=1 MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) + GLOBAL_DEFINES += MMIO_BASE_VIRT=$(MMIO_BASE_VIRT) MODULE_SRCS += $(LOCAL_DIR)/uart.c else ifeq ($(TARGET),rpi3) @@ -93,47 +89,35 @@ else ifeq ($(TARGET),rpi3) MEMSIZE ?= 0x40000000 # 1GB GLOBAL_DEFINES += \ - MEMBASE=$(MEMBASE) \ - MEMSIZE=$(MEMSIZE) \ - MMU_WITH_TRAMPOLINE=1 \ - BCM2837=1 + MMU_WITH_TRAMPOLINE=1 - MODULE_SRCS += \ - $(LOCAL_DIR)/miniuart.c + MODULE_SRCS += $(LOCAL_DIR)/miniuart.c MODULE_DEPS += \ - app/shell \ - app/tests \ - lib/fdt + app/shell \ + app/tests \ + lib/fdt else ifeq ($(TARGET),rpi3-vpu) GLOBAL_DEFINES += \ - MEMSIZE=$(MEMSIZE) \ - MEMBASE=$(MEMBASE) \ - RPI3=1 \ - VPU=1 \ - SMP_MAX_CPUS=1 \ MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ - $(LOCAL_DIR)/sdhost_impl.cpp \ $(LOCAL_DIR)/print_timestamp.c \ - MODULES += \ - lib/bio \ + MODULES += platform/bcm28xx/sdhost else ifeq ($(TARGET),rpi4-vpu) -GLOBAL_DEFINES += \ - BCM2XXX_VPU=1 SMP_MAX_CPUS=1 \ - MEMSIZE=$(MEMSIZE) \ - MEMBASE=$(MEMBASE) \ - RPI4=1 \ - VPU=1 \ + GLOBAL_DEFINES += RPI4=1 -MODULE_SRCS += \ - $(LOCAL_DIR)/uart.c \ - $(LOCAL_DIR)/genet.c \ - $(LOCAL_DIR)/udelay.c \ + MODULE_SRCS += \ + $(LOCAL_DIR)/uart.c \ + $(LOCAL_DIR)/genet.c \ + $(LOCAL_DIR)/udelay.c \ endif +GLOBAL_DEFINES += \ + MEMBASE=$(MEMBASE) \ + MEMSIZE=$(MEMSIZE) \ + include make/module.mk From fda45ef1b65e994e6006e03138be2dd0bca6b6fa Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:35:22 -0300 Subject: [PATCH 072/100] and this too --- platform/bcm28xx/platform.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 0338b45077..90b7d5fdf6 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -96,7 +96,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { #define DEBUG_UART 1 -#elif VPU +#elif ARCH_VPU #define DEBUG_UART 0 #else #error Unknown BCM28XX Variant @@ -156,7 +156,7 @@ void platform_early_init(void) { intc_init(); -#ifdef VPU +#ifdef ARCH_VPU if (xtal_freq == 19200000) { switch_vpu_to_pllc(); } @@ -210,7 +210,7 @@ void platform_early_init(void) { #elif BCM2836 arm_generic_timer_init(INTERRUPT_ARM_LOCAL_CNTPNSIRQ, 1000000); -#elif VPU +#elif ARCH_VPU #else #error Unknown BCM28XX Variant #endif @@ -246,16 +246,21 @@ void platform_early_init(void) { } #endif #endif + puts("done platform early init"); } void platform_init(void) { -#ifdef VPU +#ifdef ARCH_VPU uint32_t r28, sp; __asm__ volatile ("mov %0, r28" : "=r"(r28)); __asm__ volatile ("mov %0, sp" : "=r"(sp)); dprintf(INFO, "platform_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); #endif +#if BCM2835 == 1 + gpio_config(0, 1); +#endif + #ifdef RPI4 gpio_config(42, 1); #endif @@ -302,6 +307,8 @@ void target_set_debug_led(unsigned int led, bool on) { case 0: #ifdef RPI4 gpio_set(42, on); +#elif BCM2835==1 + gpio_set(0, on); #endif break; default: From 5ae9f7062973e6b0f88392156391be157bcc2951 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:38:28 -0300 Subject: [PATCH 073/100] fill in the arm64 compiler prefix --- lk.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/lk.nix b/lk.nix index 84f26cc40b..bf1620d186 100644 --- a/lk.nix +++ b/lk.nix @@ -16,4 +16,5 @@ stdenv.mkDerivation { echo "file binary-dist $out/lk.bin" >> $out/nix-support/hydra-build-products echo "file binary-dist $out/lk.elf" >> $out/nix-support/hydra-build-products ''; + ARCH_arm64_TOOLCHAIN_PREFIX = "aarch64-none-elf-"; } From 199cb4ab443d9189d6968a878bd939959cdf1c50 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:45:16 -0300 Subject: [PATCH 074/100] try to fix pi-logo.h rule, improve src filter name --- lk.nix | 6 +++++- platform/bcm28xx/hvs-dance/rules.mk | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lk.nix b/lk.nix index bf1620d186..d6437e47b0 100644 --- a/lk.nix +++ b/lk.nix @@ -2,7 +2,11 @@ stdenv.mkDerivation { name = "littlekernel-${project}"; - src = stdenv.lib.cleanSource ./.; + src = builtins.path { + filter = stdenv.lib.cleanSourceFilter; + path = ./.; + name = "lk-src"; + }; makeFlags = [ "PROJECT=${project}" ]; hardeningDisable = [ "format" ]; nativeBuildInputs = [ which ]; diff --git a/platform/bcm28xx/hvs-dance/rules.mk b/platform/bcm28xx/hvs-dance/rules.mk index 80b982066e..211eeb77b9 100644 --- a/platform/bcm28xx/hvs-dance/rules.mk +++ b/platform/bcm28xx/hvs-dance/rules.mk @@ -15,6 +15,8 @@ $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.h: $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.tga $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.tga: $(LOCAL_DIR)/RPi-Logo-Reg-SCREEN.png convert $< -compress RLE $@ +$(BUILDDIR)/$(LOCAL_DIR)/dance.o: $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.h + GLOBAL_INCLUDES += $(BUILDDIR)/$(LOCAL_DIR) include make/module.mk From 7b88aa78c5b74fd460d09f7c63240210ca47b871 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:47:20 -0300 Subject: [PATCH 075/100] also include imagemagick in the env --- lk.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lk.nix b/lk.nix index d6437e47b0..43a3e15977 100644 --- a/lk.nix +++ b/lk.nix @@ -1,4 +1,4 @@ -{ stdenv, project, which }: +{ stdenv, project, which, imagemagick }: stdenv.mkDerivation { name = "littlekernel-${project}"; @@ -9,7 +9,7 @@ stdenv.mkDerivation { }; makeFlags = [ "PROJECT=${project}" ]; hardeningDisable = [ "format" ]; - nativeBuildInputs = [ which ]; + nativeBuildInputs = [ which imagemagick ]; installPhase = '' mkdir -p $out/nix-support cp -r build-${project}/{config.h,lk.*} $out From 42ef69f88508767df7c30323adff9efb4a19ef99 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:53:10 -0300 Subject: [PATCH 076/100] work around a bug in nixpkgs --- lk.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lk.nix b/lk.nix index 43a3e15977..03ef4ed38e 100644 --- a/lk.nix +++ b/lk.nix @@ -9,7 +9,10 @@ stdenv.mkDerivation { }; makeFlags = [ "PROJECT=${project}" ]; hardeningDisable = [ "format" ]; - nativeBuildInputs = [ which imagemagick ]; + nativeBuildInputs = [ + which + imagemagick.__spliced.buildBuild # work around a bug in nixpkgs + ]; installPhase = '' mkdir -p $out/nix-support cp -r build-${project}/{config.h,lk.*} $out From cba5030bfbc62c0f747526aa495469c0e4928e58 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 20:56:41 -0300 Subject: [PATCH 077/100] also include python in the build --- lk.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lk.nix b/lk.nix index 03ef4ed38e..6420df8d63 100644 --- a/lk.nix +++ b/lk.nix @@ -1,4 +1,4 @@ -{ stdenv, project, which, imagemagick }: +{ stdenv, project, which, imagemagick, python }: stdenv.mkDerivation { name = "littlekernel-${project}"; @@ -12,6 +12,7 @@ stdenv.mkDerivation { nativeBuildInputs = [ which imagemagick.__spliced.buildBuild # work around a bug in nixpkgs + python ]; installPhase = '' mkdir -p $out/nix-support From 4081cf6468c062fd8f4fe6c08847c529590e5a23 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 21:00:15 -0300 Subject: [PATCH 078/100] arm1176 fixes --- arch/arm/rules.mk | 11 +++++++++-- arch/arm/toolchain.mk | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/rules.mk b/arch/arm/rules.mk index b866351231..2f4f002aea 100644 --- a/arch/arm/rules.mk +++ b/arch/arm/rules.mk @@ -104,6 +104,7 @@ GLOBAL_DEFINES += \ ARM_WITH_THUMB=1 \ ARM_WITH_THUMB2=1 \ ARM_WITH_CACHE=1 \ + ARM_WITH_FIQ=1 \ ARM_WITH_HYP=1 HANDLED_CORE := true endif @@ -174,14 +175,20 @@ GLOBAL_DEFINES += \ HANDLED_CORE := true endif ifeq ($(ARM_CPU),arm1176jzf-s) +WITH_KERNEL_VM = 0 GLOBAL_DEFINES += \ ARM_WITH_CP15=1 \ - ARM_WITH_MMU=1 \ + ARM_WITH_MMU=0 \ ARM_ISA_ARMv6=1 \ - ARM_WITH_VFP=1 \ + ARM_ISA_ARMV6K=1 \ ARM_WITH_THUMB=1 \ ARM_WITH_CACHE=1 \ + ARM_WITH_FIQ=1 \ ARM_CPU_ARM1136=1 +ifneq ($(ARM_WITHOUT_VFP_NEON),true) + GLOBAL_DEFINES += \ + ARM_WITH_VFP=1 +endif HANDLED_CORE := true endif ifeq ($(ARM_CPU),cortex-r4f) diff --git a/arch/arm/toolchain.mk b/arch/arm/toolchain.mk index b42e9c922b..71632a7742 100644 --- a/arch/arm/toolchain.mk +++ b/arch/arm/toolchain.mk @@ -103,7 +103,7 @@ ifeq ($(ARM_CPU),arm1136j-s) ARCH_arm_COMPILEFLAGS += -mcpu=$(ARM_CPU) endif ifeq ($(ARM_CPU),arm1176jzf-s) -ARCH_arm_COMPILEFLAGS += -mcpu=$(ARM_CPU) +ARCH_arm_COMPILEFLAGS += -mcpu=$(ARM_CPU) -mfpu=vfp -march=armv6zk endif ifeq ($(ARM_CPU),cortex-r4f) ARCH_arm_COMPILEFLAGS += -march=armv7-r From a91059bd32ac0feb82054d35df2023871f59e8a6 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 16 Oct 2020 21:04:22 -0300 Subject: [PATCH 079/100] include fake barrier opcodes --- arch/arm/arm/ops.S | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/arm/ops.S b/arch/arm/arm/ops.S index ca99f44535..4809bdbf55 100644 --- a/arch/arm/arm/ops.S +++ b/arch/arm/arm/ops.S @@ -8,6 +8,14 @@ #include #include +.macro DMB + mcr p15, 0, r0, c7, c10, 5 +.endm + +.macro DSB + mcr p15, 0, r0, c7, c10, 4 +.endm + .text /* void _arch_enable_ints(void); */ From abdf484c1cd02adfb5fba1fa0080aa201126b140 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 20 Nov 2020 18:22:00 -0400 Subject: [PATCH 080/100] partially implement dwc2 device mode code overhaul arch setup for targets add support for .text.bootloader_state on the pi4 --- platform/bcm28xx/dwc2.c | 302 ++++++++++++++++++++++++++++++ platform/bcm28xx/rules.mk | 21 +-- platform/bcm28xx/start4/rules.mk | 10 + platform/bcm28xx/start4/start4.c | 141 ++++++++++++++ platform/bcm28xx/start4/start4.ld | 6 + project/rpi3-bootcode.mk | 1 - project/rpi3-start.mk | 1 - project/rpi4-recovery.mk | 1 - project/rpi4-start4.mk | 2 +- project/vc4-stage1.mk | 1 - project/vc4-stage2.mk | 2 - target/rpi1/rules.mk | 4 +- target/rpi2/rules.mk | 4 +- target/rpi3-vpu/rules.mk | 4 +- target/rpi3/rules.mk | 4 +- target/rpi4-vpu/rules.mk | 5 + 16 files changed, 478 insertions(+), 31 deletions(-) create mode 100644 platform/bcm28xx/dwc2.c create mode 100644 platform/bcm28xx/start4/rules.mk create mode 100644 platform/bcm28xx/start4/start4.c create mode 100644 platform/bcm28xx/start4/start4.ld diff --git a/platform/bcm28xx/dwc2.c b/platform/bcm28xx/dwc2.c new file mode 100644 index 0000000000..b2c8a95858 --- /dev/null +++ b/platform/bcm28xx/dwc2.c @@ -0,0 +1,302 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) + +#define USB_GAHBCFG (USB_BASE + 0x0008) +#define USB_GINTSTS (USB_BASE + 0x0014) +#define USB_GINTSTS_RXFLVL (1 << 4) +#define USB_GRXSTSP (USB_BASE + 0x0020) +#define USB_DCFG (USB_BASE + 0x0800) +#define USB_DAINT (USB_BASE + 0x0818) + +#define USB_DIEPCTL0 (USB_BASE + 0x0900) +#define USB_DIEPINT0 (USB_BASE + 0x0908) + +#define USB_DIEPCTL1 (USB_BASE + 0x0920) +#define USB_DIEPINT1 (USB_BASE + 0x0928) + +#define USB_DIEPCTL2 (USB_BASE + 0x0940) + +#define USB_DOEPINT0 (USB_BASE + 0x0b08) +#define USB_DOEPINT1 (USB_BASE + 0x0b28) +#define USB_DOEPINT2 (USB_BASE + 0x0b48) +#define USB_DOEPINT3 (USB_BASE + 0x0b68) +#define USB_DOEPINT4 (USB_BASE + 0x0b88) +#define USB_DOEPINT5 (USB_BASE + 0x0ba8) +#define USB_DOEPINT6 (USB_BASE + 0x0bc8) +#define USB_DOEPINT7 (USB_BASE + 0x0be8) +#define USB_DOEPINT8 (USB_BASE + 0x0c08) +#define USB_DOEPINT9 (USB_BASE + 0x0c28) + +#define USB_DFIFO0 (USB_BASE + 0x1000) +#define USB_DFIFO1 (USB_BASE + 0x2000) + +typedef struct { + volatile uint32_t control; // 0 + uint32_t pad1; // 4 + volatile uint32_t interrupt; // 8 + uint32_t pad2; // c + volatile uint32_t size; // 10 + volatile uint32_t dma; // 14 + volatile uint32_t fifo_status;// 18 number of 32bit words that are free in the fifo +} endpoint_control; + +typedef struct { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} setupData; + +typedef struct { + uint32_t cmd; + char name[256]; +} fileServerRequest; + +timer_t dwc2_poll; + +const char *packet_status_names[] = { + [1] = "GOUTNAK", + [2] = "OUT data packet received", + [3] = "XFERCOMPL", + [4] = "SETUPCOMPL", + [5] = "TGLERR", + [6] = "SETUP packet received", + [7] = "CHLT" +}; + +static int cmd_dwc_dump(int argc, const cmd_args *argv); +static void dump_endpoint(endpoint_control *ep, bool in); +static void ack_ep(endpoint_control *ep); + +STATIC_COMMAND_START +STATIC_COMMAND("dwc_dump", "dump dwc registers", &cmd_dwc_dump) +STATIC_COMMAND_END(dwc); + +#define dumpreg(reg) { t = *REG32(reg); printf(#reg":\t 0x%x\n", t); } +#define GET_IN(epNr) ((endpoint_control*) ((USB_BASE + 0x0900) + (epNr) * 0x20)) + +static uint8_t packet_buffer[4096]; + +void ep_write_in_reply(int epNr, void *buffer, int bytes) { + int maxPacketSize = 64; + int fullPackets = bytes / maxPacketSize; + int partialPacketSize = bytes - (fullPackets*maxPacketSize); + int packets = fullPackets + ((partialPacketSize==0) ? 0 : 1); + int words = ROUNDUP(bytes,4)/4; + printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); + uint32_t x = (3 << 29) | (packets<<19) | bytes; + printf("size is 0x%x\n", x); + + endpoint_control *ep = GET_IN(epNr); + ep->size = x; + ep->control = (1<<31) | // endpoint enable + (1 << 26) | // clear nak + (0 << 22) | // fifo# + (1 << 15) | // USB active endpoint + (0 & 0x3); // max packet size + dump_endpoint(ep, true); + ack_ep(ep); + + *REG32(USB_DFIFO0) = *((uint32_t*)buffer); +} + +static void handle_incoming_setup(uint8_t *buf, int size) { + setupData *s = (setupData*)buf; + printf("bmRequestType: 0x%x\n", s->bmRequestType); + printf("bRequest: 0x%x\n", s->bRequest); + printf("wValue: 0x%x\n", s->wValue); + printf("wIndex: 0x%x\n", s->wIndex); + printf("wLength: 0x%x\n", s->wLength); + if ((s->bmRequestType == 0xc0) && (s->wLength == 0x4)) { + uint32_t a = 0x42; + ep_write_in_reply(0, &a, 4); + return; + } + if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { + endpoint_control *ep = GET_IN(0); + dump_endpoint(ep, true); + ack_ep(ep); + fileServerRequest req; + memset(&req, 0, sizeof(req)); + req.cmd = 2; + int fullPackets = sizeof(req) / 64; + int partialPacket = sizeof(req) - (fullPackets*64); + int packets = fullPackets + ((partialPacket == 0) ? 0 : 1); + int words = ROUNDUP(sizeof(req),4)/4; + printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacket, packets, words); + + uint32_t x = (3 << 29) | (packets<<19) | sizeof(req); + printf("size is 0x%x\n", x); + ep->size = x; + + for (int packetNr = 0; packetNr < packets; packetNr++) { + ep->control = (1<<31) | // endpoint enable + (1<<26) | // clear nak + (1 << 22) | // fifo# + (1 << 15) | // USB active endpoint + (0 & 0x3); // max packet size + dump_endpoint(ep, true); + ack_ep(ep); + + uint32_t *packet = (uint32_t*)&req; + int start = packetNr * (64/4); + for (int i = start; i < MIN(start+16, words); i++) { + *REG32(USB_DFIFO1) = packet[i]; + printf("%d: posted 0x%x to fifo\n", i, packet[i]); + } + + dump_endpoint(ep, true); + ack_ep(ep); + udelay(5); + } + } +} + +static void dump_endpoint(endpoint_control *ep, bool in) { + if (ep->control) { + uint32_t ctl = ep->control; + printf(" CTL: 0x%08x\n", ctl); + if ((ctl >> 15) & 1) puts(" Active"); + if ((ctl >> 17) & 1) puts(" NAK'ing"); + if ((ctl >> 31) & 1) puts(" Enabled"); + uint32_t irq = ep->interrupt; + printf(" INT: 0x%08x\n", irq); + if (irq & 1) puts(" XFERCOMPL"); + if ((irq >> 4) & 1) puts(" INTKNTXFEMP IN Token Received When TxFIFO is Empty"); + if ((irq >> 6) & 1) puts(" INEPNAKEFF IN Endpoint NAK Effective"); + if ((irq >> 13) & 1) puts(" NAKINTRPT NAK Interrupt"); + if (in) { + if ((irq >> 3) & 1) puts(" TIMEOUT"); + if ((irq >> 7) & 1) puts(" TX FIFO empty"); + } else { + if ((irq >> 3) & 1) puts(" SETUP"); + } + printf(" TSIZ: 0x%08x\n", ep->size); + printf(" TXFSTS: 0x%08x\n", ep->fifo_status); + } +} + +static void ack_ep(endpoint_control *ep) { + uint32_t irq = ep->interrupt; + ep->interrupt = irq; + printf("ACK'd interrupt 0x%x\n", irq); +} + +static void dwc_check_interrupt(void) { + uint32_t interrupt_status = *REG32(USB_GINTSTS); + while (interrupt_status & USB_GINTSTS_RXFLVL) { + uint32_t receive_status = *REG32(USB_GRXSTSP); + printf("USB_GRXSTSP:\t 0x%x\n", receive_status); + printf(" CHEPNUM: %d\n", receive_status & 0xf); + int packet_size = (receive_status >> 4) & 0x7ff; + printf(" BCNT: %d\n", packet_size); + printf(" DPID: %d\n", (receive_status >> 15) & 0x3); + int packet_status = (receive_status >> 17) & 0xf; + printf(" PKTSTS: %d %s\n", packet_status, packet_status_names[packet_status]); + printf(" FN: %d\n", (receive_status >> 21) & 0xf); + + int words = ROUNDUP(packet_size, 4) / 4; + uint32_t *dest = (uint32_t*)packet_buffer; + for (int i=0; i> i) & 1) { + printf("IN %d irq\n", i); + ep = GET_IN(i); + dump_endpoint(ep, true); + uint32_t irq = ep->interrupt; + printf("acking irq bits 0x%x\n", irq); + ep->interrupt = irq; + } + } + for (int i=16; i<32; i++) { + if ((daint >> i) & 1) { + ep = (endpoint_control*)((USB_BASE + 0x0b00) + (i-16) * 0x20); + printf("OUT %d irq\n", i - 16); + dump_endpoint(ep, false); + uint32_t irq = ep->interrupt; + printf("acking irq bits 0x%x\n", irq); + ep->interrupt = irq; + } + } + } +} + +static int cmd_dwc_dump(int argc, const cmd_args *argv) { + uint32_t t; + endpoint_control *ep = 0; + + dumpreg(USB_GAHBCFG); + dumpreg(USB_GINTSTS); + printf(" CURMOD: %d\n", t & 1); + printf(" MODEMIS: %d\n", (t >> 1) & 1); + printf(" OTGINT: %d\n", (t >> 2) & 1); + printf(" SOF: %d\n", (t >> 3) & 1); + printf(" RXFLVL: %d\n", (t >> 4) & 1); + printf(" NPTXFEMP: %d\n", (t >> 5) & 1); + printf(" GINNAKEFF: %d\n", (t >> 6) & 1); + printf(" GOUTNAKEFF: %d\n", (t >> 7) & 1); + printf(" unused: %d\n", (t >> 8) & 0x3); + printf(" ERLYSUSP: %d\n", (t >> 10) & 1); + printf(" USBSUSP: %d\n", (t >> 11) & 1); + printf(" USBRST: %d\n", (t >> 12) & 1); + printf(" ENUMDONE: %d\n", (t >> 13) & 1); + printf(" ISOOUTDROP: %d\n", (t >> 14) & 1); + printf(" EOPF: %d\n", (t >> 15) & 1); + printf(" unparsed: %d\n", (t >> 16) & 0xffff); + dumpreg(USB_DCFG); + dumpreg(USB_DAINT); + for (int i=0; i<16; i++) { + printf("IN%d\n", i); + ep = (endpoint_control*)((USB_BASE + 0x0900) + i * 0x20); + dump_endpoint(ep, true); + } + for (int i=0; i<16; i++) { + printf("OUT%d\n", i); + ep = (endpoint_control*)((USB_BASE + 0x0b00) + i * 0x20); + dump_endpoint(ep, false); + } + return 0; +} + +static enum handler_return dwc2_poller(struct timer *unused1, unsigned int unused2, void *unused3) { + dwc_check_interrupt(); + return INT_NO_RESCHEDULE; +} + +static void dwc2_init(const struct app_descriptor *app) { + timer_initialize(&dwc2_poll); +} + +static void dwc2_entry(const struct app_descriptor *app, void *args) { + timer_set_periodic(&dwc2_poll, 100, dwc2_poller, NULL); +} + +APP_START(dwc2) + .init = dwc2_init, + .entry = dwc2_entry, +APP_END diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 63ce8739c0..9f643c7864 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -3,27 +3,9 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) WITH_SMP := 1 +#SMP_MAX_CPUS ?= 1 #LK_HEAP_IMPLEMENTATION ?= dlmalloc -# 1st pass to set arch -ifeq ($(TARGET),rpi1) - ARCH := arm - ARM_CPU := arm1176jzf-s - HAVE_ARM_TIMER = 0 -else ifeq ($(TARGET),rpi2) - ARCH := arm - ARM_CPU := cortex-a7 - HAVE_ARM_TIMER = 1 -else ifeq ($(TARGET),rpi3) - ARCH := arm64 - ARM_CPU := cortex-a53 - HAVE_ARM_TIMER = 1 -else ifeq ($(TARGET),rpi3-vpu) - ARCH := vpu -else ifeq ($(TARGET),rpi4-vpu) -endif - - ifeq ($(ARCH),vpu) MODULE_DEPS += platform/bcm28xx/pll ifeq ($(BOOTCODE),1) @@ -61,6 +43,7 @@ endif MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ + $(LOCAL_DIR)/dwc2.c \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/udelay.c \ #$(LOCAL_DIR)/i2c.c \ diff --git a/platform/bcm28xx/start4/rules.mk b/platform/bcm28xx/start4/rules.mk new file mode 100644 index 0000000000..4cf0cce181 --- /dev/null +++ b/platform/bcm28xx/start4/rules.mk @@ -0,0 +1,10 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/start4.c + +EXTRA_LINKER_SCRIPTS += $(LOCAL_DIR)/start4.ld + +include make/module.mk diff --git a/platform/bcm28xx/start4/start4.c b/platform/bcm28xx/start4/start4.c new file mode 100644 index 0000000000..d21034b080 --- /dev/null +++ b/platform/bcm28xx/start4/start4.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +uint32_t bootloader_state[4] __attribute__ ((section(".text.bootloader_state"))) = { 0x41545342, 0, 0, 0 }; + +typedef struct { + char revision[41]; + char type[8]; + char date[16]; + char time[12]; + uint32_t padding; + uint32_t something; + uint32_t serial; + uint32_t something2; +} bver_state; +// the new tryboot flag may appear in BVER + +typedef struct { + uint32_t macend; // 0 + uint32_t macstart; // 4 + uint8_t mac[6]; // 10 + uint8_t pad[2]; // 12 + uint32_t thing1; // 14 + uint16_t thing2; // 18 + uint8_t pad2[2]; // 20 + char serial_str[12];// 22 + uint8_t myip[4]; // 34 + uint32_t pad3[2]; // 38 + uint8_t tftp_ip[4]; // 40 + char prefix[128]; // 44 +} bstn_state; + +typedef struct { + void *vl805hub_addr; + uint32_t vl805hub_size; + void *vl805mcu_addr; + uint32_t vl805mcu_size; + uint32_t bitfield; // bit1 means vl805 eeprom is present + void *buffer; + uint32_t usb_handle; +} busb_state; + +typedef struct { + uint32_t a; + uint32_t b; + uint32_t c; +} bstm_state; + +static void print_bver(bver_state *bver) { + printf("\trevision: %s, type: %s, %s %s, 0x%x, serial: 0x%x something 0x%x\n", bver->revision, bver->type, bver->date, bver->time, bver->something, bver->serial, bver->something2); +} + +static void print_bstn(bstn_state *bstn) { + printf("\tmac1: %08x%08x\n", bstn->macstart, bstn->macend); + printf("\tmac2: %02x:%02x:%02x:%02x:%02x:%02x\n", bstn->mac[0], bstn->mac[1], bstn->mac[2], bstn->mac[3], bstn->mac[4], bstn->mac[5]); + printf("\tserial1: %s\n", bstn->serial_str); + printf("\tmyip: %d.%d.%d.%d\n", bstn->myip[3], bstn->myip[2], bstn->myip[1], bstn->myip[0]); + printf("\ttftp_server: %d.%d.%d.%d\n", bstn->tftp_ip[3], bstn->tftp_ip[2], bstn->tftp_ip[1], bstn->tftp_ip[0]); + printf("\ttftp_prefix: %s\n", bstn->prefix); +} + +static void print_busb(busb_state *busb) { + printf("\tvl805hub: 0x%x + %d\n", busb->vl805hub_addr, busb->vl805hub_size); + printf("\tvl805mcu: 0x%x + %d\n", busb->vl805mcu_addr, busb->vl805mcu_size); + printf("\tbitfield: 0x%x\n", busb->bitfield); + printf("\tbuffer: 0x%x, handle: 0x%x\n", busb->buffer, busb->usb_handle); +} + +static void print_bstm(bstm_state *bstm) { + printf("\tA: 0x%x, B: 0x%x, C: 0x%x\n", bstm->a, bstm->b, bstm->c); + if (bstm->b == 0) puts("\tSD"); + if (bstm->b == 1) puts("\tNET"); + if (bstm->b == 2) puts("\tUSB-MSD"); + if (bstm->b == 3) puts("\tUSB-DEV"); +} + +static char guard(char c) { + if ((c >= ' ') && (c <= '~')) { + return c; + } else { + return '.'; + } +} + +static void print_word(int i, uint32_t w) { + char a,b,c,d; + a = w & 0xff; + b = (w >> 8) & 0xff; + c = (w >> 16) & 0xff; + d = (w >> 24) & 0xff; + a = guard(a); + b = guard(b); + c = guard(c); + d = guard(d); + printf("%d: 0x%x (%c%c%c%c)\n", i, w, a,b,c,d); +} + +static void start4_print_state(uint level) { + printf("ST_CLO: %d\n", *REG32(ST_CLO)); + printf("bootloader state 0x%x 0x%x 0x%x 0x%x\n", bootloader_state[0], bootloader_state[1], bootloader_state[2], bootloader_state[3]); + uint32_t *state = bootloader_state[1]; + if (state) { + puts("some state exists"); + while (true) { + char a,b,c,d; + a = state[0] & 0xff; + b = (state[0] >> 8) & 0xff; + c = (state[0] >> 16) & 0xff; + d = (state[0] >> 24) & 0xff; + printf("TAG 0x%x(%c%c%c%c), 0x%x 0x%x\n", state[0], a,b,c,d, state[1], state[2]); + switch (state[0]) { + case 0x52455642: // BVER + print_bver(&state[3]); + break; + case 0x4e545342: // BSTN + print_bstn(&state[3]); + break; + case 0x42535542: // BUSB + print_busb(&state[3]); + break; + case 0x4d545342: // BSTM + print_bstm(&state[3]); + break; + default: { + uint32_t size = state[2]; + if (size == 0) size = state[1]; + for (int i=3; i < (size/4); i++) { + print_word(i, state[i]); + } + } + } + if (state[2] == 0) break; + state += (state[2]/4); + } + } +} + +LK_INIT_HOOK(start4, &start4_print_state, LK_INIT_LEVEL_APPS); diff --git a/platform/bcm28xx/start4/start4.ld b/platform/bcm28xx/start4/start4.ld new file mode 100644 index 0000000000..7ecf51d69c --- /dev/null +++ b/platform/bcm28xx/start4/start4.ld @@ -0,0 +1,6 @@ +SECTIONS { + .text.bootloader_state : { + *(.text.bootloader_state) + } +} +INSERT AFTER .text; diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk index 5ddfcc3b04..95f5c47d85 100644 --- a/project/rpi3-bootcode.mk +++ b/project/rpi3-bootcode.mk @@ -1,7 +1,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) TARGET := rpi3-vpu -ARCH := vc4 MODULES += \ app/shell \ diff --git a/project/rpi3-start.mk b/project/rpi3-start.mk index 381d0d4a28..65203528b7 100644 --- a/project/rpi3-start.mk +++ b/project/rpi3-start.mk @@ -1,7 +1,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) TARGET := rpi3-vpu -ARCH := vc4 MODULES += \ app/shell \ diff --git a/project/rpi4-recovery.mk b/project/rpi4-recovery.mk index 10bb692d37..3d8f64afa8 100644 --- a/project/rpi4-recovery.mk +++ b/project/rpi4-recovery.mk @@ -1,7 +1,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) TARGET := rpi4-vpu -ARCH := vc4 BOOTCODE := 1 MODULES += \ diff --git a/project/rpi4-start4.mk b/project/rpi4-start4.mk index ce62430aab..32dff7c592 100644 --- a/project/rpi4-start4.mk +++ b/project/rpi4-start4.mk @@ -1,7 +1,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) TARGET := rpi4-vpu -ARCH := vc4 MODULES += \ app/shell \ @@ -11,4 +10,5 @@ MODULES += \ app/stringtests \ app/tests \ platform/bcm28xx/arm_control \ + platform/bcm28xx/dpi \ diff --git a/project/vc4-stage1.mk b/project/vc4-stage1.mk index 446852f5dc..88bc71956a 100644 --- a/project/vc4-stage1.mk +++ b/project/vc4-stage1.mk @@ -1,7 +1,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) TARGET := rpi3-vpu -ARCH := vc4 MODULES += \ app/vc4-stage1 \ diff --git a/project/vc4-stage2.mk b/project/vc4-stage2.mk index 421c3f0ff6..5ebfbdf6b5 100644 --- a/project/vc4-stage2.mk +++ b/project/vc4-stage2.mk @@ -1,11 +1,9 @@ LOCAL_DIR := $(GET_LOCAL_DIR) TARGET := rpi3-vpu -ARCH := vc4 MODULES += \ app/vc4-stage2 \ - app/shell \ platform/bcm28xx/otp \ #lib/debugcommands \ lib/cksum \ diff --git a/target/rpi1/rules.mk b/target/rpi1/rules.mk index 0ae00c435b..9f2922408d 100644 --- a/target/rpi1/rules.mk +++ b/target/rpi1/rules.mk @@ -4,7 +4,9 @@ GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include PLATFORM := bcm28xx -ARCH ?= arm +ARCH := arm +ARM_CPU := arm1176jzf-s +HAVE_ARM_TIMER = 0 GLOBAL_DEFINES += CRYSTAL=19200000 BCM2835=1 diff --git a/target/rpi2/rules.mk b/target/rpi2/rules.mk index 8ad31c0035..14a8b334db 100644 --- a/target/rpi2/rules.mk +++ b/target/rpi2/rules.mk @@ -6,7 +6,9 @@ GLOBAL_INCLUDES += \ PLATFORM := bcm28xx GLOBAL_DEFINES += CRYSTAL=19200000 BCM2836=1 -ARCH ?= arm +ARCH := arm +ARM_CPU := cortex-a7 +HAVE_ARM_TIMER = 1 #include make/module.mk diff --git a/target/rpi3-vpu/rules.mk b/target/rpi3-vpu/rules.mk index d45fc25c36..fefce02e0e 100644 --- a/target/rpi3-vpu/rules.mk +++ b/target/rpi3-vpu/rules.mk @@ -3,10 +3,10 @@ LOCAL_DIR := $(GET_LOCAL_DIR) GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include -GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 CRYSTAL=54000000 +GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 CRYSTAL=19200000 PLATFORM := bcm28xx -ARCH ?= vpu +ARCH := vpu #include make/module.mk diff --git a/target/rpi3/rules.mk b/target/rpi3/rules.mk index c17348e3b1..e2158b124f 100644 --- a/target/rpi3/rules.mk +++ b/target/rpi3/rules.mk @@ -4,7 +4,9 @@ GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include PLATFORM := bcm28xx -ARCH ?= arm64 +ARCH := arm64 +ARM_CPU := cortex-a53 +HAVE_ARM_TIMER = 1 GLOBAL_DEFINES += CRYSTAL=19200000 BCM2837=1 diff --git a/target/rpi4-vpu/rules.mk b/target/rpi4-vpu/rules.mk index e7b77f1f09..c2839c99ae 100644 --- a/target/rpi4-vpu/rules.mk +++ b/target/rpi4-vpu/rules.mk @@ -8,5 +8,10 @@ GLOBAL_DEFINES += TARGET_HAS_DEBUG_LED=1 CRYSTAL=54000000 PLATFORM := bcm28xx ARCH := vpu +ifeq ($(BOOTCODE),1) +else + MODULES += platform/bcm28xx/start4 +endif + #include make/module.mk From 2e4a35f94bfd3bfda498c6b5c44f114a9dd3cd0b Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 27 Nov 2020 06:04:32 -0400 Subject: [PATCH 081/100] the latest code, which works --- arch/vpu/intc.c | 1 + platform/bcm28xx/dwc2.c | 114 +++++++++++++++++++++---------- platform/bcm28xx/rules.mk | 3 +- platform/bcm28xx/start4/start4.c | 1 + 4 files changed, 82 insertions(+), 37 deletions(-) diff --git a/arch/vpu/intc.c b/arch/vpu/intc.c index 0637858bb5..8c6f18a8e3 100644 --- a/arch/vpu/intc.c +++ b/arch/vpu/intc.c @@ -224,6 +224,7 @@ void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { switch (source) { case 64: // timer0 + case 73: // dwc2 case 121: // uart assert(irq_handlers[source - 64].h); ret = irq_handlers[source - 64].h(irq_handlers[source - 64].arg); diff --git a/platform/bcm28xx/dwc2.c b/platform/bcm28xx/dwc2.c index b2c8a95858..1f061a3c53 100644 --- a/platform/bcm28xx/dwc2.c +++ b/platform/bcm28xx/dwc2.c @@ -1,9 +1,10 @@ #include -#include #include #include +#include #include #include +#include #include #include #include @@ -13,7 +14,12 @@ #define USB_GAHBCFG (USB_BASE + 0x0008) #define USB_GINTSTS (USB_BASE + 0x0014) #define USB_GINTSTS_RXFLVL (1 << 4) +#define USB_GINTMSK (USB_BASE + 0x0018) #define USB_GRXSTSP (USB_BASE + 0x0020) +#define USB_GHWCFG1 (USB_BASE + 0x0044) +#define USB_GHWCFG2 (USB_BASE + 0x0048) +#define USB_GHWCFG3 (USB_BASE + 0x004c) +#define USB_GHWCFG4 (USB_BASE + 0x0050) #define USB_DCFG (USB_BASE + 0x0800) #define USB_DAINT (USB_BASE + 0x0818) @@ -39,6 +45,8 @@ #define USB_DFIFO0 (USB_BASE + 0x1000) #define USB_DFIFO1 (USB_BASE + 0x2000) +#define DWC_IRQ 9 + typedef struct { volatile uint32_t control; // 0 uint32_t pad1; // 4 @@ -62,8 +70,6 @@ typedef struct { char name[256]; } fileServerRequest; -timer_t dwc2_poll; - const char *packet_status_names[] = { [1] = "GOUTNAK", [2] = "OUT data packet received", @@ -84,9 +90,14 @@ STATIC_COMMAND_END(dwc); #define dumpreg(reg) { t = *REG32(reg); printf(#reg":\t 0x%x\n", t); } #define GET_IN(epNr) ((endpoint_control*) ((USB_BASE + 0x0900) + (epNr) * 0x20)) +#define GET_OUT(epNr) ((endpoint_control*) ((USB_BASE + 0x0b00) + (epNr) * 0x20)) static uint8_t packet_buffer[4096]; +static void logmsg(const char *msg) { + printf("%4d: %s\n", *REG32(ST_CLO), msg); +} + void ep_write_in_reply(int epNr, void *buffer, int bytes) { int maxPacketSize = 64; int fullPackets = bytes / maxPacketSize; @@ -112,11 +123,11 @@ void ep_write_in_reply(int epNr, void *buffer, int bytes) { static void handle_incoming_setup(uint8_t *buf, int size) { setupData *s = (setupData*)buf; - printf("bmRequestType: 0x%x\n", s->bmRequestType); - printf("bRequest: 0x%x\n", s->bRequest); - printf("wValue: 0x%x\n", s->wValue); - printf("wIndex: 0x%x\n", s->wIndex); - printf("wLength: 0x%x\n", s->wLength); + //printf("bmRequestType: 0x%x\n", s->bmRequestType); + //printf("bRequest: 0x%x\n", s->bRequest); + //printf("wValue: 0x%x\n", s->wValue); + //printf("wIndex: 0x%x\n", s->wIndex); + //printf("wLength: 0x%x\n", s->wLength); if ((s->bmRequestType == 0xc0) && (s->wLength == 0x4)) { uint32_t a = 0x42; ep_write_in_reply(0, &a, 4); @@ -124,7 +135,8 @@ static void handle_incoming_setup(uint8_t *buf, int size) { } if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { endpoint_control *ep = GET_IN(0); - dump_endpoint(ep, true); + endpoint_control *ep_out = GET_OUT(0); + //dump_endpoint(ep, true); ack_ep(ep); fileServerRequest req; memset(&req, 0, sizeof(req)); @@ -133,32 +145,51 @@ static void handle_incoming_setup(uint8_t *buf, int size) { int partialPacket = sizeof(req) - (fullPackets*64); int packets = fullPackets + ((partialPacket == 0) ? 0 : 1); int words = ROUNDUP(sizeof(req),4)/4; - printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacket, packets, words); + //printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacket, packets, words); - uint32_t x = (3 << 29) | (packets<<19) | sizeof(req); - printf("size is 0x%x\n", x); - ep->size = x; + //uint32_t x = (3 << 29) | (packets<<19) | sizeof(req); + //printf("size is 0x%x\n", x); + int bytes_sent = 0; for (int packetNr = 0; packetNr < packets; packetNr++) { + int bytes_this_packet = MIN(64, sizeof(req) - bytes_sent); + //printf("bytes_this_packet: %d\n", bytes_this_packet); + ep->size = (1<<19) | bytes_this_packet; ep->control = (1<<31) | // endpoint enable (1<<26) | // clear nak - (1 << 22) | // fifo# + (0 << 22) | // fifo# (1 << 15) | // USB active endpoint (0 & 0x3); // max packet size - dump_endpoint(ep, true); + // TODO, r/m/w the control and only set enable + //dump_endpoint(ep, true); ack_ep(ep); uint32_t *packet = (uint32_t*)&req; int start = packetNr * (64/4); for (int i = start; i < MIN(start+16, words); i++) { - *REG32(USB_DFIFO1) = packet[i]; - printf("%d: posted 0x%x to fifo\n", i, packet[i]); + *REG32(USB_DFIFO0) = packet[i]; + //printf("%d: posted 0x%x to fifo\n", i, packet[i]); + bytes_sent += 4; } - dump_endpoint(ep, true); + //dump_endpoint(ep, true); ack_ep(ep); udelay(5); } + //puts("setup data IN stage done, on to status OUT..."); + ep->size = (3 << 29); + ep_out->control |= (1<<31) | // enable OUT0 + (1<<26); // clear NAK + + //dump_endpoint(ep, true); + ack_ep(ep); + udelay(5); + //dump_endpoint(ep, true); + ack_ep(ep); + udelay(5); + + //puts("OUT 0"); + //dump_endpoint(ep_out, false); } } @@ -189,20 +220,20 @@ static void dump_endpoint(endpoint_control *ep, bool in) { static void ack_ep(endpoint_control *ep) { uint32_t irq = ep->interrupt; ep->interrupt = irq; - printf("ACK'd interrupt 0x%x\n", irq); + //printf("ACK'd interrupt 0x%x\n", irq); } static void dwc_check_interrupt(void) { uint32_t interrupt_status = *REG32(USB_GINTSTS); while (interrupt_status & USB_GINTSTS_RXFLVL) { uint32_t receive_status = *REG32(USB_GRXSTSP); - printf("USB_GRXSTSP:\t 0x%x\n", receive_status); - printf(" CHEPNUM: %d\n", receive_status & 0xf); + //printf("USB_GRXSTSP:\t 0x%x\n", receive_status); + //printf(" CHEPNUM: %d\n", receive_status & 0xf); int packet_size = (receive_status >> 4) & 0x7ff; - printf(" BCNT: %d\n", packet_size); - printf(" DPID: %d\n", (receive_status >> 15) & 0x3); + //printf(" BCNT: %d\n", packet_size); + //printf(" DPID: %d\n", (receive_status >> 15) & 0x3); int packet_status = (receive_status >> 17) & 0xf; - printf(" PKTSTS: %d %s\n", packet_status, packet_status_names[packet_status]); + //printf(" PKTSTS: %d %s\n", packet_status, packet_status_names[packet_status]); printf(" FN: %d\n", (receive_status >> 21) & 0xf); int words = ROUNDUP(packet_size, 4) / 4; @@ -210,10 +241,10 @@ static void dwc_check_interrupt(void) { for (int i=0; i> i) & 1) { printf("IN %d irq\n", i); ep = GET_IN(i); - dump_endpoint(ep, true); + //dump_endpoint(ep, true); uint32_t irq = ep->interrupt; - printf("acking irq bits 0x%x\n", irq); + //printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; } } @@ -237,9 +268,9 @@ static void dwc_check_interrupt(void) { if ((daint >> i) & 1) { ep = (endpoint_control*)((USB_BASE + 0x0b00) + (i-16) * 0x20); printf("OUT %d irq\n", i - 16); - dump_endpoint(ep, false); + //dump_endpoint(ep, false); uint32_t irq = ep->interrupt; - printf("acking irq bits 0x%x\n", irq); + //printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; } } @@ -268,6 +299,11 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { printf(" ISOOUTDROP: %d\n", (t >> 14) & 1); printf(" EOPF: %d\n", (t >> 15) & 1); printf(" unparsed: %d\n", (t >> 16) & 0xffff); + dumpreg(USB_GINTMSK); + dumpreg(USB_GHWCFG1); + dumpreg(USB_GHWCFG2); + dumpreg(USB_GHWCFG3); + dumpreg(USB_GHWCFG4); dumpreg(USB_DCFG); dumpreg(USB_DAINT); for (int i=0; i<16; i++) { @@ -283,17 +319,25 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { return 0; } -static enum handler_return dwc2_poller(struct timer *unused1, unsigned int unused2, void *unused3) { +static enum handler_return dwc_irq(void *unused) { + lk_bigtime_t start = current_time_hires(); + logmsg("dwc irq"); dwc_check_interrupt(); + lk_bigtime_t end = current_time_hires(); + lk_bigtime_t spent = end - start; + logmsg("done"); + printf("irq time: %lld\n", spent); return INT_NO_RESCHEDULE; } static void dwc2_init(const struct app_descriptor *app) { - timer_initialize(&dwc2_poll); + register_int_handler(DWC_IRQ, dwc_irq, NULL); + unmask_interrupt(DWC_IRQ); + + *REG32(USB_GINTMSK) = (1<<4); } static void dwc2_entry(const struct app_descriptor *app, void *args) { - timer_set_periodic(&dwc2_poll, 100, dwc2_poller, NULL); } APP_START(dwc2) diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 9f643c7864..a850543d46 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -43,9 +43,9 @@ endif MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ - $(LOCAL_DIR)/dwc2.c \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/udelay.c \ + $(LOCAL_DIR)/dwc2.c \ #$(LOCAL_DIR)/i2c.c \ @@ -95,7 +95,6 @@ else ifeq ($(TARGET),rpi4-vpu) MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ $(LOCAL_DIR)/genet.c \ - $(LOCAL_DIR)/udelay.c \ endif diff --git a/platform/bcm28xx/start4/start4.c b/platform/bcm28xx/start4/start4.c index d21034b080..85f61ef204 100644 --- a/platform/bcm28xx/start4/start4.c +++ b/platform/bcm28xx/start4/start4.c @@ -75,6 +75,7 @@ static void print_bstm(bstm_state *bstm) { if (bstm->b == 1) puts("\tNET"); if (bstm->b == 2) puts("\tUSB-MSD"); if (bstm->b == 3) puts("\tUSB-DEV"); + if (bstm->b == 4) puts("\tUSB-BCM-MSD"); } static char guard(char c) { From 4a93a73b7c6778be8fc5df2d87e760260ac226bf Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 7 Dec 2020 13:48:36 -0400 Subject: [PATCH 082/100] saving before mass-delete --- platform/bcm28xx/dwc2.c | 193 +++++++++++++++++++++++++++++++++------- 1 file changed, 163 insertions(+), 30 deletions(-) diff --git a/platform/bcm28xx/dwc2.c b/platform/bcm28xx/dwc2.c index 1f061a3c53..e231580589 100644 --- a/platform/bcm28xx/dwc2.c +++ b/platform/bcm28xx/dwc2.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -21,6 +22,7 @@ #define USB_GHWCFG3 (USB_BASE + 0x004c) #define USB_GHWCFG4 (USB_BASE + 0x0050) #define USB_DCFG (USB_BASE + 0x0800) +#define USB_DIEPMSK (USB_BASE + 0x0810) #define USB_DAINT (USB_BASE + 0x0818) #define USB_DIEPCTL0 (USB_BASE + 0x0900) @@ -70,6 +72,30 @@ typedef struct { char name[256]; } fileServerRequest; +enum usb_stream_type { + USB_STREAM_SETUP +}; + +struct dwc_state_T; + +typedef struct packet_queue_T { + struct packet_queue_T *next; + void *payload; + int payload_size; + int start; + void (*cb)(struct dwc_state_T *, struct packet_queue_T *); +} packet_queue_t; + +typedef struct { + packet_queue_t *packet_queue_head; + packet_queue_t *packet_queue_tail; +} endpoint_t; + +typedef struct { + endpoint_t in[1]; + endpoint_t out[1]; +} dwc_state_t; + const char *packet_status_names[] = { [1] = "GOUTNAK", [2] = "OUT data packet received", @@ -83,6 +109,7 @@ const char *packet_status_names[] = { static int cmd_dwc_dump(int argc, const cmd_args *argv); static void dump_endpoint(endpoint_control *ep, bool in); static void ack_ep(endpoint_control *ep); +void ep_write_in(dwc_state_t *state, int epNr); STATIC_COMMAND_START STATIC_COMMAND("dwc_dump", "dump dwc registers", &cmd_dwc_dump) @@ -98,17 +125,68 @@ static void logmsg(const char *msg) { printf("%4d: %s\n", *REG32(ST_CLO), msg); } -void ep_write_in_reply(int epNr, void *buffer, int bytes) { - int maxPacketSize = 64; +void dwc2_ep_queue_in(dwc_state_t *state, int epNr, void *buffer, int bytes, void (*cb)(dwc_state_t *, packet_queue_t *)) { + assert(epNr <= 0); + packet_queue_t *pkt = malloc(sizeof(packet_queue_t)); + pkt->payload = buffer; + pkt->payload_size = bytes; + pkt->start = 0; + pkt->next = NULL; + pkt->cb = cb; + + uint32_t *data = buffer; + for (int i=0; i<(bytes/4); i++) { + printf("0x%x ", data[i]); + } + puts(""); + + int do_tx = false; + if (state->in[epNr].packet_queue_head == NULL) { + // no pending packets, can tx right away + do_tx = true; + state->in[epNr].packet_queue_head = pkt; + } + if (state->in[epNr].packet_queue_tail) { + state->in[epNr].packet_queue_tail->next = pkt; + } + state->in[epNr].packet_queue_tail = pkt; + if (do_tx) { + ep_write_in(state, epNr); + } +} + +void ep_write_in(dwc_state_t *state, int epNr) { + endpoint_control *ep = GET_IN(epNr); + while (ep->control & (1<<31)) {} + puts("ready"); + int maxPacketSize = 64; // TODO + packet_queue_t *pkt = state->in[epNr].packet_queue_head; + assert(pkt); + printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); + int bytes = pkt->payload_size - pkt->start; + if (bytes == 0) { + puts("packet sent"); + pkt->cb(state, pkt); + packet_queue_t *next = pkt->next; + state->in[epNr].packet_queue_head = next; + if (state->in[epNr].packet_queue_tail == pkt) state->in[epNr].packet_queue_tail = NULL; + if (next) return ep_write_in(state, epNr); + return; + } + assert(bytes > 0); int fullPackets = bytes / maxPacketSize; int partialPacketSize = bytes - (fullPackets*maxPacketSize); int packets = fullPackets + ((partialPacketSize==0) ? 0 : 1); int words = ROUNDUP(bytes,4)/4; printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); + if (epNr == 0) { + packets = 1; + bytes = MIN(maxPacketSize, bytes); + printf("capped to 1 packet of %d bytes\n", bytes); + } uint32_t x = (3 << 29) | (packets<<19) | bytes; printf("size is 0x%x\n", x); - endpoint_control *ep = GET_IN(epNr); ep->size = x; ep->control = (1<<31) | // endpoint enable (1 << 26) | // clear nak @@ -116,31 +194,65 @@ void ep_write_in_reply(int epNr, void *buffer, int bytes) { (1 << 15) | // USB active endpoint (0 & 0x3); // max packet size dump_endpoint(ep, true); - ack_ep(ep); + //ack_ep(ep); + + uint32_t *packet = (uint32_t*)(pkt->payload + pkt->start); + printf("packet: 0x%x\n", (uint32_t)packet); + int bytes_sent = 0; + for (int i = 0; i < MIN(maxPacketSize/4, words); i++) { + *REG32(USB_DFIFO0) = packet[i]; + //printf("%d(0x%x): posted 0x%x to fifo\n", i, &packet[i], packet[i]); + bytes_sent += 4; + } + pkt->start += bytes_sent; + printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); +} - *REG32(USB_DFIFO0) = *((uint32_t*)buffer); +static fileServerRequest req; // TODO, put on heap + +static void handle_setup_status_out(dwc_state_t *state, packet_queue_t *pkt) { + endpoint_control *ep_in = GET_IN(0); + endpoint_control *ep_out = GET_OUT(0); + puts("setup data IN stage done, on to status OUT..."); + ep_in->size = (3 << 29); + + //puts("\nOUT 0"); + //dump_endpoint(ep_out, false); + ep_out->control |= (1<<31) | // enable OUT0 + (1<<26); // clear NAK + + //puts("IN 0"); + //dump_endpoint(ep, true); + ack_ep(ep_in); + //udelay(5); + //puts("\nIN 0"); + //dump_endpoint(ep, true); + ack_ep(ep_in); + //udelay(5); + + //puts("\nOUT 0"); + //dump_endpoint(ep_out, false); + ack_ep(ep_out); + //dump_endpoint(ep_out, false); } -static void handle_incoming_setup(uint8_t *buf, int size) { +static void handle_incoming_setup(dwc_state_t *state, uint8_t *buf, int size) { setupData *s = (setupData*)buf; //printf("bmRequestType: 0x%x\n", s->bmRequestType); //printf("bRequest: 0x%x\n", s->bRequest); //printf("wValue: 0x%x\n", s->wValue); //printf("wIndex: 0x%x\n", s->wIndex); //printf("wLength: 0x%x\n", s->wLength); - if ((s->bmRequestType == 0xc0) && (s->wLength == 0x4)) { - uint32_t a = 0x42; - ep_write_in_reply(0, &a, 4); - return; - } if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { endpoint_control *ep = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); //dump_endpoint(ep, true); ack_ep(ep); - fileServerRequest req; + ack_ep(ep_out); memset(&req, 0, sizeof(req)); req.cmd = 2; + dwc2_ep_queue_in(state, 0, &req, sizeof(req), &handle_setup_status_out); + return; int fullPackets = sizeof(req) / 64; int partialPacket = sizeof(req) - (fullPackets*64); int packets = fullPackets + ((partialPacket == 0) ? 0 : 1); @@ -173,22 +285,32 @@ static void handle_incoming_setup(uint8_t *buf, int size) { } //dump_endpoint(ep, true); + //int t_0 = *REG32(ST_CLO); + while (ep->control & (1<<31)) {} ack_ep(ep); - udelay(5); + //int t_1 = *REG32(ST_CLO); + //printf("waited %d usec and read %d times\n", t_1 - t_0, cycles); } //puts("setup data IN stage done, on to status OUT..."); ep->size = (3 << 29); + + //puts("\nOUT 0"); + //dump_endpoint(ep_out, false); ep_out->control |= (1<<31) | // enable OUT0 (1<<26); // clear NAK + //puts("IN 0"); //dump_endpoint(ep, true); ack_ep(ep); - udelay(5); + //udelay(5); + //puts("\nIN 0"); //dump_endpoint(ep, true); ack_ep(ep); - udelay(5); + //udelay(5); - //puts("OUT 0"); + //puts("\nOUT 0"); + //dump_endpoint(ep_out, false); + ack_ep(ep_out); //dump_endpoint(ep_out, false); } } @@ -223,7 +345,7 @@ static void ack_ep(endpoint_control *ep) { //printf("ACK'd interrupt 0x%x\n", irq); } -static void dwc_check_interrupt(void) { +static void dwc_check_interrupt(dwc_state_t *state) { uint32_t interrupt_status = *REG32(USB_GINTSTS); while (interrupt_status & USB_GINTSTS_RXFLVL) { uint32_t receive_status = *REG32(USB_GRXSTSP); @@ -234,7 +356,7 @@ static void dwc_check_interrupt(void) { //printf(" DPID: %d\n", (receive_status >> 15) & 0x3); int packet_status = (receive_status >> 17) & 0xf; //printf(" PKTSTS: %d %s\n", packet_status, packet_status_names[packet_status]); - printf(" FN: %d\n", (receive_status >> 21) & 0xf); + //printf(" FN: %d\n", (receive_status >> 21) & 0xf); int words = ROUNDUP(packet_size, 4) / 4; uint32_t *dest = (uint32_t*)packet_buffer; @@ -246,34 +368,40 @@ static void dwc_check_interrupt(void) { //} //puts(""); if (packet_status == 4) { - handle_incoming_setup(packet_buffer, packet_size); + handle_incoming_setup(state, packet_buffer, packet_size); } interrupt_status = *REG32(USB_GINTSTS); } + logmsg("."); uint32_t daint = *REG32(USB_DAINT); endpoint_control *ep = 0; - if (daint != 0) { + while (daint != 0) { + printf("DAINT: 0x%x\n", daint); for (int i=0; i<16; i++) { if ((daint >> i) & 1) { printf("IN %d irq\n", i); ep = GET_IN(i); - //dump_endpoint(ep, true); + dump_endpoint(ep, true); uint32_t irq = ep->interrupt; - //printf("acking irq bits 0x%x\n", irq); + printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; + if (irq & 1) { + ep_write_in(state, i); + } } } for (int i=16; i<32; i++) { if ((daint >> i) & 1) { ep = (endpoint_control*)((USB_BASE + 0x0b00) + (i-16) * 0x20); printf("OUT %d irq\n", i - 16); - //dump_endpoint(ep, false); + dump_endpoint(ep, false); uint32_t irq = ep->interrupt; - //printf("acking irq bits 0x%x\n", irq); + printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; } } + daint = *REG32(USB_DAINT); } } @@ -304,14 +432,15 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { dumpreg(USB_GHWCFG2); dumpreg(USB_GHWCFG3); dumpreg(USB_GHWCFG4); - dumpreg(USB_DCFG); + dumpreg(USB_DCFG); // 800 + dumpreg(USB_DIEPMSK); // 810 dumpreg(USB_DAINT); - for (int i=0; i<16; i++) { + for (int i=0; i<3; i++) { printf("IN%d\n", i); ep = (endpoint_control*)((USB_BASE + 0x0900) + i * 0x20); dump_endpoint(ep, true); } - for (int i=0; i<16; i++) { + for (int i=0; i<3; i++) { printf("OUT%d\n", i); ep = (endpoint_control*)((USB_BASE + 0x0b00) + i * 0x20); dump_endpoint(ep, false); @@ -319,10 +448,10 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { return 0; } -static enum handler_return dwc_irq(void *unused) { +static enum handler_return dwc_irq(dwc_state_t *state) { lk_bigtime_t start = current_time_hires(); logmsg("dwc irq"); - dwc_check_interrupt(); + dwc_check_interrupt(state); lk_bigtime_t end = current_time_hires(); lk_bigtime_t spent = end - start; logmsg("done"); @@ -330,11 +459,15 @@ static enum handler_return dwc_irq(void *unused) { return INT_NO_RESCHEDULE; } +static dwc_state_t dwc_state; + static void dwc2_init(const struct app_descriptor *app) { - register_int_handler(DWC_IRQ, dwc_irq, NULL); + memset(&dwc_state, 0, sizeof(dwc_state)); + register_int_handler(DWC_IRQ, dwc_irq, &dwc_state); unmask_interrupt(DWC_IRQ); *REG32(USB_GINTMSK) = (1<<4); + *REG32(USB_DIEPMSK) = (1<<4) | (1<<3) | (1<<0); } static void dwc2_entry(const struct app_descriptor *app, void *args) { From 43f9cf27d735fc5c918bb20994cf9ef59f1d5b85 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 7 Dec 2020 18:03:04 -0400 Subject: [PATCH 083/100] cleanup of many things, including dwc2 gadget driver --- arch/vpu/start.S | 2 +- platform/bcm28xx/dwc2.c | 109 ++++---------------- platform/bcm28xx/include/platform/bcm28xx.h | 4 + platform/bcm28xx/intc.c | 7 +- platform/bcm28xx/platform.c | 23 ++--- platform/bcm28xx/pll/pll_control.c | 2 +- platform/bcm28xx/pll/pll_read.c | 6 +- platform/bcm28xx/rules.mk | 2 +- platform/bcm28xx/start4/start4.c | 4 + platform/bcm28xx/start4/start4.ld | 3 + project/rpi3-bootcode.mk | 2 +- 11 files changed, 49 insertions(+), 115 deletions(-) diff --git a/arch/vpu/start.S b/arch/vpu/start.S index cbdb2b0bf1..b81d1a621d 100644 --- a/arch/vpu/start.S +++ b/arch/vpu/start.S @@ -59,7 +59,7 @@ manual_uart_cfg: mov r1, 0x00004000 st r1, (r0) mov r0, 0x7e1010f4 // CM_UARTDIV - //mov r1, 0x5a003900 19.2mhz divisor + //mov r1, 0x5a003900 //19.2mhz divisor mov r1, 0x5a00a050 // 54mhz divisor st r1, (r0) mov r0, 0x7e1010f0 // CM_UARTCTL diff --git a/platform/bcm28xx/dwc2.c b/platform/bcm28xx/dwc2.c index e231580589..7c5536e155 100644 --- a/platform/bcm28xx/dwc2.c +++ b/platform/bcm28xx/dwc2.c @@ -134,12 +134,6 @@ void dwc2_ep_queue_in(dwc_state_t *state, int epNr, void *buffer, int bytes, voi pkt->next = NULL; pkt->cb = cb; - uint32_t *data = buffer; - for (int i=0; i<(bytes/4); i++) { - printf("0x%x ", data[i]); - } - puts(""); - int do_tx = false; if (state->in[epNr].packet_queue_head == NULL) { // no pending packets, can tx right away @@ -158,18 +152,19 @@ void dwc2_ep_queue_in(dwc_state_t *state, int epNr, void *buffer, int bytes, voi void ep_write_in(dwc_state_t *state, int epNr) { endpoint_control *ep = GET_IN(epNr); while (ep->control & (1<<31)) {} - puts("ready"); + //puts("ready"); int maxPacketSize = 64; // TODO packet_queue_t *pkt = state->in[epNr].packet_queue_head; assert(pkt); - printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); + //printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); int bytes = pkt->payload_size - pkt->start; if (bytes == 0) { - puts("packet sent"); + //puts("packet sent"); pkt->cb(state, pkt); packet_queue_t *next = pkt->next; state->in[epNr].packet_queue_head = next; if (state->in[epNr].packet_queue_tail == pkt) state->in[epNr].packet_queue_tail = NULL; + free(pkt); if (next) return ep_write_in(state, epNr); return; } @@ -178,14 +173,14 @@ void ep_write_in(dwc_state_t *state, int epNr) { int partialPacketSize = bytes - (fullPackets*maxPacketSize); int packets = fullPackets + ((partialPacketSize==0) ? 0 : 1); int words = ROUNDUP(bytes,4)/4; - printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); + //printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); if (epNr == 0) { packets = 1; bytes = MIN(maxPacketSize, bytes); - printf("capped to 1 packet of %d bytes\n", bytes); + //printf("capped to 1 packet of %d bytes\n", bytes); } uint32_t x = (3 << 29) | (packets<<19) | bytes; - printf("size is 0x%x\n", x); + //printf("size is 0x%x\n", x); ep->size = x; ep->control = (1<<31) | // endpoint enable @@ -193,11 +188,10 @@ void ep_write_in(dwc_state_t *state, int epNr) { (0 << 22) | // fifo# (1 << 15) | // USB active endpoint (0 & 0x3); // max packet size - dump_endpoint(ep, true); + //dump_endpoint(ep, true); //ack_ep(ep); uint32_t *packet = (uint32_t*)(pkt->payload + pkt->start); - printf("packet: 0x%x\n", (uint32_t)packet); int bytes_sent = 0; for (int i = 0; i < MIN(maxPacketSize/4, words); i++) { *REG32(USB_DFIFO0) = packet[i]; @@ -205,7 +199,7 @@ void ep_write_in(dwc_state_t *state, int epNr) { bytes_sent += 4; } pkt->start += bytes_sent; - printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); + //printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); } static fileServerRequest req; // TODO, put on heap @@ -213,7 +207,7 @@ static fileServerRequest req; // TODO, put on heap static void handle_setup_status_out(dwc_state_t *state, packet_queue_t *pkt) { endpoint_control *ep_in = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); - puts("setup data IN stage done, on to status OUT..."); + //puts("setup data IN stage done, on to status OUT..."); ep_in->size = (3 << 29); //puts("\nOUT 0"); @@ -244,74 +238,14 @@ static void handle_incoming_setup(dwc_state_t *state, uint8_t *buf, int size) { //printf("wIndex: 0x%x\n", s->wIndex); //printf("wLength: 0x%x\n", s->wLength); if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { - endpoint_control *ep = GET_IN(0); + endpoint_control *ep_in = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); //dump_endpoint(ep, true); - ack_ep(ep); + ack_ep(ep_in); ack_ep(ep_out); memset(&req, 0, sizeof(req)); req.cmd = 2; dwc2_ep_queue_in(state, 0, &req, sizeof(req), &handle_setup_status_out); - return; - int fullPackets = sizeof(req) / 64; - int partialPacket = sizeof(req) - (fullPackets*64); - int packets = fullPackets + ((partialPacket == 0) ? 0 : 1); - int words = ROUNDUP(sizeof(req),4)/4; - //printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacket, packets, words); - - //uint32_t x = (3 << 29) | (packets<<19) | sizeof(req); - //printf("size is 0x%x\n", x); - - int bytes_sent = 0; - for (int packetNr = 0; packetNr < packets; packetNr++) { - int bytes_this_packet = MIN(64, sizeof(req) - bytes_sent); - //printf("bytes_this_packet: %d\n", bytes_this_packet); - ep->size = (1<<19) | bytes_this_packet; - ep->control = (1<<31) | // endpoint enable - (1<<26) | // clear nak - (0 << 22) | // fifo# - (1 << 15) | // USB active endpoint - (0 & 0x3); // max packet size - // TODO, r/m/w the control and only set enable - //dump_endpoint(ep, true); - ack_ep(ep); - - uint32_t *packet = (uint32_t*)&req; - int start = packetNr * (64/4); - for (int i = start; i < MIN(start+16, words); i++) { - *REG32(USB_DFIFO0) = packet[i]; - //printf("%d: posted 0x%x to fifo\n", i, packet[i]); - bytes_sent += 4; - } - - //dump_endpoint(ep, true); - //int t_0 = *REG32(ST_CLO); - while (ep->control & (1<<31)) {} - ack_ep(ep); - //int t_1 = *REG32(ST_CLO); - //printf("waited %d usec and read %d times\n", t_1 - t_0, cycles); - } - //puts("setup data IN stage done, on to status OUT..."); - ep->size = (3 << 29); - - //puts("\nOUT 0"); - //dump_endpoint(ep_out, false); - ep_out->control |= (1<<31) | // enable OUT0 - (1<<26); // clear NAK - - //puts("IN 0"); - //dump_endpoint(ep, true); - ack_ep(ep); - //udelay(5); - //puts("\nIN 0"); - //dump_endpoint(ep, true); - ack_ep(ep); - //udelay(5); - - //puts("\nOUT 0"); - //dump_endpoint(ep_out, false); - ack_ep(ep_out); - //dump_endpoint(ep_out, false); } } @@ -373,18 +307,17 @@ static void dwc_check_interrupt(dwc_state_t *state) { interrupt_status = *REG32(USB_GINTSTS); } - logmsg("."); uint32_t daint = *REG32(USB_DAINT); endpoint_control *ep = 0; while (daint != 0) { - printf("DAINT: 0x%x\n", daint); + //printf("DAINT: 0x%x\n", daint); for (int i=0; i<16; i++) { if ((daint >> i) & 1) { - printf("IN %d irq\n", i); + //printf("IN %d irq\n", i); ep = GET_IN(i); - dump_endpoint(ep, true); + //dump_endpoint(ep, true); uint32_t irq = ep->interrupt; - printf("acking irq bits 0x%x\n", irq); + //printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; if (irq & 1) { ep_write_in(state, i); @@ -394,10 +327,10 @@ static void dwc_check_interrupt(dwc_state_t *state) { for (int i=16; i<32; i++) { if ((daint >> i) & 1) { ep = (endpoint_control*)((USB_BASE + 0x0b00) + (i-16) * 0x20); - printf("OUT %d irq\n", i - 16); - dump_endpoint(ep, false); + //printf("OUT %d irq\n", i - 16); + //dump_endpoint(ep, false); uint32_t irq = ep->interrupt; - printf("acking irq bits 0x%x\n", irq); + //printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; } } @@ -450,11 +383,11 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { static enum handler_return dwc_irq(dwc_state_t *state) { lk_bigtime_t start = current_time_hires(); - logmsg("dwc irq"); + //logmsg("dwc irq"); dwc_check_interrupt(state); lk_bigtime_t end = current_time_hires(); lk_bigtime_t spent = end - start; - logmsg("done"); + //logmsg("done"); printf("irq time: %lld\n", spent); return INT_NO_RESCHEDULE; } diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index d441cb7177..be73696e1c 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -63,9 +63,13 @@ void print_timestamp(void); #define SMI_BASE (BCM_PERIPH_BASE_VIRT + 0x600000) #define BSC1_BASE (BCM_PERIPH_BASE_VIRT + 0x804000) #define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) +#define SD_BASE (BCM_PERIPH_BASE_VIRT + 0xe00000) #define GENET_BASE (0x7d580000) // TODO, this is before the normal BCM_PERIPH_BASE_VIRT bank #define MCORE_BASE (BCM_PERIPH_BASE_VIRT + 0x0000) +#define SD_IDL (SD_BASE + 0x18) +#define SD_CYC (SD_BASE + 0x30) + #define ST_CS (ST_BASE + 0x0) #define ST_CLO (ST_BASE + 0x4) #define ST_CHI (ST_BASE + 0x8) diff --git a/platform/bcm28xx/intc.c b/platform/bcm28xx/intc.c index 6dacff5ca9..464fc3096c 100644 --- a/platform/bcm28xx/intc.c +++ b/platform/bcm28xx/intc.c @@ -16,15 +16,12 @@ #include #include -#if defined(BCM2836) || defined(BCM2835) +#if ARCH_ARM #include typedef struct arm_iframe arm_platform_iframe_t; -#elif defined (BCM2837) +#elif ARCH_ARM64 #include typedef struct arm64_iframe_long arm_platform_iframe_t; -#elif defined BCM2XXX_VPU -#else - #error Unknown BCM28XX Variant #endif diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 90b7d5fdf6..1ee1db7251 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -106,6 +106,8 @@ extern void intc_init(void); extern void arm_reset(void); static void switch_vpu_to_pllc(void); +// 19.2mhz for most models +// 54mhz for rpi4 uint32_t xtal_freq = CRYSTAL; #ifdef WITH_KERNEL_VM @@ -130,15 +132,15 @@ static void switch_vpu_to_pllc() { setup_pllc( 2000LL * 1000 * 1000); - int vpu_divisor = 2; + int vpu_divisor = 1; *REG32(CM_VPUCTL) = CM_PASSWORD | CM_VPUCTL_FRAC_SET | CM_SRC_OSC | CM_VPUCTL_GATE_SET; *REG32(CM_VPUDIV) = CM_PASSWORD | (vpu_divisor << 12); *REG32(CM_VPUCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET; *REG32(CM_VPUCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0 | CM_VPUCTL_GATE_SET | 0x10; /* ENAB */ - *REG32(CM_TIMERDIV) = CM_PASSWORD | (19 << 12) | 819; // TODO, look into this timer - *REG32(CM_TIMERCTL) = CM_PASSWORD | CM_SRC_OSC | 0x10; + //*REG32(CM_TIMERDIV) = CM_PASSWORD | (19 << 12) | 819; // TODO, look into this timer + //*REG32(CM_TIMERCTL) = CM_PASSWORD | CM_SRC_OSC | 0x10; int vpu = measure_clock(5); int pllc_core0 = vpu*vpu_divisor; @@ -149,17 +151,14 @@ static void switch_vpu_to_pllc() { } void platform_early_init(void) { - // 19.2mhz for most models - // 54mhz for rpi4 - xtal_freq = CRYSTAL; uart_init_early(); intc_init(); #ifdef ARCH_VPU - if (xtal_freq == 19200000) { + //if (xtal_freq == 19200000) { switch_vpu_to_pllc(); - } + //} #endif #if BCM2835 @@ -250,13 +249,6 @@ void platform_early_init(void) { } void platform_init(void) { -#ifdef ARCH_VPU - uint32_t r28, sp; - __asm__ volatile ("mov %0, r28" : "=r"(r28)); - __asm__ volatile ("mov %0, sp" : "=r"(sp)); - dprintf(INFO, "platform_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); -#endif - #if BCM2835 == 1 gpio_config(0, 1); #endif @@ -268,6 +260,7 @@ void platform_init(void) { #if BCM2837 init_framebuffer(); #endif + printf("crystal is %f MHz\n", (float)xtal_freq/1000/1000); } void platform_dputc(char c) { diff --git a/platform/bcm28xx/pll/pll_control.c b/platform/bcm28xx/pll/pll_control.c index 99b3f4af7a..a90be8d50a 100644 --- a/platform/bcm28xx/pll/pll_control.c +++ b/platform/bcm28xx/pll/pll_control.c @@ -489,7 +489,7 @@ void switch_vpu_to_src(int src) { void setup_pllc(uint64_t target_freq) { int pdiv = 1; uint64_t xtal_in = xtal_freq; - uint64_t goal_freq = target_freq / 2; + uint64_t goal_freq = target_freq / 1; uint64_t divisor = (goal_freq<<20) / xtal_in; int div = divisor >> 20; int frac = divisor & 0xfffff; diff --git a/platform/bcm28xx/pll/pll_read.c b/platform/bcm28xx/pll/pll_read.c index 324d74551b..acbc00bd4f 100644 --- a/platform/bcm28xx/pll/pll_read.c +++ b/platform/bcm28xx/pll/pll_read.c @@ -120,8 +120,8 @@ static int cmd_pll_dump(int argc, const cmd_args *argv) { if (freq > 0) { enum pll_chan pll_chan; for (pll_chan = 0; pll_chan < PLL_CHAN_NUM; ++pll_chan) - if (pll_chan_def[pll_chan].pll == pll) - dump_pll_chan_state(pll_chan); + if (pll_chan_def[pll_chan].pll == pll) + dump_pll_chan_state(pll_chan); } } @@ -153,7 +153,7 @@ int measure_clock(int mux) { return count * divisor; } -const char *clock_names[] = { +static const char *clock_names[] = { [1] = "H264", [2] = "ISP", [3] = "SDRAM", diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index a850543d46..ae48ad24f6 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -45,6 +45,7 @@ MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/udelay.c \ + $(LOCAL_DIR)/print_timestamp.c \ $(LOCAL_DIR)/dwc2.c \ #$(LOCAL_DIR)/i2c.c \ @@ -85,7 +86,6 @@ else ifeq ($(TARGET),rpi3-vpu) MODULE_SRCS += \ $(LOCAL_DIR)/uart.c \ - $(LOCAL_DIR)/print_timestamp.c \ MODULES += platform/bcm28xx/sdhost diff --git a/platform/bcm28xx/start4/start4.c b/platform/bcm28xx/start4/start4.c index 85f61ef204..e8ce2f18e1 100644 --- a/platform/bcm28xx/start4/start4.c +++ b/platform/bcm28xx/start4/start4.c @@ -5,6 +5,10 @@ #include uint32_t bootloader_state[4] __attribute__ ((section(".text.bootloader_state"))) = { 0x41545342, 0, 0, 0 }; +// bit 0 declares support for a certain cpuid on the VPU +// bit 1 is pi400 flag? +// pi400 booting over usb-dev requires both bit0 and bit1 +uint32_t firmware_rev[4] __attribute__ ((section(".text.firmware_rev"))) = { 0x3, 0, 0, 0 }; typedef struct { char revision[41]; diff --git a/platform/bcm28xx/start4/start4.ld b/platform/bcm28xx/start4/start4.ld index 7ecf51d69c..c174f1ee8a 100644 --- a/platform/bcm28xx/start4/start4.ld +++ b/platform/bcm28xx/start4/start4.ld @@ -2,5 +2,8 @@ SECTIONS { .text.bootloader_state : { *(.text.bootloader_state) } + .text.firmware_rev : { + *(.text.firmware_rev) + } } INSERT AFTER .text; diff --git a/project/rpi3-bootcode.mk b/project/rpi3-bootcode.mk index 95f5c47d85..540a8e3863 100644 --- a/project/rpi3-bootcode.mk +++ b/project/rpi3-bootcode.mk @@ -5,8 +5,8 @@ TARGET := rpi3-vpu MODULES += \ app/shell \ platform/bcm28xx/rpi-ddr2/autoram \ + platform/bcm28xx/otp \ #platform/bcm28xx/dpi \ - #platform/bcm28xx/otp \ #lib/debugcommands \ #app/shell \ #app/tests \ From 800027b86ad1b863c88b5799aa3b24edb0e61739 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 8 Jan 2021 03:09:36 -0400 Subject: [PATCH 084/100] move dwc code to its own module, it currently crashes on boot if the bootloader hasnt initialized things --- platform/bcm28xx/{ => dwc2}/dwc2.c | 118 ++++++++++++++++++++++------- platform/bcm28xx/dwc2/rules.mk | 11 +++ platform/bcm28xx/rules.mk | 1 - 3 files changed, 103 insertions(+), 27 deletions(-) rename platform/bcm28xx/{ => dwc2}/dwc2.c (77%) create mode 100644 platform/bcm28xx/dwc2/rules.mk diff --git a/platform/bcm28xx/dwc2.c b/platform/bcm28xx/dwc2/dwc2.c similarity index 77% rename from platform/bcm28xx/dwc2.c rename to platform/bcm28xx/dwc2/dwc2.c index 7c5536e155..099d5c7346 100644 --- a/platform/bcm28xx/dwc2.c +++ b/platform/bcm28xx/dwc2/dwc2.c @@ -76,14 +76,14 @@ enum usb_stream_type { USB_STREAM_SETUP }; -struct dwc_state_T; +struct dwc_state_t; typedef struct packet_queue_T { struct packet_queue_T *next; void *payload; int payload_size; int start; - void (*cb)(struct dwc_state_T *, struct packet_queue_T *); + void (*cb)(struct dwc_state_t *, struct packet_queue_T *); } packet_queue_t; typedef struct { @@ -91,10 +91,21 @@ typedef struct { packet_queue_t *packet_queue_tail; } endpoint_t; -typedef struct { +struct dwc_state_t { endpoint_t in[1]; endpoint_t out[1]; -} dwc_state_t; +}; + +static const wchar_t *strings[] = { + [1] = L"string 1", + [2] = L"second string" +}; + +// FIXME +static int string_lengths[] = { + [1] = 16, + [2] = 26 +}; const char *packet_status_names[] = { [1] = "GOUTNAK", @@ -109,7 +120,7 @@ const char *packet_status_names[] = { static int cmd_dwc_dump(int argc, const cmd_args *argv); static void dump_endpoint(endpoint_control *ep, bool in); static void ack_ep(endpoint_control *ep); -void ep_write_in(dwc_state_t *state, int epNr); +void ep_write_in(struct dwc_state_t *state, int epNr); STATIC_COMMAND_START STATIC_COMMAND("dwc_dump", "dump dwc registers", &cmd_dwc_dump) @@ -125,7 +136,7 @@ static void logmsg(const char *msg) { printf("%4d: %s\n", *REG32(ST_CLO), msg); } -void dwc2_ep_queue_in(dwc_state_t *state, int epNr, void *buffer, int bytes, void (*cb)(dwc_state_t *, packet_queue_t *)) { +void dwc2_ep_queue_in(struct dwc_state_t *state, int epNr, void *buffer, int bytes, void (*cb)(struct dwc_state_t *, packet_queue_t *)) { assert(epNr <= 0); packet_queue_t *pkt = malloc(sizeof(packet_queue_t)); pkt->payload = buffer; @@ -149,17 +160,17 @@ void dwc2_ep_queue_in(dwc_state_t *state, int epNr, void *buffer, int bytes, voi } } -void ep_write_in(dwc_state_t *state, int epNr) { +void ep_write_in(struct dwc_state_t *state, int epNr) { endpoint_control *ep = GET_IN(epNr); while (ep->control & (1<<31)) {} //puts("ready"); int maxPacketSize = 64; // TODO packet_queue_t *pkt = state->in[epNr].packet_queue_head; assert(pkt); - //printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); + printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); int bytes = pkt->payload_size - pkt->start; - if (bytes == 0) { - //puts("packet sent"); + if (bytes <= 0) { + puts("IN packet sent"); pkt->cb(state, pkt); packet_queue_t *next = pkt->next; state->in[epNr].packet_queue_head = next; @@ -173,14 +184,14 @@ void ep_write_in(dwc_state_t *state, int epNr) { int partialPacketSize = bytes - (fullPackets*maxPacketSize); int packets = fullPackets + ((partialPacketSize==0) ? 0 : 1); int words = ROUNDUP(bytes,4)/4; - //printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); + printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); if (epNr == 0) { packets = 1; bytes = MIN(maxPacketSize, bytes); //printf("capped to 1 packet of %d bytes\n", bytes); } uint32_t x = (3 << 29) | (packets<<19) | bytes; - //printf("size is 0x%x\n", x); + printf("size is 0x%x\n", x); ep->size = x; ep->control = (1<<31) | // endpoint enable @@ -195,16 +206,16 @@ void ep_write_in(dwc_state_t *state, int epNr) { int bytes_sent = 0; for (int i = 0; i < MIN(maxPacketSize/4, words); i++) { *REG32(USB_DFIFO0) = packet[i]; - //printf("%d(0x%x): posted 0x%x to fifo\n", i, &packet[i], packet[i]); + printf("%d(0x%x): posted 0x%x to fifo\n", i, &packet[i], packet[i]); bytes_sent += 4; } pkt->start += bytes_sent; - //printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); + printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); } static fileServerRequest req; // TODO, put on heap -static void handle_setup_status_out(dwc_state_t *state, packet_queue_t *pkt) { +static void handle_setup_status_out(struct dwc_state_t *state, packet_queue_t *pkt) { endpoint_control *ep_in = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); //puts("setup data IN stage done, on to status OUT..."); @@ -230,13 +241,17 @@ static void handle_setup_status_out(dwc_state_t *state, packet_queue_t *pkt) { //dump_endpoint(ep_out, false); } -static void handle_incoming_setup(dwc_state_t *state, uint8_t *buf, int size) { +void dwc2_out_cb_free(struct dwc_state_t *state, packet_queue_t *pkt) { + free(pkt->payload); + puts("nop"); + endpoint_control *ep_out = GET_OUT(0); + ep_out->control |= (1<<31) | // enable OUT0 + (1<<26); // clear NAK +} + +static void handle_incoming_setup(struct dwc_state_t *state, uint8_t *buf, int size) { setupData *s = (setupData*)buf; - //printf("bmRequestType: 0x%x\n", s->bmRequestType); - //printf("bRequest: 0x%x\n", s->bRequest); - //printf("wValue: 0x%x\n", s->wValue); - //printf("wIndex: 0x%x\n", s->wIndex); - //printf("wLength: 0x%x\n", s->wLength); + bool dump = false; if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { endpoint_control *ep_in = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); @@ -246,6 +261,56 @@ static void handle_incoming_setup(dwc_state_t *state, uint8_t *buf, int size) { memset(&req, 0, sizeof(req)); req.cmd = 2; dwc2_ep_queue_in(state, 0, &req, sizeof(req), &handle_setup_status_out); + } else if (s->bmRequestType == 0x80) { // control-in + puts("\n\n"); + switch (s->bRequest) { + case 0: // GET STATUS + puts("GET STATUS"); + break; + case 6: { // GET DESCRIPTOR + puts("GET DESCRIPTOR"); + uint8_t *int8 = buf; + uint16_t *int16 = buf; + switch (int8[3]) { + case 3: // string descriptor + switch (int16[2]) { // language id + case 0: { + uint8_t *reply = malloc(4); + reply[0] = 4; // length + reply[1] = 3; // type string + reply[2] = 0x09; + reply[3] = 0x04; // english us + dwc2_ep_queue_in(state, 0, reply, 4, &dwc2_out_cb_free); + break; + } + case 0x0409:{ + int string_index = int8[2]; + if ((string_index >= 1) && (string_index <= 2)) { + uint8_t *reply = malloc(string_lengths[string_index] + 2); + reply[0] = string_lengths[string_index] + 2; + reply[1] = 3; + memcpy(reply+2, strings[string_index], string_lengths[string_index]); + dwc2_ep_queue_in(state, 0, reply, string_lengths[string_index] + 2, &dwc2_out_cb_free); + } + break; + } + } + break; + } + break; + } + default: + dump = true; + } + } else { + dump = true; + } + if (dump) { + printf("bmRequestType: 0x%x\n", s->bmRequestType); + printf("bRequest: 0x%x\n", s->bRequest); + printf("wValue: 0x%x\n", s->wValue); + printf("wIndex: 0x%x\n", s->wIndex); + printf("wLength: 0x%x\n", s->wLength); } } @@ -279,7 +344,7 @@ static void ack_ep(endpoint_control *ep) { //printf("ACK'd interrupt 0x%x\n", irq); } -static void dwc_check_interrupt(dwc_state_t *state) { +static void dwc_check_interrupt(struct dwc_state_t *state) { uint32_t interrupt_status = *REG32(USB_GINTSTS); while (interrupt_status & USB_GINTSTS_RXFLVL) { uint32_t receive_status = *REG32(USB_GRXSTSP); @@ -327,10 +392,10 @@ static void dwc_check_interrupt(dwc_state_t *state) { for (int i=16; i<32; i++) { if ((daint >> i) & 1) { ep = (endpoint_control*)((USB_BASE + 0x0b00) + (i-16) * 0x20); - //printf("OUT %d irq\n", i - 16); + printf("OUT %d irq\n", i - 16); //dump_endpoint(ep, false); uint32_t irq = ep->interrupt; - //printf("acking irq bits 0x%x\n", irq); + printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; } } @@ -381,7 +446,7 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { return 0; } -static enum handler_return dwc_irq(dwc_state_t *state) { +static enum handler_return dwc_irq(struct dwc_state_t *state) { lk_bigtime_t start = current_time_hires(); //logmsg("dwc irq"); dwc_check_interrupt(state); @@ -392,9 +457,10 @@ static enum handler_return dwc_irq(dwc_state_t *state) { return INT_NO_RESCHEDULE; } -static dwc_state_t dwc_state; +static struct dwc_state_t dwc_state; static void dwc2_init(const struct app_descriptor *app) { + puts("dwc2_init\n"); memset(&dwc_state, 0, sizeof(dwc_state)); register_int_handler(DWC_IRQ, dwc_irq, &dwc_state); unmask_interrupt(DWC_IRQ); diff --git a/platform/bcm28xx/dwc2/rules.mk b/platform/bcm28xx/dwc2/rules.mk new file mode 100644 index 0000000000..10c52ac040 --- /dev/null +++ b/platform/bcm28xx/dwc2/rules.mk @@ -0,0 +1,11 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + #$(LOCAL_DIR)/dwc2.c \ + +# for 16bit chars in usb +GLOBAL_CFLAGS += -fshort-wchar + +include make/module.mk diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index ae48ad24f6..6768ac0e45 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -46,7 +46,6 @@ MODULE_SRCS += \ $(LOCAL_DIR)/platform.c \ $(LOCAL_DIR)/udelay.c \ $(LOCAL_DIR)/print_timestamp.c \ - $(LOCAL_DIR)/dwc2.c \ #$(LOCAL_DIR)/i2c.c \ From 1528f647cfe1288be210052244e82d6374ebb859 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sat, 16 Jan 2021 11:38:06 -0400 Subject: [PATCH 085/100] dwc2 gadget mode can now fully enumerate on a pi0! --- arch/vpu/intc.c | 5 - platform/bcm28xx/dwc2/dwc2.c | 489 ++++++++++++++++++++++++++++- platform/bcm28xx/dwc2/rules.mk | 2 +- platform/bcm28xx/gpio.c | 18 +- platform/bcm28xx/platform.c | 13 +- platform/bcm28xx/pll/pll_control.c | 8 +- platform/bcm28xx/uart.c | 9 +- 7 files changed, 501 insertions(+), 43 deletions(-) diff --git a/arch/vpu/intc.c b/arch/vpu/intc.c index 8c6f18a8e3..99caed757a 100644 --- a/arch/vpu/intc.c +++ b/arch/vpu/intc.c @@ -51,10 +51,6 @@ void set_interrupt(int intno, bool enable, int core) { } void intc_init(void) { - uint32_t r28, sp; - __asm__ volatile ("mov %0, r28" : "=r"(r28)); - __asm__ volatile ("mov %0, sp" : "=r"(sp)); - dprintf(INFO, "intc_init\nr28: 0x%x\nsp: 0x%x\n", r28, sp); // TODO for (int i=0; i<64; i++) { irq_handlers[0].h = 0; // is this needed? maybe .bss already took care of it? @@ -95,7 +91,6 @@ void intc_init(void) { } uint32_t irq_sp = (uint32_t)((irq_stack0 + sizeof(irq_stack0)) - 4); - dprintf(INFO, "r28 = 0x%x\nirq_stack0: %p\nsizeof(irq_stack0): %d\n", irq_sp, irq_stack0, sizeof(irq_stack0)); __asm__ volatile ("mov r28, %0": :"r"(irq_sp)); diff --git a/platform/bcm28xx/dwc2/dwc2.c b/platform/bcm28xx/dwc2/dwc2.c index 099d5c7346..efc7e46de0 100644 --- a/platform/bcm28xx/dwc2/dwc2.c +++ b/platform/bcm28xx/dwc2/dwc2.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -12,18 +14,30 @@ #define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) +#define USB_GOTGCTL (USB_BASE + 0x0000) #define USB_GAHBCFG (USB_BASE + 0x0008) +#define USB_GUSBCFG (USB_BASE + 0x000c) +#define USB_GRSTCTL (USB_BASE + 0x0010) #define USB_GINTSTS (USB_BASE + 0x0014) #define USB_GINTSTS_RXFLVL (1 << 4) #define USB_GINTMSK (USB_BASE + 0x0018) #define USB_GRXSTSP (USB_BASE + 0x0020) +#define USB_GRXFSIZ (USB_BASE + 0x0024) #define USB_GHWCFG1 (USB_BASE + 0x0044) #define USB_GHWCFG2 (USB_BASE + 0x0048) #define USB_GHWCFG3 (USB_BASE + 0x004c) #define USB_GHWCFG4 (USB_BASE + 0x0050) +#define USB_GMDIOCSR (USB_BASE + 0x0080) +#define USB_GMDIOGEN (USB_BASE + 0x0084) +#define USB_GVBUSDRV (USB_BASE + 0x0088) +#define USB_DIEPTXF1 (USB_BASE + 0x0104) #define USB_DCFG (USB_BASE + 0x0800) +#define USB_DCTL (USB_BASE + 0x0804) +#define USB_DSTS (USB_BASE + 0x0808) #define USB_DIEPMSK (USB_BASE + 0x0810) +#define USB_DOEPMSK (USB_BASE + 0x0814) #define USB_DAINT (USB_BASE + 0x0818) +#define USB_DAINTMSK (USB_BASE + 0x081c) #define USB_DIEPCTL0 (USB_BASE + 0x0900) #define USB_DIEPINT0 (USB_BASE + 0x0908) @@ -33,10 +47,19 @@ #define USB_DIEPCTL2 (USB_BASE + 0x0940) +#define USB_DOEPCTL0 (USB_BASE + 0x0b00) #define USB_DOEPINT0 (USB_BASE + 0x0b08) + +#define USB_DOEPCTL1 (USB_BASE + 0x0b20) #define USB_DOEPINT1 (USB_BASE + 0x0b28) + +#define USB_DOEPCTL2 (USB_BASE + 0x0b40) #define USB_DOEPINT2 (USB_BASE + 0x0b48) + +#define USB_DOEPCTL3 (USB_BASE + 0x0b60) #define USB_DOEPINT3 (USB_BASE + 0x0b68) + +#define USB_DOEPCTL4 (USB_BASE + 0x0b80) #define USB_DOEPINT4 (USB_BASE + 0x0b88) #define USB_DOEPINT5 (USB_BASE + 0x0ba8) #define USB_DOEPINT6 (USB_BASE + 0x0bc8) @@ -49,6 +72,144 @@ #define DWC_IRQ 9 +#define BIT(n) (1< 0x%x\n", reg, val); + return val; +} + +static void dwc_configure_phy(void) { + puts("phy configure"); + *REG32(USB_GMDIOCSR) = 0x40000; + dwc_mdio_write(0x19, 4); + dwc_mdio_write(0x18, 0x342); + dwc_mdio_write(0x1d, 4); + dwc_mdio_write(0x15, 0x111); + + int a, b; + if (true) { + // "fast" crystal (19.2mhz) + a = 0x32; + b = 1; + } else { + // "slow" crystal + a = 0x140; + b = 9; + } + dwc_mdio_write(0x17, b << 12 | 0x600 | a); + while ((dwc_mdio_read(0x1b) & 0x80) == 0) {} + *REG32(USB_GVBUSDRV) &= 0xffffff7f; + + dwc_mdio_write(0x1e, 0x8000); + dwc_mdio_write(0x1d, 0x4000); + dwc_mdio_write(0x19, 0xc004); + dwc_mdio_write(0x20, 0x1c2f); + dwc_mdio_write(0x22, 0x100); + dwc_mdio_write(0x24, 0x10); +} + +static void dwc_start(void) { + puts("usb reset"); + + // core soft reset + *REG32(USB_GRSTCTL) = BIT(0); + while ((*REG32(USB_GRSTCTL) & BIT(0)) != 0) {} + + // hclk soft reset + *REG32(USB_GRSTCTL) = BIT(1); + while ((*REG32(USB_GRSTCTL) & BIT(1)) != 0) {} + + // flush tx fifo 1 + *REG32(USB_GRSTCTL) = 0x420; + while ((*REG32(USB_GRSTCTL) & 0x20) != 0) {} + + // flush rx fifo + *REG32(USB_GRSTCTL) = 0x10; + while ((*REG32(USB_GRSTCTL) & 0x10) != 0) {} + + *REG32(USB_GAHBCFG) = BIT(0); + *REG32(USB_GUSBCFG) = 0x40402740; + *REG32(USB_DOEPCTL0) = 0x80000000; + *REG32(USB_DIEPCTL0) = 0x80000000; +} + +static void dwc_clear_fifo(void) { + volatile uint32_t *reg = REG32(USB_DFIFO0); + for (int i=0; i<0x1000; i++) { + reg[i] = 0; + } + + uint32_t config3 = *REG32(USB_GHWCFG3); + uint32_t a = config3 >> 16; + uint32_t b = a; + while (b = b>>1, b != 0) { + a |= b; + } + uint32_t c = a+1; + reg = REG32(0x7e9a0000); + for (unsigned int i=0; istart = 0; pkt->next = NULL; pkt->cb = cb; + pkt->has_0byte_tail = (bytes % 64) == 0; int do_tx = false; if (state->in[epNr].packet_queue_head == NULL) { // no pending packets, can tx right away + puts("no queue, instant tx"); do_tx = true; state->in[epNr].packet_queue_head = pkt; } @@ -162,14 +444,15 @@ void dwc2_ep_queue_in(struct dwc_state_t *state, int epNr, void *buffer, int byt void ep_write_in(struct dwc_state_t *state, int epNr) { endpoint_control *ep = GET_IN(epNr); + printf("control: 0x%x\n", ep->control); while (ep->control & (1<<31)) {} - //puts("ready"); + puts("ready"); int maxPacketSize = 64; // TODO packet_queue_t *pkt = state->in[epNr].packet_queue_head; assert(pkt); printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); int bytes = pkt->payload_size - pkt->start; - if (bytes <= 0) { + if ((bytes <= 0) && !pkt->has_0byte_tail) { puts("IN packet sent"); pkt->cb(state, pkt); packet_queue_t *next = pkt->next; @@ -179,12 +462,13 @@ void ep_write_in(struct dwc_state_t *state, int epNr) { if (next) return ep_write_in(state, epNr); return; } - assert(bytes > 0); + assert(bytes >= 0); int fullPackets = bytes / maxPacketSize; int partialPacketSize = bytes - (fullPackets*maxPacketSize); int packets = fullPackets + ((partialPacketSize==0) ? 0 : 1); int words = ROUNDUP(bytes,4)/4; printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); + if (bytes == 0) pkt->has_0byte_tail = false; if (epNr == 0) { packets = 1; bytes = MIN(maxPacketSize, bytes); @@ -249,10 +533,27 @@ void dwc2_out_cb_free(struct dwc_state_t *state, packet_queue_t *pkt) { (1<<26); // clear NAK } +void dwc2_out_cb(struct dwc_state_t *state, packet_queue_t *pkt) { + puts("nop"); + endpoint_control *ep_out = GET_OUT(0); + ep_out->control |= (1<<31) | // enable OUT0 + (1<<26); // clear NAK +} + +void dwc2_in_cb(struct dwc_state_t *state, packet_queue_t *pkt) { + puts("in done"); +} + static void handle_incoming_setup(struct dwc_state_t *state, uint8_t *buf, int size) { setupData *s = (setupData*)buf; bool dump = false; - if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { + if ((s->bmRequestType == 0x00) && (s->bRequest == 5)) { // set address + printf("i should be addr %d\n", s->wValue); + *REG32(USB_DCFG) = ((s->wValue & 0x3f) << 4) | (*REG32(USB_DCFG) & 0xfffff80f); + dwc2_ep_queue_in(state, 0, NULL, 0, &dwc2_in_cb); + } else if ((s->bmRequestType == 0x00) && (s->bRequest == 9)) { // set configuration + dwc2_ep_queue_in(state, 0, NULL, 0, &dwc2_in_cb); + } else if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { endpoint_control *ep_in = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); //dump_endpoint(ep, true); @@ -269,11 +570,22 @@ static void handle_incoming_setup(struct dwc_state_t *state, uint8_t *buf, int s break; case 6: { // GET DESCRIPTOR puts("GET DESCRIPTOR"); - uint8_t *int8 = buf; - uint16_t *int16 = buf; - switch (int8[3]) { + getDescriptorRequest *req = (getDescriptorRequest*)buf; + switch (req->bDescriptorType) { + case 1: // device descriptor + puts("queuing reply"); + dwc2_ep_queue_in(state, 0, &defaultDeviceDescriptor, sizeof(defaultDeviceDescriptor), &dwc2_out_cb); + puts("done"); + break; + case 2: // configuration descriptor + { + int size = state->mainConfigurationDescriptorSize; + if (size > req->wLength) size = req->wLength; + dwc2_ep_queue_in(state, 0, state->mainConfigurationDescriptor, size, &dwc2_out_cb); + } + break; case 3: // string descriptor - switch (int16[2]) { // language id + switch (req->wLanguageId) { // language id case 0: { uint8_t *reply = malloc(4); reply[0] = 4; // length @@ -284,7 +596,7 @@ static void handle_incoming_setup(struct dwc_state_t *state, uint8_t *buf, int s break; } case 0x0409:{ - int string_index = int8[2]; + int string_index = req->bDescriptorIndex; if ((string_index >= 1) && (string_index <= 2)) { uint8_t *reply = malloc(string_lengths[string_index] + 2); reply[0] = string_lengths[string_index] + 2; @@ -346,6 +658,49 @@ static void ack_ep(endpoint_control *ep) { static void dwc_check_interrupt(struct dwc_state_t *state) { uint32_t interrupt_status = *REG32(USB_GINTSTS); + printf("irq: 0x%x\n", interrupt_status & *REG32(USB_GINTMSK)); + if (interrupt_status & BIT(13)) { // enumeration done + *REG32(USB_GINTSTS) = BIT(13); + puts("enumeration done"); + GET_OUT(0)->size = (1 << 29) | // 1 setup + (2<<18) | // packet count + 8; // bytes + GET_OUT(0)->control = BIT(31) | BIT(26) | BIT(15); // enable and active + //dumpreg(USB_DSTS); // 808 + interrupt_status = *REG32(USB_GINTSTS); + } + if (interrupt_status & BIT(12)) { // usb reset + *REG32(USB_GINTSTS) = BIT(12); + interrupt_status = *REG32(USB_GINTSTS); + + for (int epNr = 0; epNr < 5; epNr++) { + endpoint_control *ep = GET_OUT(epNr); + ep->control = BIT(31); // enable + } + GET_OUT(0)->size = (1 << 29) | // 1 setup + (2<<18) | // packet count + 8; // bytes + GET_OUT(0)->control = BIT(31) | BIT(26) | BIT(15); // enable and active + + // flush tx fifo 1 + *REG32(USB_GRSTCTL) = 0x420; + while ((*REG32(USB_GRSTCTL) & 0x20) != 0) {} + + // flush rx fifo + *REG32(USB_GRSTCTL) = 0x10; + while ((*REG32(USB_GRSTCTL) & 0x10) != 0) {} + + *REG32(USB_DAINTMSK) = BIT(16) | BIT(0); // allow irq on in0 and out0 + *REG32(USB_DOEPMSK) = BIT(3) | BIT(0); // allow irq on xfer complete and timeout + *REG32(USB_DIEPMSK) = BIT(3) | BIT(0); // allow irq on xfer complete and timeout + + GET_IN(0)->control = BIT(30); // disable IN-0, no data to send yet + } + if (interrupt_status & BIT(11)) { // usb suspend + *REG32(USB_GINTSTS) = BIT(11); + interrupt_status = *REG32(USB_GINTSTS); + puts("suspend"); + } while (interrupt_status & USB_GINTSTS_RXFLVL) { uint32_t receive_status = *REG32(USB_GRXSTSP); //printf("USB_GRXSTSP:\t 0x%x\n", receive_status); @@ -407,8 +762,13 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { uint32_t t; endpoint_control *ep = 0; - dumpreg(USB_GAHBCFG); - dumpreg(USB_GINTSTS); + dumpreg(USB_GOTGCTL); // 0 + if (t & BIT(16)) puts(" 16: B-device mode"); + if (t & BIT(18)) puts(" 18: A-session valid (host only)"); + if (t & BIT(19)) puts(" 19: B-session valid (device only)"); + dumpreg(USB_GAHBCFG); // 8 + dumpreg(USB_GUSBCFG); // c + dumpreg(USB_GINTSTS); // 14 printf(" CURMOD: %d\n", t & 1); printf(" MODEMIS: %d\n", (t >> 1) & 1); printf(" OTGINT: %d\n", (t >> 2) & 1); @@ -425,14 +785,20 @@ static int cmd_dwc_dump(int argc, const cmd_args *argv) { printf(" ISOOUTDROP: %d\n", (t >> 14) & 1); printf(" EOPF: %d\n", (t >> 15) & 1); printf(" unparsed: %d\n", (t >> 16) & 0xffff); - dumpreg(USB_GINTMSK); + dumpreg(USB_GINTMSK); // 18 + printf("masked irq's: 0x%x\n", *REG32(USB_GINTSTS) & ~(*REG32(USB_GINTMSK))); dumpreg(USB_GHWCFG1); dumpreg(USB_GHWCFG2); dumpreg(USB_GHWCFG3); dumpreg(USB_GHWCFG4); + if ((t >> 25) & 1) puts(" dedicated transmit fifo enabled"); dumpreg(USB_DCFG); // 800 + dumpreg(USB_DCTL); // 804 + dumpreg(USB_DSTS); // 808 dumpreg(USB_DIEPMSK); // 810 - dumpreg(USB_DAINT); + dumpreg(USB_DOEPMSK); // 814 + dumpreg(USB_DAINT); // 818 + dumpreg(USB_DAINTMSK); // 81c for (int i=0; i<3; i++) { printf("IN%d\n", i); ep = (endpoint_control*)((USB_BASE + 0x0900) + i * 0x20); @@ -460,13 +826,106 @@ static enum handler_return dwc_irq(struct dwc_state_t *state) { static struct dwc_state_t dwc_state; static void dwc2_init(const struct app_descriptor *app) { - puts("dwc2_init\n"); + uint32_t t; + puts("dwc2_init"); + // TODO, move power domain code into its own driver + puts("image domain on..."); + dumpreg(PM_IMAGE); + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x10000; // CFG = 1 +#if 0 + printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); + *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 + for (int i=0; i<10; i++) { + if (*REG32(PM_IMAGE) & 2) { // if power ok + break; + } + udelay(1); + if (i == 9) puts("PM_IMAGE timeout"); + } + printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); + *REG32(PM_IMAGE) = PM_PASSWORD | (*REG32(PM_IMAGE) & ~1); // POWUP = 0 + + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x30000; // CFG = 3 + *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 + for (int i=0; i<10; i++) { + if (*REG32(PM_IMAGE) & 2) { // if power ok + break; + } + udelay(1); + if (i == 9) puts("PM_IMAGE timeout"); + } + printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x40; +#endif + dumpreg(PM_IMAGE); + power_domain_on(REG32(PM_IMAGE)); + dumpreg(PM_IMAGE); + + printf("PM_USB: 0x%x\n", *REG32(PM_USB)); + puts("usb power on..."); + *REG32(PM_USB) = PM_PASSWORD | 1; + printf("PM_USB: 0x%x\n", *REG32(PM_USB)); + udelay(600); + printf("PM_USB: 0x%x\n", *REG32(PM_USB)); + + dumpreg(CM_PERIICTL); + *REG32(CM_PERIIDIV) = CM_PASSWORD | 0x1000; + *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; + dumpreg(CM_PERIICTL); + *REG32(CM_PERIICTL) = (*REG32(CM_PERIICTL) & 0xffffffbf) | CM_PASSWORD; + dumpreg(CM_PERIICTL); + dumpreg(CM_PERIIDIV); + + *REG32(PM_IMAGE) |= PM_PASSWORD | PM_V3DRSTN; + *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; + memset(&dwc_state, 0, sizeof(dwc_state)); + dwc_state.mainConfigurationDescriptorSize = sizeof(defaultConfigurationDescriptor) + sizeof(defaultInterfaceDescriptor) + sizeof(ep0Descriptor) + sizeof(ep1Descriptor); + dwc_state.mainConfigurationDescriptor = malloc(dwc_state.mainConfigurationDescriptorSize); + + int pos = 0; + memcpy(dwc_state.mainConfigurationDescriptor + pos, &defaultConfigurationDescriptor, sizeof(defaultConfigurationDescriptor)); + pos += sizeof(defaultConfigurationDescriptor); + + memcpy(dwc_state.mainConfigurationDescriptor + pos, &defaultInterfaceDescriptor, sizeof(defaultInterfaceDescriptor)); + pos += sizeof(defaultInterfaceDescriptor); + + memcpy(dwc_state.mainConfigurationDescriptor + pos, &ep0Descriptor, sizeof(ep0Descriptor)); + pos += sizeof(ep0Descriptor); + + memcpy(dwc_state.mainConfigurationDescriptor + pos, &ep1Descriptor, sizeof(ep1Descriptor)); + pos += sizeof(ep1Descriptor); + assert(pos == dwc_state.mainConfigurationDescriptorSize); + register_int_handler(DWC_IRQ, dwc_irq, &dwc_state); unmask_interrupt(DWC_IRQ); - *REG32(USB_GINTMSK) = (1<<4); + dwc_configure_phy(); + dwc_clear_fifo(); + dwc_start(); + + //dumpreg(USB_GAHBCFG); + *REG32(USB_GINTMSK) = + BIT(19) | BIT(18) | BIT(17) | + BIT(13) | BIT(12) | BIT(11) | BIT(4) + | BIT(2) + ; *REG32(USB_DIEPMSK) = (1<<4) | (1<<3) | (1<<0); + + *REG32(USB_DCFG) = (1 << 18) | // in endpoint mismatch count + (1 << 11) | // periodic frame interval interrupt + 3; // full speed + //0; // high speed 2.0 + + *REG32(USB_GRXFSIZ) = 0x200; + + volatile uint32_t *reg = REG32(USB_DIEPTXF1); + int start = 0x300; + for (int i = 0; i< 7; i++) { + t = start | (0x100 << 16); + start = start + 0x100; + reg[i] = t; + } } static void dwc2_entry(const struct app_descriptor *app, void *args) { diff --git a/platform/bcm28xx/dwc2/rules.mk b/platform/bcm28xx/dwc2/rules.mk index 10c52ac040..06207c554c 100644 --- a/platform/bcm28xx/dwc2/rules.mk +++ b/platform/bcm28xx/dwc2/rules.mk @@ -3,7 +3,7 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) MODULE_SRCS += \ - #$(LOCAL_DIR)/dwc2.c \ + $(LOCAL_DIR)/dwc2.c \ # for 16bit chars in usb GLOBAL_CFLAGS += -fshort-wchar diff --git a/platform/bcm28xx/gpio.c b/platform/bcm28xx/gpio.c index 055826edee..94bcfed7de 100644 --- a/platform/bcm28xx/gpio.c +++ b/platform/bcm28xx/gpio.c @@ -137,15 +137,15 @@ static int cmd_gpio_write(int argc, const cmd_args *argv) { const char *mode_names[] = { - "IN", - "OUT", - "ALT5", - "ALT4", - "ALT0", - "ALT1", - "ALT2", - "ALT3", - "" + [kBCM2708PinmuxIn] = "IN", + [kBCM2708PinmuxOut] = "OUT", + [kBCM2708Pinmux_ALT5] = "ALT5", + [kBCM2708Pinmux_ALT4] = "ALT4", + [kBCM2708Pinmux_ALT0] = "ALT0", + [kBCM2708Pinmux_ALT1] = "ALT1", + [kBCM2708Pinmux_ALT2] = "ALT2", + [kBCM2708Pinmux_ALT3] = "ALT3", + [8] = "" }; const char *levels[] = { "LOW", "HIGH" }; diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 1ee1db7251..b40dbec063 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -130,7 +130,10 @@ static void switch_vpu_to_pllc() { switch_vpu_to_src(CM_SRC_OSC); *REG32(CM_VPUDIV) = CM_PASSWORD | (1 << 12); - setup_pllc( 2000LL * 1000 * 1000); + int core0_div = 4; + int per_div = 4; + + setup_pllc( 2000LL * 1000 * 1000, core0_div, per_div); int vpu_divisor = 1; @@ -144,7 +147,7 @@ static void switch_vpu_to_pllc() { int vpu = measure_clock(5); int pllc_core0 = vpu*vpu_divisor; - uint32_t pllc = pllc_core0 * 4; + uint32_t pllc = pllc_core0 * core0_div; dprintf(INFO, "VPU now at %dmhz, ", vpu/1000/1000); dprintf(INFO, "PLLC_CORE0 at %dmhz, ", pllc_core0/1000/1000); dprintf(INFO, "PLLC at %dmhz\n", pllc / 1000 / 1000); @@ -250,17 +253,17 @@ void platform_early_init(void) { void platform_init(void) { #if BCM2835 == 1 - gpio_config(0, 1); + gpio_config(0, kBCM2708PinmuxOut); #endif #ifdef RPI4 - gpio_config(42, 1); + gpio_config(42, kBCM2708PinmuxOut); #endif uart_init(); #if BCM2837 init_framebuffer(); #endif - printf("crystal is %f MHz\n", (float)xtal_freq/1000/1000); + printf("crystal is %lf MHz\n", (double)xtal_freq/1000/1000); } void platform_dputc(char c) { diff --git a/platform/bcm28xx/pll/pll_control.c b/platform/bcm28xx/pll/pll_control.c index a90be8d50a..f9ab8a546f 100644 --- a/platform/bcm28xx/pll/pll_control.c +++ b/platform/bcm28xx/pll/pll_control.c @@ -486,10 +486,10 @@ void switch_vpu_to_src(int src) { while (*REG32(CM_VPUCTL) & CM_VPUCTL_BUSY_SET) {}; } -void setup_pllc(uint64_t target_freq) { +void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { int pdiv = 1; uint64_t xtal_in = xtal_freq; - uint64_t goal_freq = target_freq / 1; + uint64_t goal_freq = target_freq / 2; uint64_t divisor = (goal_freq<<20) / xtal_in; int div = divisor >> 20; int frac = divisor & 0xfffff; @@ -527,9 +527,9 @@ void setup_pllc(uint64_t target_freq) { *REG32(A2W_PLLC_DIG1) = A2W_PASSWORD | 0x4005; *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | div | 0x555000; - *REG32(A2W_PLLC_CORE0) = A2W_PASSWORD | 4; + *REG32(A2W_PLLC_CORE0) = A2W_PASSWORD | core0_div; - *REG32(A2W_PLLC_PER) = A2W_PASSWORD | 4; + *REG32(A2W_PLLC_PER) = A2W_PASSWORD | per_div; *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_DIGRST_SET | CM_PLLC_HOLDPER_SET | CM_PLLC_HOLDCORE2_SET | diff --git a/platform/bcm28xx/uart.c b/platform/bcm28xx/uart.c index d7ec1d633d..5e3202d0e0 100644 --- a/platform/bcm28xx/uart.c +++ b/platform/bcm28xx/uart.c @@ -47,9 +47,9 @@ static int cmd_uart_dump(int argc, const cmd_args *argv); int uart_putc(int port, char c); void udelay(uint32_t t); -//STATIC_COMMAND_START -//STATIC_COMMAND("dump_uart_state", "print uart state relating to baud", &cmd_uart_dump) -//STATIC_COMMAND_END(uart); +STATIC_COMMAND_START +STATIC_COMMAND("dump_uart_state", "print uart state relating to baud", &cmd_uart_dump) +STATIC_COMMAND_END(uart); static inline uintptr_t uart_to_ptr(unsigned int n) { switch (n) { @@ -150,7 +150,8 @@ void uart_init(void) { void uart_init_early(void) { if (*REG32(CM_UARTDIV) == 0) { - puts("fixing divisor"); + //puts("fixing divisor"); + //return; // CM_UARTDIV can range from 0 to 1023 with a fractional resolution of 1/4096th // on the rpi1-3, this sets the freq to 19.2 / (0x3900 / 0x1000) == ~5.3mhz // TODO, have a better default for other models? From ab4d0818aad3edcef2a06bd075b7f4d1c66b91ea Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sat, 16 Jan 2021 13:27:51 -0400 Subject: [PATCH 086/100] clean up dwc2 code --- platform/bcm28xx/dwc2/dwc2.c | 212 +++--------------- .../dwc2/include/platform/bcm28xx/dwc2.h | 61 +++++ platform/bcm28xx/dwc2/rules.mk | 2 + .../bcm28xx/include/platform/bcm28xx/pll.h | 5 +- .../bcm28xx/include/platform/bcm28xx/pm.h | 2 + .../power/include/platform/bcm28xx/power.h | 18 ++ platform/bcm28xx/power/power.c | 84 +++++++ platform/bcm28xx/power/rules.mk | 8 + 8 files changed, 214 insertions(+), 178 deletions(-) create mode 100644 platform/bcm28xx/dwc2/include/platform/bcm28xx/dwc2.h create mode 100644 platform/bcm28xx/power/include/platform/bcm28xx/power.h create mode 100644 platform/bcm28xx/power/power.c create mode 100644 platform/bcm28xx/power/rules.mk diff --git a/platform/bcm28xx/dwc2/dwc2.c b/platform/bcm28xx/dwc2/dwc2.c index efc7e46de0..533033c107 100644 --- a/platform/bcm28xx/dwc2/dwc2.c +++ b/platform/bcm28xx/dwc2/dwc2.c @@ -4,113 +4,20 @@ #include #include #include -#include -#include +#include #include +#include +#include +#include #include #include #include #include -#define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) - -#define USB_GOTGCTL (USB_BASE + 0x0000) -#define USB_GAHBCFG (USB_BASE + 0x0008) -#define USB_GUSBCFG (USB_BASE + 0x000c) -#define USB_GRSTCTL (USB_BASE + 0x0010) -#define USB_GINTSTS (USB_BASE + 0x0014) -#define USB_GINTSTS_RXFLVL (1 << 4) -#define USB_GINTMSK (USB_BASE + 0x0018) -#define USB_GRXSTSP (USB_BASE + 0x0020) -#define USB_GRXFSIZ (USB_BASE + 0x0024) -#define USB_GHWCFG1 (USB_BASE + 0x0044) -#define USB_GHWCFG2 (USB_BASE + 0x0048) -#define USB_GHWCFG3 (USB_BASE + 0x004c) -#define USB_GHWCFG4 (USB_BASE + 0x0050) -#define USB_GMDIOCSR (USB_BASE + 0x0080) -#define USB_GMDIOGEN (USB_BASE + 0x0084) -#define USB_GVBUSDRV (USB_BASE + 0x0088) -#define USB_DIEPTXF1 (USB_BASE + 0x0104) -#define USB_DCFG (USB_BASE + 0x0800) -#define USB_DCTL (USB_BASE + 0x0804) -#define USB_DSTS (USB_BASE + 0x0808) -#define USB_DIEPMSK (USB_BASE + 0x0810) -#define USB_DOEPMSK (USB_BASE + 0x0814) -#define USB_DAINT (USB_BASE + 0x0818) -#define USB_DAINTMSK (USB_BASE + 0x081c) - -#define USB_DIEPCTL0 (USB_BASE + 0x0900) -#define USB_DIEPINT0 (USB_BASE + 0x0908) - -#define USB_DIEPCTL1 (USB_BASE + 0x0920) -#define USB_DIEPINT1 (USB_BASE + 0x0928) - -#define USB_DIEPCTL2 (USB_BASE + 0x0940) - -#define USB_DOEPCTL0 (USB_BASE + 0x0b00) -#define USB_DOEPINT0 (USB_BASE + 0x0b08) - -#define USB_DOEPCTL1 (USB_BASE + 0x0b20) -#define USB_DOEPINT1 (USB_BASE + 0x0b28) - -#define USB_DOEPCTL2 (USB_BASE + 0x0b40) -#define USB_DOEPINT2 (USB_BASE + 0x0b48) - -#define USB_DOEPCTL3 (USB_BASE + 0x0b60) -#define USB_DOEPINT3 (USB_BASE + 0x0b68) - -#define USB_DOEPCTL4 (USB_BASE + 0x0b80) -#define USB_DOEPINT4 (USB_BASE + 0x0b88) -#define USB_DOEPINT5 (USB_BASE + 0x0ba8) -#define USB_DOEPINT6 (USB_BASE + 0x0bc8) -#define USB_DOEPINT7 (USB_BASE + 0x0be8) -#define USB_DOEPINT8 (USB_BASE + 0x0c08) -#define USB_DOEPINT9 (USB_BASE + 0x0c28) - -#define USB_DFIFO0 (USB_BASE + 0x1000) -#define USB_DFIFO1 (USB_BASE + 0x2000) - -#define DWC_IRQ 9 - -#define BIT(n) (1< 0x%x\n", reg, val); + //printf("usb MDIO 0x%x -> 0x%x\n", reg, val); return val; } @@ -294,8 +201,8 @@ deviceDescriptor defaultDeviceDescriptor = { .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = 64, - .idVendor = 0x1234, - .idProduct = 0x5678, + .idVendor = 0x0000, + .idProduct = 0x0000, .bcdDevice = 0, .iManufacturer = 1, .iProduct = 2, @@ -429,7 +336,6 @@ void dwc2_ep_queue_in(struct dwc_state_t *state, int epNr, void *buffer, int byt int do_tx = false; if (state->in[epNr].packet_queue_head == NULL) { // no pending packets, can tx right away - puts("no queue, instant tx"); do_tx = true; state->in[epNr].packet_queue_head = pkt; } @@ -444,16 +350,15 @@ void dwc2_ep_queue_in(struct dwc_state_t *state, int epNr, void *buffer, int byt void ep_write_in(struct dwc_state_t *state, int epNr) { endpoint_control *ep = GET_IN(epNr); - printf("control: 0x%x\n", ep->control); + //printf("control: 0x%x\n", ep->control); while (ep->control & (1<<31)) {} - puts("ready"); int maxPacketSize = 64; // TODO packet_queue_t *pkt = state->in[epNr].packet_queue_head; assert(pkt); - printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); + //printf("packet(%x): 0x%x+(0x%x/0x%x)\n", (uint32_t)pkt, (uint32_t)pkt->payload, pkt->start, pkt->payload_size); int bytes = pkt->payload_size - pkt->start; if ((bytes <= 0) && !pkt->has_0byte_tail) { - puts("IN packet sent"); + //puts("IN packet sent"); pkt->cb(state, pkt); packet_queue_t *next = pkt->next; state->in[epNr].packet_queue_head = next; @@ -467,7 +372,7 @@ void ep_write_in(struct dwc_state_t *state, int epNr) { int partialPacketSize = bytes - (fullPackets*maxPacketSize); int packets = fullPackets + ((partialPacketSize==0) ? 0 : 1); int words = ROUNDUP(bytes,4)/4; - printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); + //printf("sending %d full packets and a %d byte partial, %d total, %d words\n", fullPackets, partialPacketSize, packets, words); if (bytes == 0) pkt->has_0byte_tail = false; if (epNr == 0) { packets = 1; @@ -475,7 +380,6 @@ void ep_write_in(struct dwc_state_t *state, int epNr) { //printf("capped to 1 packet of %d bytes\n", bytes); } uint32_t x = (3 << 29) | (packets<<19) | bytes; - printf("size is 0x%x\n", x); ep->size = x; ep->control = (1<<31) | // endpoint enable @@ -490,11 +394,11 @@ void ep_write_in(struct dwc_state_t *state, int epNr) { int bytes_sent = 0; for (int i = 0; i < MIN(maxPacketSize/4, words); i++) { *REG32(USB_DFIFO0) = packet[i]; - printf("%d(0x%x): posted 0x%x to fifo\n", i, &packet[i], packet[i]); + //printf("%d: posted 0x%08x to fifo\n", i, packet[i]); bytes_sent += 4; } pkt->start += bytes_sent; - printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); + //printf("%d bytes sent, start now %d\n", bytes_sent, pkt->start); } static fileServerRequest req; // TODO, put on heap @@ -527,32 +431,33 @@ static void handle_setup_status_out(struct dwc_state_t *state, packet_queue_t *p void dwc2_out_cb_free(struct dwc_state_t *state, packet_queue_t *pkt) { free(pkt->payload); - puts("nop"); + //puts("nop"); endpoint_control *ep_out = GET_OUT(0); ep_out->control |= (1<<31) | // enable OUT0 (1<<26); // clear NAK } void dwc2_out_cb(struct dwc_state_t *state, packet_queue_t *pkt) { - puts("nop"); + //puts("nop"); endpoint_control *ep_out = GET_OUT(0); ep_out->control |= (1<<31) | // enable OUT0 (1<<26); // clear NAK } void dwc2_in_cb(struct dwc_state_t *state, packet_queue_t *pkt) { - puts("in done"); + //puts("in done"); } static void handle_incoming_setup(struct dwc_state_t *state, uint8_t *buf, int size) { setupData *s = (setupData*)buf; bool dump = false; if ((s->bmRequestType == 0x00) && (s->bRequest == 5)) { // set address - printf("i should be addr %d\n", s->wValue); *REG32(USB_DCFG) = ((s->wValue & 0x3f) << 4) | (*REG32(USB_DCFG) & 0xfffff80f); dwc2_ep_queue_in(state, 0, NULL, 0, &dwc2_in_cb); + logf("i am device %d\n", s->wValue); } else if ((s->bmRequestType == 0x00) && (s->bRequest == 9)) { // set configuration dwc2_ep_queue_in(state, 0, NULL, 0, &dwc2_in_cb); + logf("set configuration\n"); } else if ((s->bmRequestType == 0xc0) && (s->wLength == 0x104)) { endpoint_control *ep_in = GET_IN(0); endpoint_control *ep_out = GET_OUT(0); @@ -563,19 +468,21 @@ static void handle_incoming_setup(struct dwc_state_t *state, uint8_t *buf, int s req.cmd = 2; dwc2_ep_queue_in(state, 0, &req, sizeof(req), &handle_setup_status_out); } else if (s->bmRequestType == 0x80) { // control-in - puts("\n\n"); + //puts("\n\n"); switch (s->bRequest) { case 0: // GET STATUS puts("GET STATUS"); break; case 6: { // GET DESCRIPTOR - puts("GET DESCRIPTOR"); + //puts("GET DESCRIPTOR"); getDescriptorRequest *req = (getDescriptorRequest*)buf; switch (req->bDescriptorType) { case 1: // device descriptor - puts("queuing reply"); - dwc2_ep_queue_in(state, 0, &defaultDeviceDescriptor, sizeof(defaultDeviceDescriptor), &dwc2_out_cb); - puts("done"); + { + int size = sizeof(defaultDeviceDescriptor); + if (size > req->wLength) size = req->wLength; + dwc2_ep_queue_in(state, 0, &defaultDeviceDescriptor, size, &dwc2_out_cb); + } break; case 2: // configuration descriptor { @@ -658,10 +565,10 @@ static void ack_ep(endpoint_control *ep) { static void dwc_check_interrupt(struct dwc_state_t *state) { uint32_t interrupt_status = *REG32(USB_GINTSTS); - printf("irq: 0x%x\n", interrupt_status & *REG32(USB_GINTMSK)); + //printf("irq: 0x%x\n", interrupt_status & *REG32(USB_GINTMSK)); if (interrupt_status & BIT(13)) { // enumeration done *REG32(USB_GINTSTS) = BIT(13); - puts("enumeration done"); + logf("enumeration done\n"); GET_OUT(0)->size = (1 << 29) | // 1 setup (2<<18) | // packet count 8; // bytes @@ -699,7 +606,7 @@ static void dwc_check_interrupt(struct dwc_state_t *state) { if (interrupt_status & BIT(11)) { // usb suspend *REG32(USB_GINTSTS) = BIT(11); interrupt_status = *REG32(USB_GINTSTS); - puts("suspend"); + //puts("suspend"); } while (interrupt_status & USB_GINTSTS_RXFLVL) { uint32_t receive_status = *REG32(USB_GRXSTSP); @@ -747,10 +654,10 @@ static void dwc_check_interrupt(struct dwc_state_t *state) { for (int i=16; i<32; i++) { if ((daint >> i) & 1) { ep = (endpoint_control*)((USB_BASE + 0x0b00) + (i-16) * 0x20); - printf("OUT %d irq\n", i - 16); + //printf("OUT %d irq\n", i - 16); //dump_endpoint(ep, false); uint32_t irq = ep->interrupt; - printf("acking irq bits 0x%x\n", irq); + //printf("acking irq bits 0x%x\n", irq); ep->interrupt = irq; } } @@ -819,7 +726,7 @@ static enum handler_return dwc_irq(struct dwc_state_t *state) { lk_bigtime_t end = current_time_hires(); lk_bigtime_t spent = end - start; //logmsg("done"); - printf("irq time: %lld\n", spent); + if (spent > 20) logf("irq time: %lld\n", spent); return INT_NO_RESCHEDULE; } @@ -827,57 +734,8 @@ static struct dwc_state_t dwc_state; static void dwc2_init(const struct app_descriptor *app) { uint32_t t; - puts("dwc2_init"); - // TODO, move power domain code into its own driver - puts("image domain on..."); - dumpreg(PM_IMAGE); - *REG32(PM_IMAGE) |= PM_PASSWORD | 0x10000; // CFG = 1 -#if 0 - printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); - *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 - for (int i=0; i<10; i++) { - if (*REG32(PM_IMAGE) & 2) { // if power ok - break; - } - udelay(1); - if (i == 9) puts("PM_IMAGE timeout"); - } - printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); - *REG32(PM_IMAGE) = PM_PASSWORD | (*REG32(PM_IMAGE) & ~1); // POWUP = 0 - - *REG32(PM_IMAGE) |= PM_PASSWORD | 0x30000; // CFG = 3 - *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 - for (int i=0; i<10; i++) { - if (*REG32(PM_IMAGE) & 2) { // if power ok - break; - } - udelay(1); - if (i == 9) puts("PM_IMAGE timeout"); - } - printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); - *REG32(PM_IMAGE) |= PM_PASSWORD | 0x40; -#endif - dumpreg(PM_IMAGE); - power_domain_on(REG32(PM_IMAGE)); - dumpreg(PM_IMAGE); - - printf("PM_USB: 0x%x\n", *REG32(PM_USB)); - puts("usb power on..."); - *REG32(PM_USB) = PM_PASSWORD | 1; - printf("PM_USB: 0x%x\n", *REG32(PM_USB)); - udelay(600); - printf("PM_USB: 0x%x\n", *REG32(PM_USB)); - - dumpreg(CM_PERIICTL); - *REG32(CM_PERIIDIV) = CM_PASSWORD | 0x1000; - *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; - dumpreg(CM_PERIICTL); - *REG32(CM_PERIICTL) = (*REG32(CM_PERIICTL) & 0xffffffbf) | CM_PASSWORD; - dumpreg(CM_PERIICTL); - dumpreg(CM_PERIIDIV); - - *REG32(PM_IMAGE) |= PM_PASSWORD | PM_V3DRSTN; - *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; + logf("dwc2_init\n"); + power_up_usb(); memset(&dwc_state, 0, sizeof(dwc_state)); dwc_state.mainConfigurationDescriptorSize = sizeof(defaultConfigurationDescriptor) + sizeof(defaultInterfaceDescriptor) + sizeof(ep0Descriptor) + sizeof(ep1Descriptor); diff --git a/platform/bcm28xx/dwc2/include/platform/bcm28xx/dwc2.h b/platform/bcm28xx/dwc2/include/platform/bcm28xx/dwc2.h new file mode 100644 index 0000000000..5ed1ea0adb --- /dev/null +++ b/platform/bcm28xx/dwc2/include/platform/bcm28xx/dwc2.h @@ -0,0 +1,61 @@ +#pragma once + +#define USB_BASE (BCM_PERIPH_BASE_VIRT + 0x980000) + +#define USB_GOTGCTL (USB_BASE + 0x0000) +#define USB_GAHBCFG (USB_BASE + 0x0008) +#define USB_GUSBCFG (USB_BASE + 0x000c) +#define USB_GRSTCTL (USB_BASE + 0x0010) +#define USB_GINTSTS (USB_BASE + 0x0014) +#define USB_GINTSTS_RXFLVL (1 << 4) +#define USB_GINTMSK (USB_BASE + 0x0018) +#define USB_GRXSTSP (USB_BASE + 0x0020) +#define USB_GRXFSIZ (USB_BASE + 0x0024) +#define USB_GHWCFG1 (USB_BASE + 0x0044) +#define USB_GHWCFG2 (USB_BASE + 0x0048) +#define USB_GHWCFG3 (USB_BASE + 0x004c) +#define USB_GHWCFG4 (USB_BASE + 0x0050) +#define USB_GMDIOCSR (USB_BASE + 0x0080) +#define USB_GMDIOGEN (USB_BASE + 0x0084) +#define USB_GVBUSDRV (USB_BASE + 0x0088) +#define USB_DIEPTXF1 (USB_BASE + 0x0104) +#define USB_DCFG (USB_BASE + 0x0800) +#define USB_DCTL (USB_BASE + 0x0804) +#define USB_DSTS (USB_BASE + 0x0808) +#define USB_DIEPMSK (USB_BASE + 0x0810) +#define USB_DOEPMSK (USB_BASE + 0x0814) +#define USB_DAINT (USB_BASE + 0x0818) +#define USB_DAINTMSK (USB_BASE + 0x081c) + +#define USB_DIEPCTL0 (USB_BASE + 0x0900) +#define USB_DIEPINT0 (USB_BASE + 0x0908) + +#define USB_DIEPCTL1 (USB_BASE + 0x0920) +#define USB_DIEPINT1 (USB_BASE + 0x0928) + +#define USB_DIEPCTL2 (USB_BASE + 0x0940) + +#define USB_DOEPCTL0 (USB_BASE + 0x0b00) +#define USB_DOEPINT0 (USB_BASE + 0x0b08) + +#define USB_DOEPCTL1 (USB_BASE + 0x0b20) +#define USB_DOEPINT1 (USB_BASE + 0x0b28) + +#define USB_DOEPCTL2 (USB_BASE + 0x0b40) +#define USB_DOEPINT2 (USB_BASE + 0x0b48) + +#define USB_DOEPCTL3 (USB_BASE + 0x0b60) +#define USB_DOEPINT3 (USB_BASE + 0x0b68) + +#define USB_DOEPCTL4 (USB_BASE + 0x0b80) +#define USB_DOEPINT4 (USB_BASE + 0x0b88) +#define USB_DOEPINT5 (USB_BASE + 0x0ba8) +#define USB_DOEPINT6 (USB_BASE + 0x0bc8) +#define USB_DOEPINT7 (USB_BASE + 0x0be8) +#define USB_DOEPINT8 (USB_BASE + 0x0c08) +#define USB_DOEPINT9 (USB_BASE + 0x0c28) + +#define USB_DFIFO0 (USB_BASE + 0x1000) +#define USB_DFIFO1 (USB_BASE + 0x2000) + +#define DWC_IRQ 9 diff --git a/platform/bcm28xx/dwc2/rules.mk b/platform/bcm28xx/dwc2/rules.mk index 06207c554c..2cc809da8f 100644 --- a/platform/bcm28xx/dwc2/rules.mk +++ b/platform/bcm28xx/dwc2/rules.mk @@ -8,4 +8,6 @@ MODULE_SRCS += \ # for 16bit chars in usb GLOBAL_CFLAGS += -fshort-wchar +MODULES += platform/bcm28xx/power + include make/module.mk diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 7c902275e4..3097bdf98e 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -68,7 +68,7 @@ struct pll_chan_def { extern uint32_t xtal_freq; extern const struct pll_chan_def pll_chan_def[PLL_CHAN_NUM]; -void setup_pllc(uint64_t freq); +void setup_pllc(uint64_t freq, int core0_div, int per_div); void switch_vpu_to_src(int src); @@ -83,6 +83,9 @@ void switch_vpu_to_src(int src); #define CM_VPUCTL_GATE_SET 0x00000040 #define CM_VPUDIV (CM_BASE + 0x00c) +#define CM_PERIICTL (CM_BASE + 0x020) +#define CM_PERIIDIV (CM_BASE + 0x024) + #define CM_DPICTL (CM_BASE + 0x068) #define CM_DPICTL_KILL_SET 0x20 #define CM_DPICTL_BUSY_SET 0x80 diff --git a/platform/bcm28xx/include/platform/bcm28xx/pm.h b/platform/bcm28xx/include/platform/bcm28xx/pm.h index 6e658b0680..c642143f65 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pm.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pm.h @@ -24,5 +24,7 @@ #define PM_RSTS_HADDRQ_SET 0x00000001 // bit 0 had debugger quick reset #define PM_WDOG (PM_BASE + 0x24) #define PM_WDOG_MASK 0x00000fff +#define PM_USB (PM_BASE + 0x5c) #define PM_SMPS (PM_BASE + 0x6c) #define PM_SPAREW (PM_BASE + 0x74) +#define PM_IMAGE (PM_BASE + 0x108) diff --git a/platform/bcm28xx/power/include/platform/bcm28xx/power.h b/platform/bcm28xx/power/include/platform/bcm28xx/power.h new file mode 100644 index 0000000000..23f0e3ed1f --- /dev/null +++ b/platform/bcm28xx/power/include/platform/bcm28xx/power.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#define BIT(n) (1< +#include +#include +#include +#include + +void power_up_image(void) { + puts("image domain on..."); + //dumpreg(PM_IMAGE); + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x10000; // CFG = 1 +#if 0 + printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); + *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 + for (int i=0; i<10; i++) { + if (*REG32(PM_IMAGE) & 2) { // if power ok + break; + } + udelay(1); + if (i == 9) puts("PM_IMAGE timeout"); + } + printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); + *REG32(PM_IMAGE) = PM_PASSWORD | (*REG32(PM_IMAGE) & ~1); // POWUP = 0 + + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x30000; // CFG = 3 + *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 + for (int i=0; i<10; i++) { + if (*REG32(PM_IMAGE) & 2) { // if power ok + break; + } + udelay(1); + if (i == 9) puts("PM_IMAGE timeout"); + } + printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x40; +#endif + //dumpreg(PM_IMAGE); + power_domain_on(REG32(PM_IMAGE)); + //dumpreg(PM_IMAGE); +} + +void power_up_usb(void) { + // TODO, move power domain code into its own driver + power_up_image(); + + puts("usb power on..."); + *REG32(PM_USB) = PM_PASSWORD | 1; + udelay(600); + + //dumpreg(CM_PERIICTL); + *REG32(CM_PERIIDIV) = CM_PASSWORD | 0x1000; + *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; + //dumpreg(CM_PERIICTL); + *REG32(CM_PERIICTL) = (*REG32(CM_PERIICTL) & 0xffffffbf) | CM_PASSWORD; + //dumpreg(CM_PERIICTL); + //dumpreg(CM_PERIIDIV); + + *REG32(PM_IMAGE) |= PM_PASSWORD | PM_V3DRSTN; + *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; +} + +void power_domain_on(volatile uint32_t *reg) { + /* If it was already powered on by the fw, leave it that way. */ + if (*REG32(reg) & PM_POWUP) { + puts("already on"); + return; + } + /* Enable power */ + *REG32(reg) |= PM_PASSWORD | PM_POWUP; + + while (!(*REG32(reg) & PM_POWOK)) { + udelay(1); // TODO, add timeout + } + + /* Disable electrical isolation */ + *REG32(reg) |= PM_PASSWORD | PM_ISPOW; + + /* Repair memory */ + *REG32(reg) |= PM_PASSWORD | PM_MEMREP; + while (!(*REG32(reg) & PM_MRDONE)) { + udelay(1); // TODO, add timeout + } + /* Disable functional isolation */ + *REG32(reg) |= PM_PASSWORD | PM_ISFUNC; +} diff --git a/platform/bcm28xx/power/rules.mk b/platform/bcm28xx/power/rules.mk new file mode 100644 index 0000000000..5f817e8e27 --- /dev/null +++ b/platform/bcm28xx/power/rules.mk @@ -0,0 +1,8 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/power.c \ + +include make/module.mk From 8166bb507e15b16de2a1a032fcad13bcdf8d064e Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sat, 16 Jan 2021 13:32:14 -0400 Subject: [PATCH 087/100] fix a missing include --- platform/bcm28xx/platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index b40dbec063..7aa6939a14 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include From 5f010196e431c563fdd3be2cacdebfefa315ec35 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 19 Mar 2021 12:57:36 -0300 Subject: [PATCH 088/100] implement the VEC in ntsc mode --- platform/bcm28xx/hvs/hvs.c | 71 +- .../hvs/include/platform/bcm28xx/hvs.h | 9 +- .../bcm28xx/include/platform/bcm28xx/pll.h | 6 + .../pixelvalve/include/platform/bcm28xx/pv.h | 3 + platform/bcm28xx/pixelvalve/pv.c | 11 +- .../vec/include/platform/bcm28xx/vec.h | 39 + platform/bcm28xx/vec/pi-logo.h | 4308 +++++++++++++++++ platform/bcm28xx/vec/rules.mk | 7 + platform/bcm28xx/vec/vec.c | 129 + project/rpi3-start.mk | 1 + 10 files changed, 4575 insertions(+), 9 deletions(-) create mode 100644 platform/bcm28xx/vec/include/platform/bcm28xx/vec.h create mode 100644 platform/bcm28xx/vec/pi-logo.h create mode 100644 platform/bcm28xx/vec/rules.mk create mode 100644 platform/bcm28xx/vec/vec.c diff --git a/platform/bcm28xx/hvs/hvs.c b/platform/bcm28xx/hvs/hvs.c index b4cc4b9fae..6d93123fca 100644 --- a/platform/bcm28xx/hvs/hvs.c +++ b/platform/bcm28xx/hvs/hvs.c @@ -4,6 +4,7 @@ #include #include #include +#include // note, 4096 slots total volatile uint32_t* dlist_memory = REG32(SCALER_LIST_MEMORY); @@ -31,11 +32,12 @@ static uint32_t gfx_to_hvs_pixel_format(gfx_format fmt) { } } -void hvs_add_plane(gfx_surface *fb, int x, int y) { +void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip) { dlist_memory[display_slot++] = CONTROL_VALID | CONTROL_WORDS(7) | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) -// | CONTROL0_VFLIP +// | CONTROL0_VFLIP // makes the HVS addr count down instead, pointer word must be last line of image + | (hflip ? CONTROL0_HFLIP : 0) | CONTROL_UNITY | CONTROL_FORMAT(gfx_to_hvs_pixel_format(fb->format)); dlist_memory[display_slot++] = POS0_X(x) | POS0_Y(y) | POS0_ALPHA(0xff); @@ -46,10 +48,58 @@ void hvs_add_plane(gfx_surface *fb, int x, int y) { dlist_memory[display_slot++] = fb->stride * fb->pixelsize; } +void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, int width, int height, bool hflip) { + int start = display_slot; + dlist_memory[display_slot++] = CONTROL_VALID + | CONTROL_WORDS(14) + | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) +// | CONTROL0_VFLIP // makes the HVS addr count down instead, pointer word must be last line of image + | (hflip ? CONTROL0_HFLIP : 0) + | CONTROL_FORMAT(gfx_to_hvs_pixel_format(fb->format)); + dlist_memory[display_slot++] = POS0_X(x) | POS0_Y(y) | POS0_ALPHA(0xff); + dlist_memory[display_slot++] = width | (height << 16); + dlist_memory[display_slot++] = POS2_H(fb->height) | POS2_W(fb->width); + dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state + dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0xc0000000; + dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state + dlist_memory[display_slot++] = fb->stride * fb->pixelsize; + dlist_memory[display_slot++] = 0x100; + +#if 0 + bool ppf = false; + if (ppf) { + uint32_t xscale = (1<<16) * fb->width / width; + uint32_t yscale = (1<<16) * fb->height / height; + + dlist_memory[display_slot++] = SCALER_PPF_AGC | (xscale << 8); + dlist_memory[display_slot++] = SCALER_PPF_AGC | (yscale << 8); + dlist_memory[display_slot++] = 0xDEADBEEF; //scaling context + } +#endif + bool tpz = true; + if (tpz) { + uint32_t xscale = (1<<16) * fb->width / width; + uint32_t yscale = (1<<16) * fb->height / height; + uint32_t xrecip = ~0 / xscale; + uint32_t yrecip = ~0 / yscale; + dlist_memory[display_slot++] = (xscale << 8); + dlist_memory[display_slot++] = xrecip; + dlist_memory[display_slot++] = (yscale << 8); + dlist_memory[display_slot++] = yrecip; + dlist_memory[display_slot++] = 0xDEADBEEF; //scaling context + } + printf("entry size: %d\n", display_slot - start); +} + void hvs_terminate_list(void) { dlist_memory[display_slot++] = CONTROL_END; } +static enum handler_return hvs_irq(void *unused) { + puts("hvs interrupt"); + return INT_NO_RESCHEDULE; +} + void hvs_initialize() { *REG32(SCALER_DISPCTRL) &= ~SCALER_DISPCTRL_ENABLE; // disable HVS *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE | 0x9a0dddff; // re-enable HVS @@ -68,11 +118,17 @@ void hvs_initialize() { *REG32(SCALER_DISPEOLN) = 0x40000000; } +void hvs_setup_irq() { + register_int_handler(33, hvs_irq, NULL); + unmask_interrupt(33); +} + void hvs_configure_channel(int channel, int width, int height) { - hvs_channels[0].dispctrl = SCALER_DISPCTRLX_RESET; - hvs_channels[0].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(width) | SCALER_DISPCTRL_H(height); + hvs_channels[channel].dispctrl = SCALER_DISPCTRLX_RESET; + hvs_channels[channel].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(width) | SCALER_DISPCTRL_H(height); - hvs_channels[0].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202; + hvs_channels[channel].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202 | SCALER_DISPBKGND_INTERLACE; + // the SCALER_DISPBKGND_INTERLACE flag makes the HVS alternate between sending even and odd scanlines } void hvs_wipe_displaylist(void) { @@ -84,6 +140,7 @@ void hvs_wipe_displaylist(void) { static int cmd_hvs_dump(int argc, const cmd_args *argv) { printf("SCALER_DISPCTRL: 0x%x\n", *REG32(SCALER_DISPCTRL)); + printf("SCALER_DISPSTAT: 0x%x\n", *REG32(SCALER_DISPSTAT)); printf("SCALER_DISPEOLN: 0x%08x\n", *REG32(SCALER_DISPEOLN)); printf("SCALER_DISPLIST0: 0x%x\n", *REG32(SCALER_DISPLIST0)); uint32_t list1 = *REG32(SCALER_DISPLIST1); @@ -91,6 +148,8 @@ static int cmd_hvs_dump(int argc, const cmd_args *argv) { printf("SCALER_DISPLIST2: 0x%x\n\n", *REG32(SCALER_DISPLIST2)); for (int i=0; i<3; i++) { printf("SCALER_DISPCTRL%d: 0x%x\n", i, hvs_channels[i].dispctrl); + printf(" width: %d\n", (hvs_channels[i].dispctrl >> 12) & 0xfff); + printf(" height: %d\n", hvs_channels[i].dispctrl & 0xfff); printf("SCALER_DISPBKGND%d: 0x%x\n", i, hvs_channels[i].dispbkgnd); uint32_t stat = hvs_channels[i].dispstat; printf("SCALER_DISPSTAT%d: 0x%x\n", i, stat); @@ -99,7 +158,7 @@ static int cmd_hvs_dump(int argc, const cmd_args *argv) { if (stat & (1<<28)) puts("empty"); printf("unknown: 0x%x\n", (stat >> 18) & 0x3ff); printf("frame count: %d\n", (stat >> 12) & 0x3f); - printf("line: %d\n", stat & 0xfff); + printf("line: %d\n", SCALER_STAT_LINE(stat)); uint32_t base = hvs_channels[i].dispbase; printf("SCALER_DISPBASE%d: base 0x%x top 0x%x\n\n", i, base & 0xffff, base >> 16); } diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index 385452def3..a33bb0847a 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -6,6 +6,7 @@ #define SCALER_BASE (BCM_PERIPH_BASE_VIRT + 0x400000) #define SCALER_DISPCTRL (SCALER_BASE + 0x00) +#define SCALER_DISPSTAT (SCALER_BASE + 0x04) #define SCALER_DISPCTRL_ENABLE (1<<31) #define SCALER_DISPEOLN (SCALER_BASE + 0x18) #define SCALER_DISPLIST0 (SCALER_BASE + 0x20) @@ -26,13 +27,17 @@ struct hvs_channel { extern volatile struct hvs_channel *hvs_channels; +#define SCALER_STAT_LINE(n) ((n) & 0xfff) + #define SCALER_DISPCTRL0 (SCALER_BASE + 0x40) #define SCALER_DISPCTRLX_ENABLE (1<<31) #define SCALER_DISPCTRLX_RESET (1<<30) #define SCALER_DISPCTRL_W(n) ((n & 0xfff) << 12) #define SCALER_DISPCTRL_H(n) (n & 0xfff) #define SCALER_DISPBKGND_AUTOHS (1<<31) +#define SCALER_DISPBKGND_INTERLACE (1<<30) #define SCALER_DISPBKGND_GAMMA (1<<29) +#define SCALER_DISPBKGND_FILL (1<<24) #define BASE_BASE(n) (n & 0xffff) #define BASE_TOP(n) ((n & 0xffff) << 16) @@ -97,8 +102,10 @@ enum hvs_pixel_format { extern int display_slot; extern volatile uint32_t* dlist_memory; -void hvs_add_plane(gfx_surface *fb, int x, int y); +void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip); +void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, int width, int height, bool hflip); void hvs_terminate_list(void); void hvs_wipe_displaylist(void); void hvs_initialize(void); void hvs_configure_channel(int channel, int width, int height); +void hvs_setup_irq(void); diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 3097bdf98e..8f8c1beb4c 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -1,5 +1,7 @@ #pragma once +#include + #define MHZ_TO_HZ(f) ((f)*1000*1000) enum pll { @@ -103,6 +105,10 @@ void switch_vpu_to_src(int src); #define CM_UARTCTL_ENAB_SET 0x00000010 #define CM_UARTDIV (CM_BASE + 0x0f4) +#define CM_VECCTL (CM_BASE + 0x0f8) +#define CM_VECCTL_ENAB_SET 0x00000010 +#define CM_VECDIV (CM_BASE + 0x0fc) + #define CM_OSCCOUNT (CM_BASE + 0x100) #define CM_PLLA (CM_BASE + 0x104) diff --git a/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h b/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h index 1ee3e8a982..372961ef0d 100644 --- a/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h +++ b/platform/bcm28xx/pixelvalve/include/platform/bcm28xx/pv.h @@ -5,6 +5,9 @@ struct pv_timings { uint16_t vfp, vsync, vbp, vactive; uint16_t hfp, hsync, hbp, hactive; + uint16_t vfp_even, vsync_even, vbp_even, vactive_even; + bool interlaced; + int clock_mux; }; struct pixel_valve { diff --git a/platform/bcm28xx/pixelvalve/pv.c b/platform/bcm28xx/pixelvalve/pv.c index 505453fcb0..b70b899f00 100644 --- a/platform/bcm28xx/pixelvalve/pv.c +++ b/platform/bcm28xx/pixelvalve/pv.c @@ -54,6 +54,11 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { rawpv->verta = (t->vbp << 16) | t->vsync; rawpv->vertb = (t->vfp << 16) | t->vactive; + if (t->interlaced) { + rawpv->verta_even = (t->vbp_even << 16) | t->vsync_even; + rawpv->vertb_even = (t->vfp << 16) | t->vactive_even; + } + #define CLK_SELECT(n) ((n & 3) << 2) # define PV_CONTROL_CLK_SELECT_DSI 0 # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 @@ -62,7 +67,8 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { #define FIFO_LEVEL(n) ((n & 0x3f) << 15) rawpv->vc = BV(0) | // video enable - BV(1); // continous + BV(1)| // continous + (t->interlaced ? BV(4) : 0); rawpv->h_active = t->hactive; @@ -71,7 +77,8 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { rawpv->c = PV_CONTROL_EN | PV_CONTROL_FIFO_CLR | - CLK_SELECT(PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI) | // set to DPI clock + //CLK_SELECT(PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI) | // set to DPI clock + CLK_SELECT(PV_CONTROL_CLK_SELECT_VEC) | // vec PIXEL_REP(1 - 1) | BV(12) | // wait for h-start BV(13) | // trigger underflow diff --git a/platform/bcm28xx/vec/include/platform/bcm28xx/vec.h b/platform/bcm28xx/vec/include/platform/bcm28xx/vec.h new file mode 100644 index 0000000000..82ed0f91a7 --- /dev/null +++ b/platform/bcm28xx/vec/include/platform/bcm28xx/vec.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#define BIT(n) (1 << n) + +#define VEC_BASE (BCM_PERIPH_BASE_VIRT + 0x806000) + +#define VEC_WSE_RESET (VEC_BASE + 0x0c0) +#define VEC_WSE_CONTROL (VEC_BASE + 0x0c4) +#define VEC_CONFIG0 (VEC_BASE + 0x104) +#define VEC_CONFIG0_NTSC_STD 0 +#define VEC_CONFIG0_PAL_BDGHI_STD 1 +#define VEC_CONFIG0_PDEN BIT(6) +#define VEC_SCHPH (VEC_BASE + 0x108) +#define VEC_SOFT_RESET (VEC_BASE + 0x10c) +#define VEC_CLMP0_START (VEC_BASE + 0x144) +#define VEC_CLMP0_END (VEC_BASE + 0x148) +#define VEC_FREQ3_2 (VEC_BASE + 0x180) +#define VEC_FREQ1_0 (VEC_BASE + 0x184) +#define VEC_CONFIG1 (VEC_BASE + 0x188) +#define VEC_CONFIG1_CUSTOM_FREQ BIT(0) +#define VEC_CONFIG1_C_CVBS_CVBS (7 << 10) +#define VEC_CONFIG2 (VEC_BASE + 0x18c) +#define VEC_CONFIG2_UV_DIG_DIS BIT(6) +#define VEC_CONFIG2_RGB_DIG_DIS BIT(5) +#define VEC_CONFIG3 (VEC_BASE + 0x1a0) +#define VEC_CONFIG3_HORIZ_LEN_STD (0 << 0) +#define VEC_MASK0 (VEC_BASE + 0x204) +#define VEC_CFG (VEC_BASE + 0x208) +#define VEC_CFG_VEC_EN BIT(3) +#define VEC_DAC_CONFIG (VEC_BASE + 0x210) +#define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24) +#define VEC_DAC_CONFIG_DRIVER_CTRL(x) ((x) << 16) +#define VEC_DAC_CONFIG_DAC_CTRL(x) (x) +#define VEC_DAC_MISC (VEC_BASE + 0x214) +#define VEC_DAC_MISC_DAC_RST_N BIT(0) +#define VEC_DAC_MISC_VID_ACT BIT(8) diff --git a/platform/bcm28xx/vec/pi-logo.h b/platform/bcm28xx/vec/pi-logo.h new file mode 100644 index 0000000000..4bb62c365d --- /dev/null +++ b/platform/bcm28xx/vec/pi-logo.h @@ -0,0 +1,4308 @@ +uint8_t pilogo[] = { +0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, 0x01, 0x6c, 0x02, +0x20, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, +0x40, 0x00, 0x00, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x70, +0x83, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xed, +0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, +0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x80, 0x00, +0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xef, 0x96, 0x00, 0x00, 0x00, 0xff, +0x05, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, +0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, +0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, +0x00, 0xef, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x9f, +0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0xfb, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, +0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xef, 0xae, 0x00, 0x00, +0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0x10, 0xfb, 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, +0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xef, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, +0x00, 0xcf, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x30, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xda, +0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, +0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xcf, 0xbd, 0x00, 0x00, 0x00, 0xff, +0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x50, 0xfc, 0x00, 0x00, +0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xcf, 0xc3, 0x00, +0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x30, +0xfc, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xce, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xaf, 0xc9, 0x00, 0x00, +0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x10, 0xfc, +0x00, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, +0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xdf, +0xce, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x30, 0xfd, 0x00, +0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xd3, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x50, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0x9f, 0xd7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, +0x00, 0x00, 0x00, 0x60, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, +0xbf, 0xdb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x60, 0xfd, +0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xdf, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x50, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xc6, +0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0xe3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xbf, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, +0x00, 0xef, 0xe6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x20, +0xfd, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbe, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xcf, 0xe9, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x70, 0xfd, 0x00, 0x00, 0x00, 0x00, +0xc1, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0xed, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xcf, 0x00, 0x00, 0x00, 0x30, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0xef, 0xf0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, +0x10, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xb9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xaf, 0xf3, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x00, 0x00, 0x00, +0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xef, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, +0x03, 0x19, 0xff, 0x86, 0x12, 0x06, 0x31, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xb6, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, +0xaf, 0x00, 0x00, 0x00, 0xff, 0x05, 0x09, 0x03, 0x19, 0xff, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, +0x62, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x37, 0x13, 0x93, 0xff, 0x37, 0x13, 0x93, 0xff, 0x8e, 0x49, +0x19, 0xc4, 0xff, 0x06, 0x44, 0x17, 0xb8, 0xff, 0x37, 0x13, 0x93, 0xff, 0x37, 0x13, 0x93, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x20, 0xfd, 0x00, +0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcf, 0xab, 0x00, 0x00, 0x00, 0xff, +0x04, 0x05, 0x02, 0x0c, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, +0xff, 0x44, 0x17, 0xb8, 0xff, 0x9b, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x44, 0x17, 0xb8, 0xff, 0x32, +0x11, 0x87, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x60, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x50, 0x00, 0x00, 0x00, 0xef, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x02, 0x12, 0x06, 0x31, 0xff, +0x29, 0x0e, 0x6e, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x37, 0x13, +0x93, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x9f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xa8, 0x00, 0x00, +0x00, 0xff, 0x02, 0x17, 0x08, 0x3d, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xab, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, 0xac, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x0e, 0x05, 0x25, +0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x20, 0xfd, +0x00, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xbf, 0xa6, 0x00, 0x00, 0x00, +0xff, 0x02, 0x17, 0x08, 0x3d, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xb1, 0x49, +0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, 0xac, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x0e, 0x05, 0x25, 0xff, +0xa4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xfd, 0x00, +0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xcf, 0xa4, 0x00, 0x00, 0x00, 0xff, +0x02, 0x09, 0x03, 0x19, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x40, 0x16, 0xac, 0xff, 0xb7, 0x49, 0x19, +0xc4, 0xff, 0x02, 0x3b, 0x14, 0x9f, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa3, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0xef, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, +0x32, 0x11, 0x87, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x29, 0x0e, +0x6e, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, +0xfe, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xae, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, +0x09, 0x4a, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, +0xff, 0x12, 0x06, 0x31, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, +0x00, 0x00, 0x10, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xa2, 0x00, 0x00, 0x00, +0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xc5, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa1, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xc9, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x20, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x9f, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x40, 0x16, 0xac, 0xff, +0xcd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9e, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xfd, 0x00, 0x00, 0x00, +0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xbf, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x05, 0x25, 0xff, 0x37, 0x13, 0x93, 0xff, 0xd1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x25, 0x0d, 0x62, +0xff, 0x05, 0x02, 0x0c, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, +0x00, 0x00, 0x30, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, +0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0xd4, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x9d, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xab, +0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xd7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x09, +0x03, 0x19, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x30, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xa6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x9d, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, 0xdb, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, +0x00, 0x00, 0x00, 0x30, 0xfd, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, +0x9f, 0x00, 0x00, 0x00, 0xef, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x0b, 0x56, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, +0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, 0x00, +0x00, 0x00, 0x10, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x8f, +0x00, 0x00, 0x00, 0xef, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, 0x13, +0x93, 0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, +0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x50, 0xfd, 0x00, +0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xcf, 0xa0, +0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe3, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, +0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x00, 0x00, +0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xef, 0xa1, 0x00, +0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xe6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, +0xac, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, +0x00, 0x00, 0x00, 0x60, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0xcf, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xe9, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x00, 0x00, 0x00, 0x00, +0x9d, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x02, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xef, 0xa3, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xeb, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, +0x00, 0x40, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xa5, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xed, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x60, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0xaf, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, +0xf0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa4, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x60, 0xfd, 0x00, 0x00, 0x00, +0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbf, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0xf2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, +0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x70, 0x00, +0x00, 0x00, 0x10, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbf, +0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xf4, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x92, +0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbf, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xf6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa7, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x70, 0xfd, 0x00, 0x00, +0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbf, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0xf8, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x60, +0xfd, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x89, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xab, 0x00, 0x00, +0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x0e, 0x05, 0x25, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, +0x00, 0x00, 0x50, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, +0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xbf, 0x00, 0x00, 0x00, 0x40, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, +0x00, 0x00, 0xef, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x20, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x50, 0x00, 0x00, 0x00, 0xdf, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x37, 0x13, 0x93, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x80, +0x00, 0x00, 0x00, 0x10, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, +0xbf, 0xaf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x50, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0x80, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xae, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x20, 0xfd, 0x00, 0x00, 0x00, 0x00, +0x83, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0xdf, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xaf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0xfd, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xaf, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, +0x0e, 0x6e, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, +0x40, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xef, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, +0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x88, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, +0x19, 0xff, 0xb1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x10, +0xfc, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, +0x00, 0x00, 0xbf, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x88, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb2, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x50, 0xfb, 0x00, 0x00, 0x00, 0x00, 0xf9, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, +0x16, 0xac, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, +0x19, 0xff, 0xb3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x20, +0xf9, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, +0x00, 0x00, 0xcf, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0xb9, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xbf, 0x00, 0x00, 0x00, 0x10, 0xf6, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xbf, 0xba, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, +0x19, 0xc4, 0xff, 0x8a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xb6, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x50, 0xf5, 0x00, 0x00, 0x00, 0x00, +0xf3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xef, 0xbb, 0x00, +0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8a, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xaf, 0x00, 0x00, 0x00, 0x10, 0xf3, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xaf, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xb9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x40, 0xf2, +0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, +0x00, 0xef, 0xbe, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xfd, 0x49, 0x19, 0xc4, 0xff, 0x8a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xbb, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xf1, 0x00, 0x00, 0x00, 0x00, 0xee, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0xc1, 0x00, 0x00, 0x00, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0xbc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, +0x00, 0x00, 0x30, 0xef, 0x00, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x30, 0x00, 0x00, 0x00, 0xcf, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xbe, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x60, 0xee, 0x00, 0x00, +0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xef, +0xc4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xfd, 0x49, +0x19, 0xc4, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xc0, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x10, 0xec, 0x00, 0x00, 0x00, 0x00, +0xea, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xaf, 0xc7, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xfd, 0x49, 0x19, 0xc4, +0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xc1, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x30, 0xeb, 0x00, 0x00, +0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xdf, +0xc9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xfd, 0x49, +0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xc4, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0xea, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xcd, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x1b, 0x09, +0x4a, 0xff, 0xc6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x10, +0xe8, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, +0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xcf, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc8, +0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, +0x50, 0xe6, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xcf, 0xd3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, +0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, +0x17, 0x08, 0x3d, 0xff, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, +0x00, 0x8f, 0x00, 0x00, 0x00, 0x20, 0xe3, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, +0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xef, 0xd7, 0x00, 0x00, +0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x37, 0x13, 0x93, 0xff, 0xf7, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x37, 0x13, 0x93, 0xff, 0x09, 0x03, 0x19, 0xff, 0xd0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x40, 0xe1, 0x00, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xdc, 0x00, 0x00, 0x00, 0xff, 0x01, +0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xf3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, 0xd4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, +0x00, 0x00, 0x00, 0x40, 0xdf, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, +0xff, 0x40, 0x16, 0xac, 0xff, 0xf0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, +0x03, 0x19, 0xff, 0xd7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0x40, 0xdd, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0x80, 0xe4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x32, 0x11, +0x87, 0xff, 0xec, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, +0xdb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x30, 0xdb, 0x00, +0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, +0xef, 0xe7, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, 0x19, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xe7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, +0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x10, 0xd9, +0x00, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, +0x00, 0xcf, 0xec, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x32, 0x11, 0x87, 0xff, +0xe2, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, 0xac, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xe2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x70, +0xd8, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x8f, 0xf0, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x1b, 0x09, 0x4a, +0xff, 0x32, 0x11, 0x87, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x17, +0x08, 0x3d, 0xff, 0xe7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, +0x30, 0xd6, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, +0x00, 0x00, 0x00, 0xdf, 0xf4, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x02, 0x0c, 0xff, 0x1b, 0x09, +0x4a, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xeb, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd5, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0xfa, 0x00, 0x00, 0x00, 0xff, 0x02, 0x12, +0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, +0x02, 0x40, 0x16, 0xac, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xf0, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x30, 0xd3, 0x00, 0x00, 0x00, 0x00, +0xd1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xdf, 0xfd, 0x00, +0x00, 0x00, 0xff, 0x04, 0x00, 0x00, 0x00, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x17, 0x08, 0x3d, 0xff, +0x29, 0x0e, 0x6e, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc7, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x44, 0x17, +0xb8, 0xff, 0x32, 0x11, 0x87, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xb5, 0x00, +0x00, 0x00, 0xff, 0x05, 0x05, 0x02, 0x0c, 0xff, 0x12, 0x06, 0x31, 0xff, 0x17, 0x08, 0x3d, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x84, 0x37, 0x13, 0x93, +0xff, 0x05, 0x29, 0x0e, 0x6e, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, +0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0xd2, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x80, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x03, 0x12, 0x06, +0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x32, 0x11, 0x87, 0xff, 0x40, 0x16, 0xac, 0xff, 0xbe, 0x49, +0x19, 0xc4, 0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x20, 0x0b, 0x56, 0xff, +0x0e, 0x05, 0x25, 0xff, 0xb5, 0x00, 0x00, 0x00, 0xff, 0x03, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, +0x62, 0xff, 0x37, 0x13, 0x93, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x91, 0x49, 0x19, 0xc4, 0xff, 0x04, +0x40, 0x16, 0xac, 0xff, 0x32, 0x11, 0x87, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, +0x05, 0x02, 0x0c, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, +0x00, 0x10, 0xd0, 0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0xbf, 0xad, 0x00, 0x00, 0x00, 0xff, 0x07, 0x05, 0x02, 0x0c, 0xff, 0x12, +0x06, 0x31, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x37, +0x13, 0x93, 0xff, 0x37, 0x13, 0x93, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, +0x06, 0x3b, 0x14, 0x9f, 0xff, 0x37, 0x13, 0x93, 0xff, 0x37, 0x13, 0x93, 0xff, 0x29, 0x0e, 0x6e, +0xff, 0x25, 0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0x09, 0x03, 0x19, 0xff, 0xc8, 0x00, 0x00, +0x00, 0xff, 0x04, 0x05, 0x02, 0x0c, 0xff, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x3b, 0x14, 0x9f, +0xff, 0x2e, 0x10, 0x7b, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x17, 0x08, 0x3d, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, +0x17, 0xb8, 0xff, 0x9a, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x3b, 0x14, 0x9f, 0xff, 0x29, 0x0e, 0x6e, +0xff, 0x17, 0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x40, 0xcf, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xef, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x03, +0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x32, 0x11, 0x87, 0xff, 0x40, 0x16, 0xac, 0xff, +0x93, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x44, 0x17, 0xb8, 0xff, 0x32, 0x11, 0x87, 0xff, 0x20, 0x0b, +0x56, 0xff, 0x09, 0x03, 0x19, 0xff, 0xca, 0x00, 0x00, 0x00, 0xff, 0x05, 0x09, 0x03, 0x19, 0xff, +0x12, 0x06, 0x31, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, 0xff, +0x37, 0x13, 0x93, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x05, 0x3b, 0x14, 0x9f, 0xff, 0x37, 0x13, +0x93, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xb9, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, 0x19, 0xff, 0x29, 0x0e, 0x6e, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, +0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, +0xce, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xa8, +0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x05, 0x25, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x37, 0x13, 0x93, +0xff, 0x9c, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x3b, 0x14, 0x9f, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x05, 0x25, 0xff, 0x12, 0x06, 0x31, +0xff, 0x17, 0x08, 0x3d, 0xff, 0x82, 0x25, 0x0d, 0x62, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x89, +0x37, 0x13, 0x93, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, +0x14, 0x9f, 0xff, 0x83, 0x37, 0x13, 0x93, 0xff, 0x06, 0x2e, 0x10, 0x7b, 0xff, 0x25, 0x0d, 0x62, +0xff, 0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0x12, 0x06, 0x31, +0xff, 0x05, 0x02, 0x0c, 0xff, 0xbe, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0xa7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, +0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x10, 0xcc, +0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa6, 0x00, +0x00, 0x00, 0xff, 0x02, 0x0e, 0x05, 0x25, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x40, 0x16, 0xac, 0xff, +0xa1, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, +0x19, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x0b, 0x56, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xcf, 0x00, 0x00, 0x00, 0x30, 0xcb, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, +0x19, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x40, 0x16, 0xac, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0xae, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, 0x13, 0x93, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x40, 0xca, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xdf, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, +0x12, 0x06, 0x31, 0xff, 0x32, 0x11, 0x87, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, +0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, +0x16, 0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x60, 0xc9, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0xef, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, +0xac, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x00, 0x00, 0x00, +0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb5, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x40, 0x16, 0xac, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x80, 0xc8, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x50, 0x00, 0x00, 0x00, 0xef, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, +0x40, 0x16, 0xac, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfe, 0x00, +0x00, 0x00, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb8, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x9f, 0xc7, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, +0xac, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, +0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x32, 0x11, 0x87, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x9f, 0xc6, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xb6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0xfd, 0x00, +0x00, 0x00, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xbc, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x10, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, +0x19, 0xff, 0x32, 0x11, 0x87, 0xff, 0xb9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0xfe, 0x00, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xbf, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x9d, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xc3, 0x00, 0x00, 0x00, 0x00, +0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, +0x20, 0x0b, 0x56, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, +0x19, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xc2, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, +0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0xfe, 0x00, 0x00, 0x00, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xc3, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x9c, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xc2, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xc0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xa1, +0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x9f, 0xc1, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, +0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc1, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xa1, 0x00, 0x00, +0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xc6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, +0xff, 0x05, 0x02, 0x0c, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xc0, +0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x00, 0xef, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xa1, +0x00, 0x00, 0x00, 0xff, 0xc8, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, +0x25, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xbf, 0x00, 0x00, 0x00, +0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x9c, +0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xc5, 0x49, 0x19, 0xc4, 0xff, 0xff, 0x00, +0x00, 0x00, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xc9, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x60, 0xbe, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, +0x0c, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0xfe, 0x00, 0x00, 0x00, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xcb, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x40, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xbf, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xc7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x9f, +0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xcc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x30, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, +0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xc8, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x9f, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xcd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, +0xff, 0x05, 0x02, 0x0c, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, +0x00, 0x00, 0x10, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xca, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, +0xcf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x99, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0x9a, 0x00, 0x00, 0x00, 0xff, +0x00, 0x1b, 0x09, 0x4a, 0xff, 0xcc, 0x49, 0x19, 0xc4, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x9e, +0x00, 0x00, 0x00, 0xff, 0xd0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xba, 0x00, 0x00, 0x00, +0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x9a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xcd, 0x49, 0x19, 0xc4, 0xff, 0xcd, 0x00, +0x00, 0x00, 0xff, 0x88, 0x12, 0x06, 0x31, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xc5, 0x00, 0x00, +0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xd1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, +0xff, 0x05, 0x02, 0x0c, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb9, +0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x9a, 0x00, +0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xce, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x05, 0x0e, 0x05, 0x25, 0xff, 0x17, 0x08, 0x3d, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x37, 0x13, 0x93, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0x8e, 0x49, 0x19, 0xc4, 0xff, 0x06, 0x40, 0x16, 0xac, 0xff, 0x37, 0x13, 0x93, 0xff, 0x32, 0x11, +0x87, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x12, 0x06, 0x31, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xbc, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xd2, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xbe, 0x00, 0x00, 0x00, 0xff, +0x03, 0x0e, 0x05, 0x25, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x3b, 0x14, 0x9f, +0xff, 0x9c, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x32, 0x11, 0x87, 0xff, 0x25, +0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x99, 0x00, 0x00, 0x00, +0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xd0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0xba, 0x00, 0x00, 0x00, 0xff, 0x03, 0x09, 0x03, 0x19, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, +0x87, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x37, 0x13, 0x93, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, +0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xb6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0xd1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb7, 0x00, 0x00, +0x00, 0xff, 0x02, 0x09, 0x03, 0x19, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xac, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x17, 0x08, 0x3d, +0xff, 0xb1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xd5, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, +0x00, 0x00, 0x30, 0xb6, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x70, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xd2, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, +0x20, 0x0b, 0x56, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, +0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x98, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xb6, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, 0x00, 0xff, +0x00, 0x1b, 0x09, 0x4a, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb2, +0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xb8, 0x49, 0x19, +0xc4, 0xff, 0x02, 0x3b, 0x14, 0x9f, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xab, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xd7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, +0x0e, 0x6e, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0xb5, 0x00, 0x00, +0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x98, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x29, 0x0e, 0x6e, 0xff, +0x09, 0x03, 0x19, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xd8, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x20, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x60, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xae, 0x00, 0x00, +0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, +0xc5, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa5, 0x00, +0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, +0xb3, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, +0x05, 0x25, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x40, 0x16, 0xac, +0xff, 0xc8, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, +0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, +0x00, 0x00, 0x00, 0x10, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd7, 0x49, 0x19, +0xc4, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, +0xcc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa3, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0xd8, 0x49, 0x19, 0xc4, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x25, 0x0d, 0x62, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x09, 0x03, 0x19, +0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xdb, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x20, 0x0b, 0x56, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, +0x00, 0x00, 0x20, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x40, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xd7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x9f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xd8, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9e, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, +0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x20, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, 0x13, +0x93, 0xff, 0xd8, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, +0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x32, 0x11, 0x87, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xb0, 0x00, +0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xdb, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xde, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x9f, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xdb, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, +0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xae, 0x00, 0x00, +0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0x00, 0x00, 0x00, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0xdf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xaf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xdb, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x37, 0x13, 0x93, 0xff, 0xe4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x0e, 0x05, 0x25, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xdf, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0xad, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0xdb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xe6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, +0xe0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0xad, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x8f, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xdc, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x3b, 0x14, 0x9f, 0xff, 0xe8, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, +0x05, 0x25, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xe1, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xdf, 0xad, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, +0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x9c, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xea, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x40, 0x16, 0xac, 0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x95, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0xac, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9c, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xec, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, +0x0e, 0x05, 0x25, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xe1, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0xaf, 0xac, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xbf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xee, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xab, 0x00, 0x00, 0x00, 0x00, +0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x0e, 0x05, 0x25, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x9a, 0x00, +0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xf0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, +0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, +0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x70, 0xab, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x70, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xdc, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0xf2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x3b, 0x14, 0x9f, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x94, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xab, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, +0x0c, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x99, 0x00, 0x00, 0x00, +0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xf3, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xe2, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x30, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x30, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x17, 0x08, 0x3d, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xf5, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, +0x05, 0x25, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xf6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xe1, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, +0xaa, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x95, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xf8, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x30, 0xa9, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x20, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xdd, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, +0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, +0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0xa9, 0x00, +0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, +0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, +0x17, 0xb8, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa9, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, +0x0e, 0x05, 0x25, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa8, 0x00, 0x00, 0x00, +0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, +0x03, 0x19, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xe2, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x50, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x3b, 0x14, 0x9f, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xdd, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, +0x16, 0xac, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, 0x12, 0x06, 0x31, +0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x09, 0x03, 0x19, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xa8, +0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x95, 0x00, +0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, +0x93, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xe2, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, +0xa7, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x95, +0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, +0x0e, 0x6e, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x90, 0x00, 0x00, 0x00, +0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xa6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, +0x05, 0x25, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, +0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x60, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xdc, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, +0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x05, 0x02, 0x0c, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa7, 0x00, +0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x93, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0xa7, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0xff, 0xdc, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x8f, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe0, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x10, 0xa6, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x90, 0x00, 0x00, +0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa6, 0x00, 0x00, 0x00, 0x00, +0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xdb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x87, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, +0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x70, 0xa6, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x40, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xdb, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x88, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, +0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xa6, 0x00, 0x00, 0x00, 0x00, 0xa5, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, +0x17, 0xb8, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, +0xe0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xbf, 0xa6, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x8f, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xdb, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, +0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xdf, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xa6, 0x00, +0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x8a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, +0x09, 0x03, 0x19, 0xff, 0xdf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x94, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8a, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xd9, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, +0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xef, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xef, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xd8, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa4, 0x00, +0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xd7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x09, 0x03, 0x19, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, +0x49, 0x19, 0xc4, 0xff, 0x8c, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xdc, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, +0xa4, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x96, +0x00, 0x00, 0x00, 0xff, 0xd8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9a, 0x00, +0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8c, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x10, 0xa3, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x10, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xd7, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x8c, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, +0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x60, 0xa3, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xd6, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9a, 0x00, 0x00, 0x00, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xdc, +0x49, 0x19, 0xc4, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xa3, 0x00, +0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x8d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0xdb, 0x49, 0x19, 0xc4, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x20, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x20, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd5, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x94, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xda, 0x49, 0x19, +0xc4, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xa2, 0x00, 0x00, 0x00, +0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x97, 0x00, 0x00, 0x00, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, +0x02, 0x0c, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, +0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, +0xa2, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x9e, 0x00, 0x00, 0x00, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xd8, 0x49, 0x19, 0xc4, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x9f, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd2, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x20, 0x0b, 0x56, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, +0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x96, 0x00, +0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xd8, 0x49, 0x19, 0xc4, 0xff, 0x98, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xd1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, +0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xd7, 0x49, 0x19, +0xc4, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa0, 0x00, 0x00, 0x00, +0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x99, 0x00, 0x00, 0x00, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0xd0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa1, +0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, +0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, +0xa0, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x99, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x9a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0xce, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xa2, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xd4, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x60, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x60, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xcd, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, +0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9a, 0x00, 0x00, +0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x9f, 0x00, 0x00, 0x00, 0x00, +0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xcc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, +0xd2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x20, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xcb, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xd1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x60, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xca, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa6, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xd0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0xc9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa7, +0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, +0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x9d, 0x00, 0x00, 0x00, 0xff, 0xc8, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa8, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, +0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x12, 0x06, 0x31, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9d, 0x00, +0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9d, 0x00, 0x00, +0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xc6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, +0xff, 0x05, 0x02, 0x0c, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, +0x49, 0x19, 0xc4, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0xce, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x9c, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0xc5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xcd, 0x49, 0x19, +0xc4, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x9c, 0x00, 0x00, 0x00, +0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x9d, 0x00, 0x00, 0x00, 0xff, +0x00, 0x29, 0x0e, 0x6e, 0xff, 0xc4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xac, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8d, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0xcb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9e, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x50, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc3, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, +0x02, 0x0c, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xca, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x9c, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x9e, +0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, 0xaf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8c, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, +0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc9, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0x9c, 0x00, +0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x9f, 0x00, 0x00, +0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, +0xff, 0x0e, 0x05, 0x25, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, +0x49, 0x19, 0xc4, 0xff, 0x8c, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xa5, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0x9b, 0x00, 0x00, 0x00, +0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xb1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xa7, 0x00, 0x00, 0x00, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, +0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x9a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, +0x08, 0x3d, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb3, 0x00, 0x00, +0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8b, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0xc5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xba, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, 0xb4, 0x00, 0x00, 0x00, 0xff, +0x00, 0x05, 0x02, 0x0c, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc4, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x9b, 0x00, 0x00, +0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xa1, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, +0x05, 0x02, 0x0c, 0xff, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x8a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xaa, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9a, 0x00, 0x00, 0x00, 0x00, +0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, +0x0e, 0x05, 0x25, 0xff, 0xb8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xb8, 0x00, +0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x80, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb5, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xb9, 0x00, 0x00, 0x00, +0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x89, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x29, 0x0e, 0x6e, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc0, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x9f, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb4, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xbc, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x88, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xae, +0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbe, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, +0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xa4, 0x00, 0x00, 0x00, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x0e, +0x05, 0x25, 0xff, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xb0, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x0e, 0x05, 0x25, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x99, 0x00, +0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa5, 0x00, 0x00, +0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0xbf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xfe, +0x49, 0x19, 0xc4, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xb1, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xbb, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, +0x99, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa6, +0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x29, +0x0e, 0x6e, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xc1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, +0xb2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, 0x13, 0x93, 0xff, 0xba, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x9f, 0x99, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x80, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x32, 0x11, 0x87, 0xff, 0x09, 0x03, 0x19, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0xb5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb9, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, +0x99, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xa7, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa7, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0xc6, 0x00, 0x00, 0x00, 0xff, +0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xb7, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x99, 0x00, 0x00, +0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, +0xa8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa4, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0xc8, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x40, 0x16, 0xac, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xb5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa6, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0x98, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, +0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xca, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, +0xff, 0x3b, 0x14, 0x9f, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0x00, 0x00, +0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xac, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x9d, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x3b, 0x14, 0x9f, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xcd, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, +0x49, 0x19, 0xc4, 0xff, 0x40, 0x16, 0xac, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, +0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xa8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0x96, 0x00, +0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xaf, 0x00, 0x00, +0x00, 0xff, 0x02, 0x09, 0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x97, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, 0xac, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x0e, 0x05, 0x25, +0xff, 0xd0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xfd, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x1b, 0x09, 0x4a, +0xff, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xb0, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x10, 0x95, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, +0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, 0x87, 0xff, 0x92, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x32, 0x11, +0x87, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xd4, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xbf, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xae, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, +0x95, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xb6, +0x00, 0x00, 0x00, 0xff, 0x04, 0x05, 0x02, 0x0c, 0xff, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, +0xff, 0x32, 0x11, 0x87, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x3b, +0x14, 0x9f, 0xff, 0x37, 0x13, 0x93, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x0e, +0x05, 0x25, 0xff, 0xd8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, +0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xc1, 0x00, 0x00, 0x00, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x94, 0x00, 0x00, +0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, +0xfd, 0x00, 0x00, 0x00, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfc, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x93, 0x00, 0x00, 0x00, 0x00, +0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xa5, +0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, +0x03, 0x19, 0xff, 0xc5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa8, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xaf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x30, 0x92, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, +0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xc7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, 0xa5, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0xb0, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x91, 0x00, 0x00, 0x00, 0x00, +0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x82, 0x25, 0x0d, 0x62, 0xff, 0x00, 0x0e, 0x05, +0x25, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xf8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xca, 0x00, 0x00, 0x00, 0xff, +0x01, 0x17, 0x08, 0x3d, 0xff, 0x40, 0x16, 0xac, 0xff, 0xa3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, +0x08, 0x3d, 0xff, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x91, 0x00, 0x00, +0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, +0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x84, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xfd, 0x00, 0x00, 0x00, +0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xf7, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x0e, 0x05, 0x25, 0xff, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb4, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0x88, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, +0x00, 0x00, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, +0xff, 0xf5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xce, 0x00, 0x00, 0x00, 0xff, +0x02, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x40, 0x16, 0xac, 0xff, 0x9c, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, +0x01, 0x17, 0x08, 0x3d, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x82, 0x37, 0x13, 0x93, 0xff, 0x01, 0x25, +0x0d, 0x62, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x10, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x50, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x8a, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xfd, 0x00, 0x00, 0x00, +0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xf4, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xd2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0x99, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x09, 0x03, 0x19, +0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x40, 0x16, 0xac, 0xff, 0x85, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9b, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0x8c, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, +0x19, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xf2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xd4, +0x00, 0x00, 0x00, 0xff, 0x02, 0x12, 0x06, 0x31, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, +0xff, 0x94, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0x92, +0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x89, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x8e, 0x00, 0x00, +0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x99, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, +0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, +0x11, 0x87, 0xff, 0xf0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, +0xff, 0xd8, 0x00, 0x00, 0x00, 0xff, 0x02, 0x17, 0x08, 0x3d, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x40, +0x16, 0xac, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, +0xff, 0x0e, 0x05, 0x25, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x8b, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0x90, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x83, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xef, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xdc, 0x00, 0x00, 0x00, 0xff, 0x04, 0x09, 0x03, 0x19, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x37, 0x13, 0x93, 0xff, 0x40, 0x16, 0xac, +0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x3b, 0x14, 0x9f, 0xff, 0x32, 0x11, 0x87, 0xff, 0x25, +0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xaf, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xdf, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0x92, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfe, 0x00, 0x00, 0x00, +0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, 0xed, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x82, 0x00, +0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x8f, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8c, 0x00, 0x00, 0x00, +0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x98, 0x00, 0x00, 0x00, 0xff, +0x00, 0x17, 0x08, 0x3d, 0xff, 0x93, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, +0x03, 0x19, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, +0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xeb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0xfe, 0x00, 0x00, 0x00, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x91, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xdf, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, +0x44, 0x17, 0xb8, 0xff, 0x94, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x00, +0x00, 0x00, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, +0xff, 0xe9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, +0x82, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x92, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x70, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x96, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x84, 0x00, +0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe7, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0x93, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, +0x05, 0x25, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x10, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, +0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x97, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x85, 0x00, 0x00, +0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe5, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x00, +0x17, 0x08, 0x3d, 0xff, 0x95, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x8a, 0x00, 0x00, 0x00, +0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0x99, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, +0x00, 0x00, 0x00, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x40, 0x16, +0xac, 0xff, 0xe3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, +0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, 0x96, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x20, 0x89, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x40, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, +0x99, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, +0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, +0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, +0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x98, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x89, 0x00, +0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x9b, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x32, 0x11, 0x87, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x44, 0x17, 0xb8, 0xff, 0x98, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, +0x03, 0x19, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x88, 0x00, 0x00, +0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0x00, 0x00, 0x00, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9c, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, +0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0x9a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x9f, 0x88, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x9d, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0x00, +0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x9b, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x87, 0x00, 0x00, 0x00, 0x00, +0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0x9e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfe, 0x00, +0x00, 0x00, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, +0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xfd, +0x00, 0x00, 0x00, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9c, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x97, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x87, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, +0x16, 0xac, 0xff, 0x9f, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xcf, 0x00, 0x00, +0x00, 0xff, 0x04, 0x0e, 0x05, 0x25, 0xff, 0x12, 0x06, 0x31, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x25, +0x0d, 0x62, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x88, 0x37, 0x13, 0x93, 0xff, 0x04, 0x2e, 0x10, 0x7b, +0xff, 0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x12, 0x06, 0x31, +0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x37, 0x13, 0x93, 0xff, 0x09, 0x03, 0x19, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x89, 0x00, +0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x9d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, +0x6e, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, +0x86, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, +0x11, 0x87, 0xff, 0xca, 0x00, 0x00, 0x00, 0xff, 0x03, 0x0e, 0x05, 0x25, 0xff, 0x20, 0x0b, 0x56, +0xff, 0x2e, 0x10, 0x7b, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x94, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x44, +0x17, 0xb8, 0xff, 0x37, 0x13, 0x93, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x09, +0x03, 0x19, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x37, 0x13, 0x93, +0xff, 0xd0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, 0xfd, +0x00, 0x00, 0x00, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9f, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x60, 0x86, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa1, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xc5, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, +0x02, 0x0c, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, 0x87, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x9d, +0x49, 0x19, 0xc4, 0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x1b, 0x09, 0x4a, +0xff, 0x09, 0x03, 0x19, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x0b, 0x56, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xcd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, +0x9f, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xdf, 0x86, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xdf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xa2, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xc2, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x3b, +0x14, 0x9f, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xca, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, +0x14, 0x9f, 0xff, 0x12, 0x06, 0x31, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0x89, 0x12, 0x06, 0x31, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xcf, 0x00, 0x00, 0x00, 0xff, +0x00, 0x0e, 0x05, 0x25, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x85, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xa2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xc0, 0x00, 0x00, 0x00, +0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x3b, 0x14, 0x9f, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9c, 0x00, 0x00, 0x00, +0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc6, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x40, 0x16, 0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x04, 0x12, 0x06, +0x31, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, 0xff, 0x37, 0x13, +0x93, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x40, 0x16, 0xac, 0xff, 0x37, 0x13, 0x93, 0xff, +0x29, 0x0e, 0x6e, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0xc9, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x85, 0x00, 0x00, 0x00, 0x00, 0x84, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0xa4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xbd, 0x00, 0x00, +0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x32, 0x11, 0x87, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, +0x06, 0x31, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x02, 0x0c, 0xff, 0x17, +0x08, 0x3d, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x37, 0x13, 0x93, 0xff, 0x9a, 0x49, 0x19, 0xc4, 0xff, +0x03, 0x3b, 0x14, 0x9f, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa2, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, +0xa4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, +0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, +0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, +0x12, 0x06, 0x31, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, +0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x05, 0x25, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xa2, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x37, 0x13, +0x93, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x09, 0x03, 0x19, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0xa3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x84, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xb9, 0x00, 0x00, 0x00, 0xff, +0x01, 0x12, 0x06, 0x31, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb8, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, +0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, +0x02, 0x09, 0x03, 0x19, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xb9, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, +0x02, 0x0e, 0x05, 0x25, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x40, 0x16, 0xac, 0xff, 0xa8, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xbe, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xa4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x84, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xb6, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9c, 0x00, 0x00, 0x00, +0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x40, 0x16, 0xac, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa3, 0x00, 0x00, 0x00, +0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x40, 0x16, 0xac, 0xff, 0xad, 0x49, +0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xba, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x83, 0x00, +0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xb5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbf, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x9d, 0x00, 0x00, +0x00, 0xff, 0x02, 0x09, 0x03, 0x19, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xae, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x12, 0x06, 0x31, +0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xb3, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xb8, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, +0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x83, 0x00, 0x00, 0x00, 0x00, +0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0xa7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xb3, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0xc3, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x12, 0x06, 0x31, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x03, +0x09, 0x03, 0x19, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, 0x87, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xa7, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x3b, 0x14, 0x9f, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x37, 0x13, 0x93, 0xff, +0xb7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xb6, 0x00, +0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, +0x3d, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x83, 0x00, 0x00, 0x00, +0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xa8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xb1, +0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xc6, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, +0x03, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x32, 0x11, 0x87, 0xff, 0x44, 0x17, 0xb8, +0xff, 0x9f, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x37, 0x13, 0x93, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x17, +0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, +0xff, 0x40, 0x16, 0xac, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x20, +0x0b, 0x56, 0xff, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xa7, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, 0x00, +0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x05, 0x02, 0x0c, 0xff, 0xa9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xb0, +0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xc9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x04, 0x09, 0x03, 0x19, +0xff, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x37, 0x13, 0x93, +0xff, 0x94, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x3b, 0x14, 0x9f, 0xff, 0x37, 0x13, 0x93, 0xff, 0x25, +0x0d, 0x62, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, +0x01, 0x12, 0x06, 0x31, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, +0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xa8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x50, 0x82, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xa9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xaf, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xcc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x05, 0x25, 0xff, 0x12, 0x06, 0x31, +0xff, 0x12, 0x06, 0x31, 0xff, 0x8a, 0x25, 0x0d, 0x62, 0xff, 0x03, 0x17, 0x08, 0x3d, 0xff, 0x12, +0x06, 0x31, 0xff, 0x12, 0x06, 0x31, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0xb1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xa8, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x8f, 0x82, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x70, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xaa, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x37, 0x13, 0x93, 0xff, 0xce, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, +0x08, 0x3d, 0xff, 0xe5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x29, 0x0e, 0x6e, +0xff, 0xc5, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x09, 0x03, 0x19, 0xff, 0xaf, +0x00, 0x00, 0x00, 0xff, 0xa9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x96, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x82, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x44, 0x17, 0xb8, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xab, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd1, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x29, 0x0e, 0x6e, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xe2, 0x00, 0x00, 0x00, 0xff, 0x01, +0x17, 0x08, 0x3d, 0xff, 0x40, 0x16, 0xac, 0xff, 0xc7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, +0xaa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x02, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, +0x05, 0x25, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xaa, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x3b, 0x14, 0x9f, 0xff, 0x09, 0x03, 0x19, 0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0xcb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x17, 0x08, 0x3d, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, +0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x44, 0x17, 0xb8, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xd5, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, +0xdd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xcd, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x96, 0x00, 0x00, 0x00, +0xff, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0xdb, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xd0, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, +0x00, 0x09, 0x03, 0x19, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x44, 0x17, 0xb8, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xa7, 0x00, +0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xd8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xd2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa7, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, +0x19, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x2e, 0x10, 0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xd5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, +0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, +0xff, 0x05, 0x02, 0x0c, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xac, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x44, 0x17, 0xb8, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xde, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xd3, 0x00, 0x00, 0x00, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xd7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, +0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, +0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xdf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, +0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xd1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, +0x00, 0x0e, 0x05, 0x25, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xae, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, +0xe1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xce, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xdb, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, +0xae, 0x49, 0x19, 0xc4, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, +0xb8, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa2, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xe3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, +0x05, 0x02, 0x0c, 0xff, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa2, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xe5, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xca, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, +0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xe6, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0xc9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xe0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, +0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xb0, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0xe8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xc7, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xaf, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0xc5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, +0xff, 0xe4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, +0x00, 0x29, 0x0e, 0x6e, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x95, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xeb, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x3b, 0x14, 0x9f, 0xff, 0xe5, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb0, 0x49, 0x19, 0xc4, +0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x9d, +0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xeb, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xc1, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xe7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xed, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xe9, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x50, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb1, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xee, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xbf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xea, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb1, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb1, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xf0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xbd, 0x00, 0x00, 0x00, 0xff, +0x00, 0x1b, 0x09, 0x4a, 0xff, 0xec, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, 0x00, 0x00, +0x00, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x9b, 0x00, 0x00, 0x00, +0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xf1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, +0xbb, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xed, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb1, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xf2, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xb9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xee, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, +0x00, 0x00, 0x00, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xf3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xb9, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xef, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, +0x00, 0x00, 0x00, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x98, 0x00, +0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xf5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xb7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xf1, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xf5, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xb5, 0x00, 0x00, 0x00, 0xff, +0x00, 0x0e, 0x05, 0x25, 0xff, 0xf2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, 0x00, 0x00, +0x00, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x98, 0x00, 0x00, 0x00, +0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xf6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xb4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, 0xf2, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, +0x6e, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, +0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, +0x09, 0x03, 0x19, 0xff, 0xf8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xb3, 0x00, +0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xf4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb2, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, +0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xf8, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xf5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x96, 0x00, 0x00, 0x00, +0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, +0x3d, 0xff, 0xb1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xf6, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb3, 0x49, +0x19, 0xc4, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xf7, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, +0x11, 0x87, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xf7, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfb, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x95, 0x00, +0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfa, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, +0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x44, 0x17, 0xb8, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfa, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x94, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfb, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x96, 0x00, 0x00, 0x00, 0xff, 0xb3, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xaa, 0x00, 0x00, 0x00, +0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, +0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x49, 0x19, 0xc4, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, +0x08, 0x3d, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x92, 0x00, 0x00, +0x00, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xdf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb3, 0x49, 0x19, +0xc4, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, 0x93, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, +0x6e, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, +0x09, 0x03, 0x19, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x80, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xb3, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x29, +0x0e, 0x6e, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, +0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, +0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, +0x0c, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb2, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x80, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xdf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb2, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, +0x19, 0xc4, 0xff, 0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa4, 0x00, 0x00, +0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, +0xff, 0x49, 0x19, 0xc4, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xb2, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x93, 0x00, 0x00, 0x00, +0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, +0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x82, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x95, 0x00, 0x00, +0x00, 0xff, 0x82, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x70, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xb2, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xa2, 0x00, 0x00, 0x00, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x82, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb2, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x82, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x30, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xb1, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, +0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa1, 0x00, 0x00, +0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x8f, 0x82, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xef, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xb1, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, +0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, +0x00, 0x20, 0x0b, 0x56, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xb1, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x40, 0x82, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x84, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, +0x14, 0x9f, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, +0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x83, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x60, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xb0, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, +0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9f, 0x00, 0x00, +0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x44, 0x17, 0xb8, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x83, +0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x96, 0x00, +0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x90, +0x00, 0x00, 0x00, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0x83, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, +0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, +0xff, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, +0x32, 0x11, 0x87, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, +0x3d, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x83, 0x00, 0x00, 0x00, +0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, +0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x90, 0x00, 0x00, 0x00, +0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xcf, 0x84, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x20, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xaf, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, +0x9f, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0xb0, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x70, 0x84, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xcf, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xae, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x9d, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x20, 0x84, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x9d, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, +0xaf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xcf, 0x85, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, +0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, +0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x9d, +0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x85, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xad, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, +0x25, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xfe, 0x49, 0x19, 0xc4, +0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x85, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, +0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, +0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, +0x19, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xae, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x86, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, +0x91, 0x00, 0x00, 0x00, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, +0x02, 0x0c, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x86, 0x00, 0x00, +0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x97, 0x00, 0x00, 0x00, +0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x91, 0x00, 0x00, +0x00, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x87, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xab, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, +0x14, 0x9f, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xfe, 0x49, 0x19, 0xc4, +0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, +0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x60, 0x87, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xaa, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0x9b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x10, 0x87, 0x00, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x9a, 0x00, 0x00, +0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, +0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, +0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x91, +0x00, 0x00, 0x00, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x88, 0x00, 0x00, 0x00, +0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, +0x00, 0x3b, 0x14, 0x9f, 0xff, 0xa8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x95, +0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, +0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x86, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xa9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x89, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xa8, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x44, 0x17, 0xb8, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa8, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x89, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xa7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, +0xff, 0xa8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa6, 0x49, +0x19, 0xc4, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xa7, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, +0x00, 0x10, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x20, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa4, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, +0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, +0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xa6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0xa4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x9a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x85, 0x49, +0x19, 0xc4, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa5, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, 0x00, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, +0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8c, 0x00, 0x00, 0x00, 0x00, +0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0xa2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x98, 0x00, +0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, +0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, +0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, +0x00, 0x05, 0x02, 0x0c, 0xff, 0xa4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x98, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, +0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x84, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0xa3, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x40, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x40, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, +0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, +0x49, 0x19, 0xc4, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, +0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, +0xff, 0x05, 0x02, 0x0c, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x8e, +0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x99, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x9e, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, +0x93, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, 0x49, 0x19, 0xc4, +0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x29, 0x0e, 0x6e, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, +0x03, 0x19, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x10, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xef, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0x9d, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x9a, 0x00, 0x00, 0x00, +0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, +0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, 0x93, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9f, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x60, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x50, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0x9c, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, +0x09, 0x03, 0x19, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xfe, 0x49, 0x19, 0xc4, 0xff, 0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x9e, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xbf, 0x90, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x9b, 0x49, 0x19, 0xc4, 0xff, 0x9c, +0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, +0x19, 0xc4, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x9c, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x20, 0x90, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0x99, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x9c, 0x00, 0x00, +0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, +0x49, 0x19, 0xc4, 0xff, 0x82, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x9b, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, +0x91, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9c, +0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x98, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, +0x08, 0x3d, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x37, +0x13, 0x93, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x9a, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x8f, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, +0xb8, 0xff, 0x95, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x9e, 0x00, 0x00, 0x00, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, +0x00, 0x0e, 0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, +0x19, 0xc4, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, +0xff, 0x98, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x99, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x10, 0x92, 0x00, 0x00, +0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9c, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x94, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfc, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0x97, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0x93, 0x00, 0x00, 0x00, 0x00, 0x93, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xef, 0x9c, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x92, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x9c, 0x00, 0x00, 0x00, +0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x96, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x94, 0x00, +0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9e, 0x00, 0x00, +0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x90, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfb, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, +0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x9f, 0x95, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x37, 0x13, 0x93, 0xff, +0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0xfb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9c, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, +0x62, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x92, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xcf, 0x96, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x0b, 0x56, 0xff, 0x44, 0x17, 0xb8, +0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa3, +0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, 0x9d, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, +0x0c, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x90, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, +0x00, 0x00, 0x00, 0x10, 0x96, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, +0xff, 0x89, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa4, +0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, +0x11, 0x87, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfc, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x40, 0x16, 0xac, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, +0x05, 0x25, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x30, 0x97, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xcf, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x40, 0x16, +0xac, 0xff, 0x86, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x29, 0x0e, 0x6e, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xf8, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xfa, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9f, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0x00, +0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0xcf, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x06, 0x1b, 0x09, 0x4a, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x37, +0x13, 0x93, 0xff, 0x37, 0x13, 0x93, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xf8, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, +0x01, 0x0e, 0x05, 0x25, 0xff, 0x40, 0x16, 0xac, 0xff, 0x88, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, +0x13, 0x93, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x60, 0x99, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xef, 0xd1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xf6, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xa2, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x44, 0x17, +0xb8, 0xff, 0x84, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, +0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x9a, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0xd0, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, 0xf5, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x20, 0x0b, 0x56, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xf9, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x04, 0x12, +0x06, 0x31, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, +0x06, 0x31, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9b, 0x00, 0x00, +0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, +0xd0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xf5, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x09, 0x03, 0x19, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xf7, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x60, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x20, 0x00, 0x00, 0x00, 0xcf, 0xd0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xf3, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, +0x0e, 0x6e, 0xff, 0xf7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xcb, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, 0xf2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xf6, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xca, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, +0x00, 0x00, 0x00, 0x60, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xbf, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, +0xff, 0xf1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, +0x00, 0x40, 0x16, 0xac, 0xff, 0xf4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xc9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x30, 0x9f, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, +0xcf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xf0, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xf4, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xc9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xcf, 0x00, 0x00, 0x00, 0x30, 0xa0, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x70, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xee, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa3, 0x00, 0x00, +0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xf3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xc9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x10, 0xa1, +0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, +0x00, 0xef, 0xcd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x40, 0x16, 0xac, 0xff, +0xed, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0xf1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xc8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xa3, 0x00, 0x00, 0x00, +0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xbf, 0xcd, +0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xeb, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, +0x00, 0x17, 0x08, 0x3d, 0xff, 0xf1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xc7, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x50, 0xa4, 0x00, 0x00, +0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcd, 0x00, 0x00, 0x00, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xeb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xef, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0xc7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, +0x00, 0x10, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x30, 0x00, 0x00, 0x00, 0xcf, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xe9, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa7, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xee, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0xc6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x70, 0xa7, +0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, +0x00, 0xef, 0xcb, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xe8, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, +0xec, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xc5, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x20, 0xa8, 0x00, 0x00, 0x00, +0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0x00, 0x00, 0x00, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0xe6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xaa, +0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xeb, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xc5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xbf, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, +0xcb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xe5, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xea, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xc6, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0xaa, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xe3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xac, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xe9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, +0xff, 0xc6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xab, 0x00, 0x00, 0x00, 0x00, +0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xe1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, +0x9f, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xe7, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xc6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, +0x00, 0x00, 0x00, 0x10, 0xab, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0xcd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, +0xff, 0xdf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0xae, +0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe5, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xc7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x80, 0xac, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xcd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xde, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0xe4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xc7, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xad, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0xce, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb2, 0x00, 0x00, +0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, +0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x08, 0x05, 0x02, 0x0c, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x44, +0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x50, 0xad, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x03, 0x09, 0x03, 0x19, 0xff, 0x12, 0x06, +0x31, 0xff, 0x12, 0x06, 0x31, 0xff, 0x09, 0x03, 0x19, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0xda, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb3, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe0, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, +0x32, 0x11, 0x87, 0xff, 0x87, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x95, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x37, 0x13, 0x93, 0xff, 0x83, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x44, 0x17, 0xb8, 0xff, 0x32, +0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, +0x00, 0x1b, 0x09, 0x4a, 0xff, 0xd8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xb5, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xdf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, +0xff, 0x8a, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x87, 0x49, +0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x0e, 0x05, 0x25, 0xff, +0xac, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xd5, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xb6, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xdd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0xa5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0x8c, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, +0x12, 0x06, 0x31, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xb8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xdb, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, +0xac, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, +0x6e, 0xff, 0xd1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, +0xb9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd9, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, +0x31, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0x90, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xaa, 0x00, 0x00, 0x00, +0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xce, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x37, 0x13, 0x93, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, +0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xd6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, +0x0e, 0x05, 0x25, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x32, 0x11, +0x87, 0xff, 0x92, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x91, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa9, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0xcc, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xbe, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xd4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x09, 0x03, 0x19, +0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x25, 0x0d, 0x62, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x93, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x92, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x01, +0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xc9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xd2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, +0x12, 0x06, 0x31, 0xff, 0x40, 0x16, 0xac, 0xff, 0x95, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, +0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, +0x94, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x12, 0x06, 0x31, 0xff, 0xa9, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xc6, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xc2, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xcf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x2e, 0x10, 0x7b, 0xff, 0x97, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xae, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, +0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xff, 0x96, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, +0xff, 0x05, 0x02, 0x0c, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xc3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xc4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0xcd, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa1, 0x00, 0x00, +0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x98, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xae, +0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0xff, 0x97, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xaa, 0x00, 0x00, 0x00, +0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xc8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xca, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, +0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0x9a, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x40, 0xae, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, +0xff, 0x99, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa9, +0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x44, 0x17, 0xb8, +0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xca, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xc7, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, +0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x9b, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xae, 0x00, 0x00, +0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x97, 0x00, 0x00, 0x00, +0xff, 0x9a, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xaa, +0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x44, 0x17, 0xb8, +0xff, 0xb8, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x12, 0x06, 0x31, 0xff, 0xcd, +0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc4, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x9d, 0x49, 0x19, 0xc4, 0xff, 0x95, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xae, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x9c, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x01, +0x1b, 0x09, 0x4a, 0xff, 0x40, 0x16, 0xac, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, +0xac, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xd0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x29, 0x0e, 0x6e, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, +0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, +0x40, 0x16, 0xac, 0xff, 0x9e, 0x49, 0x19, 0xc4, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x30, 0xae, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x9d, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x17, 0x08, 0x3d, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x32, +0x11, 0x87, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x1b, 0x09, 0x4a, +0xff, 0xd4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xbe, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa2, 0x00, 0x00, +0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9e, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x2e, 0x10, 0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, +0x0c, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x2e, 0x10, 0x7b, 0xff, 0x12, 0x06, 0x31, 0xff, 0xd8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x25, 0x0d, +0x62, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, +0x09, 0x03, 0x19, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xa0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x9f, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x40, 0x16, 0xac, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, +0x19, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xdb, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xb7, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, +0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, +0x11, 0x87, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb0, 0x00, 0x00, +0x00, 0xff, 0x03, 0x05, 0x02, 0x0c, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x40, +0x16, 0xac, 0xff, 0x9d, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x44, 0x17, 0xb8, 0xff, 0x32, 0x11, 0x87, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, +0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, 0xac, +0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xa3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, +0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xaf, 0x00, 0x00, 0x00, 0x00, +0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xa2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x04, 0x09, 0x03, 0x19, 0xff, 0x17, 0x08, 0x3d, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, 0xff, 0x40, 0x16, 0xac, 0xff, 0x94, 0x49, 0x19, 0xc4, +0xff, 0x03, 0x3b, 0x14, 0x9f, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xe6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, 0x62, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x17, 0x08, +0x3d, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xa4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xbf, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa3, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, 0xb7, 0x00, 0x00, 0x00, 0xff, +0x04, 0x12, 0x06, 0x31, 0xff, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, +0xff, 0x2e, 0x10, 0x7b, 0xff, 0x88, 0x37, 0x13, 0x93, 0xff, 0x04, 0x29, 0x0e, 0x6e, 0xff, 0x25, +0x0d, 0x62, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xee, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, 0x87, 0xff, 0xa8, 0x49, 0x19, +0xc4, 0xff, 0x02, 0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa6, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xa5, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x80, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xa5, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, +0x02, 0x0c, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, 0x87, 0xff, 0xa1, 0x49, 0x19, 0xc4, 0xff, +0x03, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xa7, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x80, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, +0xff, 0x05, 0x02, 0x0c, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0xbe, 0x00, 0x00, 0x00, 0xff, 0x02, +0x17, 0x08, 0x3d, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x37, 0x13, 0x93, 0xff, 0x99, 0x49, 0x19, 0xc4, +0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x32, 0x11, 0x87, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xa8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x40, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcf, 0x97, 0x00, 0x00, 0x00, 0xff, 0xa7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0xc1, 0x00, 0x00, 0x00, 0xff, +0x04, 0x12, 0x06, 0x31, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, +0xff, 0x37, 0x13, 0x93, 0xff, 0x8d, 0x49, 0x19, 0xc4, 0xff, 0x05, 0x37, 0x13, 0x93, 0xff, 0x37, +0x13, 0x93, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, +0xff, 0xa8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x40, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xaf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xa8, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xc6, 0x00, 0x00, +0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0x87, 0x12, 0x06, 0x31, 0xff, 0x00, 0x05, 0x02, 0x0c, +0xff, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0xa9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, 0x13, 0x93, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, +0x0e, 0x6e, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xb0, 0x00, 0x00, +0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x97, 0x00, 0x00, 0x00, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xaa, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, +0x0e, 0x05, 0x25, 0xff, 0xf4, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x02, 0x0c, 0xff, 0x12, 0x06, +0x31, 0xff, 0x12, 0x06, 0x31, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x83, 0x25, 0x0d, 0x62, 0xff, 0x00, +0x32, 0x11, 0x87, 0xff, 0x88, 0x37, 0x13, 0x93, 0xff, 0x84, 0x25, 0x0d, 0x62, 0xff, 0x82, 0x12, +0x06, 0x31, 0xff, 0xef, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x40, 0x16, 0xac, +0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xbf, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x30, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xab, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xec, 0x00, 0x00, 0x00, +0xff, 0x05, 0x0e, 0x05, 0x25, 0xff, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x2e, 0x10, +0x7b, 0xff, 0x37, 0x13, 0x93, 0xff, 0x40, 0x16, 0xac, 0xff, 0x9c, 0x49, 0x19, 0xc4, 0xff, 0x05, +0x40, 0x16, 0xac, 0xff, 0x37, 0x13, 0x93, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x25, 0x0d, 0x62, 0xff, +0x17, 0x08, 0x3d, 0xff, 0x12, 0x06, 0x31, 0xff, 0xe6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, +0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xad, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xb0, +0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xad, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xe6, 0x00, 0x00, 0x00, 0xff, 0x03, 0x0e, 0x05, +0x25, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x37, 0x13, 0x93, 0xff, 0xaa, 0x49, +0x19, 0xc4, 0xff, 0x04, 0x40, 0x16, 0xac, 0xff, 0x37, 0x13, 0x93, 0xff, 0x25, 0x0d, 0x62, 0xff, +0x17, 0x08, 0x3d, 0xff, 0x09, 0x03, 0x19, 0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, +0x6e, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xcf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xad, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xe0, 0x00, 0x00, +0x00, 0xff, 0x02, 0x12, 0x06, 0x31, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb4, +0x49, 0x19, 0xc4, 0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x32, 0x11, 0x87, 0xff, 0x20, 0x0b, 0x56, +0xff, 0x0e, 0x05, 0x25, 0xff, 0xd9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, +0x13, 0x93, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x95, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0xb0, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, +0xae, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xdb, 0x00, +0x00, 0x00, 0xff, 0x03, 0x09, 0x03, 0x19, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x32, 0x11, 0x87, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x2e, 0x10, +0x7b, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xd4, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x05, 0x25, 0xff, 0x40, 0x16, 0xac, 0xff, 0xb0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, +0xaf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xd7, 0x00, +0x00, 0x00, 0xff, 0x02, 0x09, 0x03, 0x19, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xc3, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x32, 0x11, 0x87, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xd0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0xbf, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xb1, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xd3, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0x37, 0x13, 0x93, 0xff, 0xc9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, +0x11, 0x87, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xcd, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, +0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, +0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, 0x19, +0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xcd, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, +0x16, 0xac, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xc9, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0xb2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x09, 0x03, 0x19, 0xff, +0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x37, 0x13, 0x93, 0xff, 0xd3, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xc5, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x17, 0x08, 0x3d, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb1, 0x00, +0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x0e, 0x05, 0x25, 0xff, 0xc9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xd7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, +0xff, 0xc2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xb4, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x44, 0x17, 0xb8, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xcf, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x02, 0x0c, 0xff, 0xb5, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, +0x3b, 0x14, 0x9f, 0xff, 0xdb, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x29, 0x0e, 0x6e, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xbf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xb5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x8f, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xef, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xb5, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xc3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, +0xff, 0x37, 0x13, 0x93, 0xff, 0xde, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x1b, +0x09, 0x4a, 0xff, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb7, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x50, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb6, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x2e, 0x10, 0x7b, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, +0x62, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x09, 0x03, 0x19, 0xff, +0xba, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xb7, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x40, 0x16, 0xac, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0xb2, 0x00, +0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x97, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xb6, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, +0x06, 0x31, 0xff, 0x40, 0x16, 0xac, 0xff, 0xe4, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x1b, 0x09, 0x4a, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb8, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xaf, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb7, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x00, +0x29, 0x0e, 0x6e, 0xff, 0xe8, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb5, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb9, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, +0xb3, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x97, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb8, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, +0xff, 0x3b, 0x14, 0x9f, 0xff, 0xea, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, +0x02, 0x0c, 0xff, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, +0xff, 0xb9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x20, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x70, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xb8, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xb6, 0x00, 0x00, 0x00, +0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xec, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, +0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, +0x0b, 0x56, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xb4, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xef, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, +0xff, 0x05, 0x02, 0x0c, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, +0x17, 0xb8, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xb2, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xf1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, +0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x96, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, +0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, +0x00, 0x1b, 0x09, 0x4a, 0xff, 0xf3, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xab, +0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, +0x16, 0xac, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xb5, 0x00, 0x00, +0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x32, 0x11, 0x87, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0xf5, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xa9, 0x00, 0x00, 0x00, +0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb5, 0x00, 0x00, 0x00, 0x00, 0xb5, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xf7, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x0e, 0x05, 0x25, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xbd, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xef, 0xb6, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xbd, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xf7, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x3b, 0x14, +0x9f, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xbe, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, +0xb6, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, +0x16, 0xac, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x3b, 0x14, 0x9f, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa4, +0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xb6, 0x00, 0x00, +0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x98, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, +0x6e, 0xff, 0xfa, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xa2, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x0e, 0x05, 0x25, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xb7, 0x00, +0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x98, 0x00, 0x00, +0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x0e, 0x05, 0x25, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfc, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x29, 0x0e, 0x6e, +0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb7, 0x00, 0x00, 0x00, 0x00, +0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, +0x40, 0x16, 0xac, 0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, +0x25, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xfc, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x3b, 0x14, 0x9f, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xb8, 0x00, 0x00, 0x00, +0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x98, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, +0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, +0x3b, 0x14, 0x9f, 0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, +0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, +0x00, 0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0x9c, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc0, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xdf, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x44, 0x17, +0xb8, 0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9e, 0x00, 0x00, 0x00, +0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, +0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xb9, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, +0x06, 0x31, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9d, 0x00, 0x00, +0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, +0xff, 0x2e, 0x10, 0x7b, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xba, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, +0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, +0x37, 0x13, 0x93, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, +0x93, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x40, 0xba, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x50, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, 0x93, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, +0x87, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xbb, 0x00, 0x00, 0x00, +0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x99, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, +0x09, 0x4a, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xfe, 0x49, 0x19, +0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x37, 0x13, 0x93, 0xff, 0x97, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x20, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x30, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0xc2, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, +0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, +0x37, 0x13, 0x93, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, +0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xbc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, +0x0d, 0x62, 0xff, 0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, +0xff, 0x49, 0x19, 0xc4, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x0e, 0x05, 0x25, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, +0x00, 0x00, 0x10, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x10, 0x00, 0x00, 0x00, 0xdf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, +0x25, 0x0d, 0x62, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, +0xc4, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, +0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x40, 0x94, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1c, 0x1e, 0x1d, 0x30, 0x1c, 0x1e, +0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x80, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, +0x1d, 0xcf, 0x82, 0x1c, 0x1e, 0x1d, 0xff, 0x82, 0x1c, 0x1e, 0x1d, 0xbf, 0x02, 0x1c, 0x1e, 0x1d, +0x80, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x30, 0x99, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, +0x93, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x12, 0x06, 0x31, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, +0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x91, 0x00, 0x00, 0x00, 0x00, 0x03, +0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0xaf, 0x1c, 0x1e, 0x1d, 0xef, +0x8e, 0x1c, 0x1e, 0x1d, 0xff, 0x03, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0xaf, 0x1c, 0x1e, +0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x10, 0x95, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x8f, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, +0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x49, 0x19, 0xc4, 0xff, 0x49, 0x19, 0xc4, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0xc2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x99, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x10, 0x8f, 0x00, 0x00, 0x00, 0x00, +0x01, 0x1c, 0x1e, 0x1d, 0x50, 0x1c, 0x1e, 0x1d, 0xaf, 0x96, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, +0x1e, 0x1d, 0xaf, 0x1c, 0x1e, 0x1d, 0x40, 0x93, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0xff, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x32, 0x11, 0x87, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xc2, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x40, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, +0xdf, 0x9a, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, 0x60, 0x91, +0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x00, 0xef, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, +0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x93, 0x00, +0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xfe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, +0x4a, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xc1, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, +0x1d, 0xcf, 0x9e, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0x40, +0x8f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9b, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, +0x00, 0x17, 0x08, 0x3d, 0xff, 0xfd, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0x92, +0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x05, 0x25, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, +0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xbf, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0x8f, 0x8e, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x82, 0x1c, 0x1e, 0x1d, 0xbf, 0x00, 0x1c, +0x1e, 0x1d, 0xdf, 0x8e, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x8f, 0x1c, 0x1e, 0x1d, +0x10, 0x8d, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc1, 0x49, +0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, +0xac, 0xff, 0xfc, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x91, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x30, +0x1c, 0x1e, 0x1d, 0xdf, 0x8a, 0x1c, 0x1e, 0x1d, 0xff, 0x03, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, +0x1d, 0x80, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0x10, 0x86, 0x00, 0x00, 0x00, 0x00, 0x03, +0x1c, 0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0x80, 0x1c, 0x1e, 0x1d, 0xbf, +0x8a, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, 0x30, 0x8c, 0x00, +0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0xcf, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xfb, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x90, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x37, 0x13, 0x93, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x30, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x89, 0x1c, 0x1e, +0x1d, 0xff, 0x02, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x10, 0x8e, +0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, +0xbf, 0x89, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x8b, 0x00, 0x00, 0x00, 0x00, +0xc2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x9c, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, +0x56, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x40, 0x16, 0xac, 0xff, 0xfa, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, +0xc0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x60, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x88, 0x1c, +0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x9f, 0x1c, 0x1e, 0x1d, 0x20, 0x94, 0x00, 0x00, 0x00, +0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0x9f, 0x88, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x8f, 0x8a, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xc0, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x17, 0x08, 0x3d, 0xff, 0x91, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xf9, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, +0x13, 0x93, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xbf, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x8f, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x87, +0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0x20, 0x98, 0x00, 0x00, +0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0xbf, 0x87, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x89, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, +0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x0e, 0x6e, 0xff, 0xf7, 0x49, 0x19, 0xc4, 0xff, 0x01, +0x44, 0x17, 0xb8, 0xff, 0x09, 0x03, 0x19, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x08, +0x3d, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x37, 0x13, 0x93, 0xff, 0x05, 0x02, 0x0c, 0xff, +0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x1e, 0x1d, 0x9f, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, +0x1d, 0x50, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x70, 0x1c, 0x1e, 0x1d, 0xef, +0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x88, 0x00, 0x00, 0x00, 0x00, 0xc5, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x02, 0x0c, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xbf, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, +0xff, 0x05, 0x02, 0x0c, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x3b, +0x14, 0x9f, 0xff, 0xf6, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x90, 0x00, 0x00, +0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbd, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x44, 0x17, 0xb8, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, +0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xcf, 0x1c, 0x1e, 0x1d, 0x20, 0x9e, 0x00, 0x00, 0x00, 0x00, +0x01, 0x1c, 0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0xcf, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, +0x1e, 0x1d, 0x60, 0x87, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x70, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, 0x3d, 0xff, 0x44, 0x17, 0xb8, 0xff, +0xbe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x05, 0x25, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xf4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x2e, 0x10, +0x7b, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xbd, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x09, 0x03, 0x19, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x50, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0xa1, 0x00, 0x00, 0x00, +0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0x9f, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x50, 0x86, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, +0xff, 0xbe, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, +0x00, 0x17, 0x08, 0x3d, 0xff, 0xf3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, +0x02, 0x0c, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xbc, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, +0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0xef, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x9f, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x85, 0x1c, 0x1e, 0x1d, 0xff, +0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x20, 0x85, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x08, +0x3d, 0xff, 0x40, 0x16, 0xac, 0xff, 0xbc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, +0x09, 0x03, 0x19, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0xf1, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x90, 0x00, 0x00, 0x00, +0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, 0x02, +0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9e, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x1e, 0x1d, 0xbf, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0xa6, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0xbf, 0x85, 0x00, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x25, 0x0d, 0x62, 0xff, 0xbc, +0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, +0x10, 0x7b, 0xff, 0xef, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, +0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0xba, 0x49, 0x19, 0xc4, 0xff, +0x01, 0x29, 0x0e, 0x6e, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x70, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xaf, 0x85, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x86, 0x1c, 0x1e, 0x1d, 0x40, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x8d, +0x00, 0x00, 0x00, 0x00, 0x87, 0x1c, 0x1e, 0x1d, 0x40, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0xcf, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x84, 0x00, 0x00, +0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x00, +0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x20, 0x0b, 0x56, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xed, 0x49, +0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x91, 0x00, 0x00, 0x00, +0xff, 0x00, 0x12, 0x06, 0x31, 0xff, 0xb9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, +0x09, 0x03, 0x19, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, +0x00, 0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, +0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, 0x10, 0x85, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x30, 0x86, 0x1c, 0x1e, 0x1d, +0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, +0x1c, 0x1e, 0x1d, 0xdf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, +0x1d, 0x10, 0x83, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x60, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb9, +0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x92, 0x00, 0x00, +0x00, 0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xeb, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, +0xff, 0x0e, 0x05, 0x25, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0xb6, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x10, 0x8c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, +0x1e, 0x1d, 0x30, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, +0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x50, 0x84, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x83, +0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa2, 0x00, +0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x37, 0x13, 0x93, 0xff, 0xb8, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, +0xe9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x92, 0x00, +0x00, 0x00, 0xff, 0x00, 0x09, 0x03, 0x19, 0xff, 0xb5, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, +0x9f, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x9f, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x8f, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, +0xcd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0xa2, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xb6, 0x49, 0x19, 0xc4, +0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x09, 0x4a, 0xff, 0xe7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x3b, 0x14, 0x9f, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0xb2, 0x49, 0x19, 0xc4, +0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xa4, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x9f, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, 0x10, +0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x85, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x86, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, +0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, +0x82, 0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, +0x00, 0x00, 0xcf, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x02, 0x0c, 0xff, 0x20, 0x0b, 0x56, +0xff, 0x40, 0x16, 0xac, 0xff, 0xb4, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x1b, 0x09, 0x4a, 0xff, 0x94, +0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x06, 0x31, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xe4, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2e, 0x10, 0x7b, 0xff, 0xaf, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x60, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, 0x84, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xcf, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0xbf, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0xef, 0x82, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xbf, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x02, 0x12, 0x06, +0x31, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x00, +0x32, 0x11, 0x87, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0xe2, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x20, 0x0b, 0x56, 0xff, 0x96, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2e, 0x10, 0x7b, 0xff, 0xac, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, 0x16, 0xac, 0xff, +0x29, 0x0e, 0x6e, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x60, +0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, +0x00, 0x00, 0x00, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x88, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x02, 0x1c, 0x1e, 0x1d, +0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x8f, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x02, 0x17, 0x08, 0x3d, 0xff, 0x2e, 0x10, 0x7b, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xae, 0x49, 0x19, 0xc4, 0xff, 0x00, 0x37, 0x13, 0x93, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, 0xff, 0x32, 0x11, 0x87, 0xff, 0xdf, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x12, 0x06, 0x31, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, +0x00, 0x12, 0x06, 0x31, 0xff, 0xa8, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x40, 0x16, 0xac, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x09, 0x03, 0x19, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x20, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0xaf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x89, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, +0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x02, +0x1c, 0x1e, 0x1d, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xef, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x02, +0x12, 0x06, 0x31, 0xff, 0x29, 0x0e, 0x6e, 0xff, 0x3b, 0x14, 0x9f, 0xff, 0xab, 0x49, 0x19, 0xc4, +0xff, 0x00, 0x32, 0x11, 0x87, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x0b, 0x56, 0xff, +0x44, 0x17, 0xb8, 0xff, 0xdc, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x05, 0x02, +0x0c, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x03, 0x12, 0x06, 0x31, 0xff, 0x29, 0x0e, 0x6e, 0xff, +0x37, 0x13, 0x93, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x9f, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x3b, 0x14, +0x9f, 0xff, 0x32, 0x11, 0x87, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x12, 0x06, 0x31, 0xff, 0x05, 0x02, +0x0c, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x10, +0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x10, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x10, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x10, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x88, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x00, 0xcf, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x02, 0x0c, 0xff, 0x17, 0x08, 0x3d, 0xff, +0x29, 0x0e, 0x6e, 0xff, 0x37, 0x13, 0x93, 0xff, 0xa6, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, +0xb8, 0xff, 0x0e, 0x05, 0x25, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, +0x3b, 0x14, 0x9f, 0xff, 0xd9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x44, 0x17, 0xb8, 0xff, 0x20, 0x0b, +0x56, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x07, 0x12, 0x06, 0x31, 0xff, 0x12, 0x06, 0x31, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x32, 0x11, 0x87, 0xff, 0x37, 0x13, 0x93, 0xff, +0x37, 0x13, 0x93, 0xff, 0x44, 0x17, 0xb8, 0xff, 0x8e, 0x49, 0x19, 0xc4, 0xff, 0x06, 0x37, 0x13, +0x93, 0xff, 0x37, 0x13, 0x93, 0xff, 0x32, 0x11, 0x87, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, +0x56, 0xff, 0x12, 0x06, 0x31, 0xff, 0x0e, 0x05, 0x25, 0xff, 0xb0, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x60, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x50, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xaf, 0x8a, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, +0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xaf, 0x84, 0x1c, +0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x50, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0xae, 0x00, 0x00, 0x00, 0xff, 0x04, +0x0e, 0x05, 0x25, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x37, 0x13, 0x93, 0xff, +0x40, 0x16, 0xac, 0xff, 0x9c, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x37, 0x13, 0x93, 0xff, 0x32, 0x11, +0x87, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, 0xff, 0x9c, 0x00, +0x00, 0x00, 0xff, 0x00, 0x25, 0x0d, 0x62, 0xff, 0xd7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, +0x87, 0xff, 0x09, 0x03, 0x19, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x85, 0x12, 0x06, 0x31, 0xff, +0x00, 0x05, 0x02, 0x0c, 0xff, 0xba, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, +0x00, 0x00, 0x30, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x84, 0x1c, 0x1e, +0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x89, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, +0x1e, 0x1d, 0x80, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x50, 0x00, 0x00, 0x00, 0xef, 0xb2, 0x00, 0x00, 0x00, 0xff, 0x05, 0x09, 0x03, 0x19, 0xff, 0x12, +0x06, 0x31, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x2e, +0x10, 0x7b, 0xff, 0x83, 0x37, 0x13, 0x93, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x83, 0x49, 0x19, +0xc4, 0xff, 0x00, 0x3b, 0x14, 0x9f, 0xff, 0x83, 0x37, 0x13, 0x93, 0xff, 0x05, 0x32, 0x11, 0x87, +0xff, 0x25, 0x0d, 0x62, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, 0x31, +0xff, 0x12, 0x06, 0x31, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x05, 0x25, 0xff, 0x37, +0x13, 0x93, 0xff, 0xd3, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x40, 0x16, 0xac, 0xff, 0x17, 0x08, 0x3d, +0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x10, 0x94, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, +0x1e, 0x1d, 0x20, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, +0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0xcf, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x89, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xbf, 0x00, +0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0xbf, 0xf2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xcf, +0x49, 0x19, 0xc4, 0xff, 0x02, 0x44, 0x17, 0xb8, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, +0xff, 0xef, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x40, 0x96, +0x00, 0x00, 0x00, 0x00, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x8b, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x87, 0x1c, 0x1e, 0x1d, +0xff, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xef, 0x83, 0x1c, 0x1e, 0x1d, 0xff, +0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xef, 0xf1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x02, 0x0c, +0xff, 0x25, 0x0d, 0x62, 0xff, 0xcd, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, +0x03, 0x19, 0xff, 0xf0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, +0x10, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x89, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, +0x1e, 0x1d, 0x50, 0x1c, 0x1e, 0x1d, 0xef, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x9f, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, +0x00, 0x00, 0xbf, 0xf2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, +0xff, 0xc9, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x09, 0x03, 0x19, 0xff, 0xf0, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x50, 0x98, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x87, 0x1c, 0x1e, 0x1d, 0x80, 0x01, 0x1c, 0x1e, 0x1d, 0xaf, 0x1c, +0x1e, 0x1d, 0xdf, 0x88, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x8b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x40, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xef, 0xf2, +0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0xc5, 0x49, 0x19, +0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x12, 0x06, 0x31, 0xff, 0xf1, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x10, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x40, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x99, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x8f, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x40, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0xaf, 0xf3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x03, 0x19, 0xff, 0x2e, 0x10, 0x7b, +0xff, 0xc1, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x2e, 0x10, 0x7b, 0xff, 0x09, 0x03, 0x19, 0xff, 0xf1, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x40, 0x9b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x40, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x98, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x84, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xdf, 0xf3, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, 0x19, +0xff, 0x25, 0x0d, 0x62, 0xff, 0x44, 0x17, 0xb8, 0xff, 0xbb, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x40, +0x16, 0xac, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xf2, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x80, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x84, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x80, 0x96, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, +0x40, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x40, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x80, 0xf5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x09, 0x4a, 0xff, 0x37, 0x13, 0x93, +0xff, 0xb7, 0x49, 0x19, 0xc4, 0xff, 0x01, 0x32, 0x11, 0x87, 0xff, 0x17, 0x08, 0x3d, 0xff, 0xf3, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x20, 0x9e, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x40, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x98, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x84, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xaf, 0xf5, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x03, 0x19, +0xff, 0x29, 0x0e, 0x6e, 0xff, 0x40, 0x16, 0xac, 0xff, 0xb1, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x3b, +0x14, 0x9f, 0xff, 0x1b, 0x09, 0x4a, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xf3, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x50, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x60, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x8b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x99, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x9f, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x40, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, +0x00, 0x00, 0xdf, 0xf6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x05, 0x25, 0xff, 0x29, 0x0e, 0x6e, +0xff, 0x40, 0x16, 0xac, 0xff, 0xab, 0x49, 0x19, 0xc4, 0xff, 0x02, 0x32, 0x11, 0x87, 0xff, 0x20, +0x0b, 0x56, 0xff, 0x09, 0x03, 0x19, 0xff, 0xf4, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x40, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x9f, 0x88, 0x1c, 0x1e, 0x1d, 0x40, 0x01, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x9f, 0x87, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0xe2, 0x00, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xbf, 0xfa, +0x00, 0x00, 0x00, 0xff, 0x03, 0x09, 0x03, 0x19, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x32, 0x11, 0x87, +0xff, 0x44, 0x17, 0xb8, 0xff, 0xa3, 0x49, 0x19, 0xc4, 0xff, 0x03, 0x3b, 0x14, 0x9f, 0xff, 0x29, +0x0e, 0x6e, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xf8, 0x00, 0x00, 0x00, 0xff, +0x02, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x50, 0xa0, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x86, +0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x10, 0x8a, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x40, 0xde, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xef, 0xfb, 0x00, 0x00, 0x00, 0xff, 0x85, 0x00, 0x00, 0x00, +0xff, 0x03, 0x0e, 0x05, 0x25, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x3b, 0x14, +0x9f, 0xff, 0x9a, 0x49, 0x19, 0xc4, 0xff, 0x04, 0x44, 0x17, 0xb8, 0xff, 0x37, 0x13, 0x93, 0xff, +0x25, 0x0d, 0x62, 0xff, 0x17, 0x08, 0x3d, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xfa, 0x00, 0x00, 0x00, +0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x70, 0x00, +0x00, 0x00, 0x20, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x84, 0x1c, 0x1e, +0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x8a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x00, +0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, +0x9f, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x05, 0x12, 0x06, 0x31, 0xff, +0x17, 0x08, 0x3d, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x2e, 0x10, 0x7b, 0xff, 0x37, 0x13, 0x93, 0xff, +0x37, 0x13, 0x93, 0xff, 0x8c, 0x49, 0x19, 0xc4, 0xff, 0x06, 0x40, 0x16, 0xac, 0xff, 0x37, 0x13, +0x93, 0xff, 0x37, 0x13, 0x93, 0xff, 0x25, 0x0d, 0x62, 0xff, 0x20, 0x0b, 0x56, 0xff, 0x12, 0x06, +0x31, 0xff, 0x05, 0x02, 0x0c, 0xff, 0xf8, 0x00, 0x00, 0x00, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x02, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x10, 0x9a, 0x00, 0x00, +0x00, 0x00, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x8b, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, +0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x30, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0xaf, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xef, 0x83, 0x1c, +0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xdf, 0xfd, 0x00, 0x00, 0x00, 0xff, 0xff, +0x00, 0x00, 0x00, 0xff, 0xb3, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, +0x00, 0x9f, 0x00, 0x00, 0x00, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, +0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, +0x00, 0x00, 0x00, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x89, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x30, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, +0xbf, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0xdf, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x85, 0x24, 0x60, +0x36, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x86, 0x24, 0x60, 0x36, 0xff, +0x03, 0x17, 0x3c, 0x21, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x0e, 0x24, 0x14, +0xff, 0xfb, 0x00, 0x00, 0x00, 0xff, 0xd3, 0x00, 0x00, 0x00, 0xff, 0x03, 0x0e, 0x24, 0x14, 0xff, +0x12, 0x30, 0x1b, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x86, 0x24, 0x60, 0x36, +0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x36, 0x90, 0x50, 0xff, 0x85, 0x24, 0x60, 0x36, 0xff, 0x00, +0x20, 0x54, 0x2f, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, +0x00, 0x10, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x84, 0x1c, 0x1e, 0x1d, +0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, +0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x87, +0x1c, 0x1e, 0x1d, 0xff, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x84, 0x1c, +0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x80, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xaf, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x02, +0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x92, 0x48, 0xc0, 0x6b, +0xff, 0x06, 0x3b, 0x9c, 0x57, 0xff, 0x36, 0x90, 0x50, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x24, 0x60, +0x36, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xf8, 0x00, +0x00, 0x00, 0xff, 0xc5, 0x00, 0x00, 0x00, 0xff, 0x05, 0x12, 0x30, 0x1b, 0xff, 0x1b, 0x48, 0x28, +0xff, 0x24, 0x60, 0x36, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x36, 0x90, 0x50, 0xff, 0x3b, 0x9c, 0x57, +0xff, 0x92, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, +0x30, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x50, 0x84, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0xaf, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x30, 0x87, 0x1c, 0x1e, 0x1d, 0xff, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0xaf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00, +0xd5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xcf, 0xa4, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x98, 0x48, 0xc0, 0x6b, +0xff, 0x04, 0x44, 0xb4, 0x64, 0xff, 0x36, 0x90, 0x50, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x1b, 0x48, +0x28, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xfa, 0x00, 0x00, 0x00, 0xff, 0xb8, 0x00, 0x00, 0x00, 0xff, +0x04, 0x0e, 0x24, 0x14, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x24, 0x60, 0x36, 0xff, 0x36, 0x90, 0x50, +0xff, 0x44, 0xb4, 0x64, 0xff, 0x98, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x05, +0x0c, 0x07, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x94, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x10, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, +0x10, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, +0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xef, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, +0x1e, 0x1d, 0x20, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0xa7, +0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x9c, 0x48, 0xc0, +0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, 0x24, 0x60, 0x36, 0xff, 0x12, 0x30, 0x1b, 0xff, 0xfc, +0x00, 0x00, 0x00, 0xff, 0xae, 0x00, 0x00, 0x00, 0xff, 0x02, 0x12, 0x30, 0x1b, 0xff, 0x24, 0x60, +0x36, 0xff, 0x36, 0x90, 0x50, 0xff, 0x9c, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, +0x17, 0x3c, 0x21, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x94, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xaf, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0x70, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x86, 0x1c, 0x1e, 0x1d, +0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, +0x87, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x02, 0x1c, 0x1e, 0x1d, 0xaf, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xcf, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, +0x64, 0xff, 0x9f, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, 0x24, 0x60, 0x36, 0xff, +0x0e, 0x24, 0x14, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, +0x24, 0x14, 0xff, 0x24, 0x60, 0x36, 0xff, 0x36, 0x90, 0x50, 0xff, 0x9f, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x40, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x84, 0x1c, 0x1e, +0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xdf, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x80, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x88, 0x1c, 0x1e, 0x1d, 0x40, +0x01, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x9f, 0x88, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, +0x1e, 0x1d, 0x70, 0x87, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, +0xef, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x02, 0x1c, 0x1e, 0x1d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xab, 0x00, 0x00, +0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xa1, 0x48, 0xc0, 0x6b, 0xff, +0x02, 0x3f, 0xa8, 0x5e, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x17, 0x3c, 0x21, 0xff, 0xfc, 0x00, 0x00, +0x00, 0xff, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x02, 0x17, 0x3c, 0x21, 0xff, 0x29, 0x6c, 0x3c, 0xff, +0x3f, 0xa8, 0x5e, 0xff, 0xa1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, +0x14, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, +0x92, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, 0x84, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x9b, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x87, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xef, +0x82, 0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xad, +0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xa4, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, +0xb4, 0x64, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, +0x9a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x24, 0x14, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xa4, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xab, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, +0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x10, 0x87, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x9a, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x87, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, +0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x82, 0x00, 0x00, 0x00, 0x00, 0xd2, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xa6, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3b, 0x9c, 0x57, +0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0x94, 0x00, +0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x3b, 0x9c, 0x57, 0xff, +0xa7, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0xac, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x20, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x20, 0x85, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x99, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xcf, 0x88, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, +0x1c, 0x1e, 0x1d, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0xab, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x0c, 0x07, 0xff, 0x17, 0x3c, 0x21, +0xff, 0x29, 0x6c, 0x3c, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, +0xb4, 0x64, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, +0x90, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, 0x0d, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x44, 0xb4, 0x64, 0xff, 0x2d, 0x78, 0x43, 0xff, +0x17, 0x3c, 0x21, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x9f, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x85, 0x1c, 0x1e, 0x1d, +0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, +0x98, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xcf, 0x1c, 0x1e, 0x1d, 0x10, 0x87, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x83, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0x82, 0x12, 0x30, 0x1b, 0xff, +0x82, 0x24, 0x60, 0x36, 0xff, 0x02, 0x2d, 0x78, 0x43, 0xff, 0x36, 0x90, 0x50, 0xff, 0x36, 0x90, +0x50, 0xff, 0xb1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, +0xfd, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x2d, +0x78, 0x43, 0xff, 0xb1, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, 0x36, 0x90, 0x50, +0xff, 0x2d, 0x78, 0x43, 0xff, 0x82, 0x24, 0x60, 0x36, 0xff, 0x82, 0x12, 0x30, 0x1b, 0xff, 0x00, +0x05, 0x0c, 0x07, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0x93, 0x00, +0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, 0x84, 0x1c, 0x1e, 0x1d, +0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, 0x10, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, +0x1c, 0x1e, 0x1d, 0x80, 0x96, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, +0x1d, 0x80, 0x88, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xef, +0x84, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x10, 0x83, 0x00, +0x00, 0x00, 0x00, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, +0x00, 0xff, 0x05, 0x05, 0x0c, 0x07, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x24, +0x60, 0x36, 0xff, 0x36, 0x90, 0x50, 0xff, 0x36, 0x90, 0x50, 0xff, 0xbf, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xfd, 0x00, 0x00, 0x00, 0xff, 0x87, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xbf, 0x48, 0xc0, 0x6b, +0xff, 0x05, 0x36, 0x90, 0x50, 0xff, 0x36, 0x90, 0x50, 0xff, 0x24, 0x60, 0x36, 0xff, 0x20, 0x54, +0x2f, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x50, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x85, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xcf, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x80, 0x93, 0x1c, 0x1e, 0x1d, 0xff, 0x03, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0xbf, +0x1c, 0x1e, 0x1d, 0x70, 0x1c, 0x1e, 0x1d, 0x10, 0x88, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, +0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xcf, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x60, +0x84, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x95, +0x00, 0x00, 0x00, 0xff, 0x03, 0x09, 0x18, 0x0d, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x2d, 0x78, 0x43, +0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xc6, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, +0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xfc, 0x00, 0x00, 0x00, 0xff, 0x84, 0x00, 0x00, 0x00, +0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc6, 0x48, +0xc0, 0x6b, 0xff, 0x03, 0x3f, 0xa8, 0x5e, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x1b, 0x48, 0x28, 0xff, +0x09, 0x18, 0x0d, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x94, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, +0x1d, 0x9f, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x85, 0x1c, 0x1e, 0x1d, +0xff, 0x00, 0x1c, 0x1e, 0x1d, 0xbf, 0x85, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, +0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xcf, 0x93, 0x00, 0x00, +0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xcc, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x17, 0x3c, 0x21, 0xff, 0xfd, 0x00, 0x00, +0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x3f, +0xa8, 0x5e, 0xff, 0xcc, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3b, 0x9c, 0x57, 0xff, 0x20, 0x54, 0x2f, +0xff, 0x09, 0x18, 0x0d, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xef, 0x00, +0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, +0x01, 0x1c, 0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0xef, 0x85, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, +0x1e, 0x1d, 0x9f, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x85, 0x1c, 0x1e, +0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x10, 0x85, 0x00, 0x00, 0x00, 0x00, +0xca, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, +0x00, 0xdf, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, +0xd1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xfb, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xd1, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x50, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, +0x1d, 0x50, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xaf, 0x1c, 0x1e, 0x1d, 0x10, +0xa0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0xbf, 0x86, 0x1c, +0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x40, 0x86, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbf, 0x96, 0x00, 0x00, 0x00, 0xff, +0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xd3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x12, 0x30, 0x1b, 0xff, 0xf9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, +0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xd3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x12, +0x30, 0x1b, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, +0x70, 0x00, 0x00, 0x00, 0x10, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x70, 0x86, +0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xcf, 0x1c, 0x1e, 0x1d, 0x30, 0x9e, 0x00, 0x00, +0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x30, 0x1c, 0x1e, 0x1d, 0xcf, 0x86, 0x1c, 0x1e, 0x1d, 0xff, +0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x87, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, +0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xd2, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x24, 0x60, 0x36, 0xff, 0xf7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xd2, 0x48, +0xc0, 0x6b, 0xff, 0x02, 0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x8d, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, +0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x70, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x70, +0x1c, 0x1e, 0x1d, 0xef, 0x86, 0x1c, 0x1e, 0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x8f, 0x88, 0x00, +0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0xaf, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xd1, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xf3, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xd1, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x40, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, +0x9f, 0x87, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0x30, 0x98, +0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0xbf, 0x87, 0x1c, 0x1e, +0x1d, 0xff, 0x00, 0x1c, 0x1e, 0x1d, 0x9f, 0x89, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xef, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x00, +0x2d, 0x78, 0x43, 0xff, 0xd1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, +0x07, 0xff, 0xf1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, +0xd1, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x8f, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x80, 0x88, 0x1c, +0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x9f, 0x1c, 0x1e, 0x1d, 0x30, 0x94, 0x00, 0x00, 0x00, +0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0xbf, 0x88, 0x1c, 0x1e, 0x1d, 0xff, 0x00, +0x1c, 0x1e, 0x1d, 0x70, 0x8a, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x60, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0xd1, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xef, 0x00, 0x00, 0x00, 0xff, +0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xd1, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, +0x90, 0x50, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x1d, 0x60, 0x89, 0x1c, 0x1e, 0x1d, 0xff, +0x02, 0x1c, 0x1e, 0x1d, 0xcf, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x10, 0x8e, 0x00, 0x00, +0x00, 0x00, 0x02, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0xcf, 0x88, +0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x60, 0x8b, 0x00, 0x00, +0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa5, 0x00, 0x00, 0x00, +0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x24, 0x60, 0x36, 0xff, 0xd2, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xed, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, +0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, +0x0e, 0x24, 0x14, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, +0x00, 0x10, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x30, 0x1c, 0x1e, 0x1d, 0xdf, +0x8a, 0x1c, 0x1e, 0x1d, 0xff, 0x03, 0x1c, 0x1e, 0x1d, 0xcf, 0x1c, 0x1e, 0x1d, 0x80, 0x1c, 0x1e, +0x1d, 0x50, 0x1c, 0x1e, 0x1d, 0x30, 0x86, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x1e, 0x1d, 0x30, +0x1c, 0x1e, 0x1d, 0x50, 0x1c, 0x1e, 0x1d, 0x8f, 0x1c, 0x1e, 0x1d, 0xcf, 0x8a, 0x1c, 0x1e, 0x1d, +0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xcf, 0x1c, 0x1e, 0x1d, 0x30, 0x8c, 0x00, 0x00, 0x00, 0x00, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, +0x24, 0x14, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xd5, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xeb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd5, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3f, 0xa8, 0x5e, +0xff, 0x29, 0x6c, 0x3c, 0xff, 0x12, 0x30, 0x1b, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, +0x8f, 0x8f, 0x1c, 0x1e, 0x1d, 0xff, 0x02, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, +0x1e, 0x1d, 0xdf, 0x8f, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0x8f, 0x1c, 0x1e, 0x1d, +0x10, 0x8d, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0xa0, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x0c, 0x07, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x2d, 0x78, +0x43, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd9, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, +0x05, 0x0c, 0x07, 0xff, 0xe9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, +0x57, 0xff, 0xd9, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x44, 0xb4, 0x64, 0xff, 0x2d, 0x78, 0x43, 0xff, +0x17, 0x3c, 0x21, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x80, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0xbf, +0x9e, 0x1c, 0x1e, 0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0x30, 0x8f, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9d, 0x00, 0x00, +0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xde, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0xe9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, +0x9c, 0x57, 0xff, 0xde, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8e, +0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0xbf, 0x9a, 0x1c, 0x1e, +0x1d, 0xff, 0x01, 0x1c, 0x1e, 0x1d, 0xbf, 0x1c, 0x1e, 0x1d, 0x40, 0x91, 0x00, 0x00, 0x00, 0x00, +0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x02, +0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xe2, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xe7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, +0xe2, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, +0x07, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x90, 0x00, 0x00, 0x00, +0x00, 0x01, 0x1c, 0x1e, 0x1d, 0x40, 0x1c, 0x1e, 0x1d, 0x9f, 0x95, 0x1c, 0x1e, 0x1d, 0xff, 0x02, +0x1c, 0x1e, 0x1d, 0xef, 0x1c, 0x1e, 0x1d, 0x9f, 0x1c, 0x1e, 0x1d, 0x40, 0x93, 0x00, 0x00, 0x00, +0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x99, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xe6, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xe5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, +0xff, 0xe6, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0x00, 0x00, +0x00, 0x00, 0x03, 0x1c, 0x1e, 0x1d, 0x10, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x9f, 0x1c, +0x1e, 0x1d, 0xef, 0x8e, 0x1c, 0x1e, 0x1d, 0xff, 0x03, 0x1c, 0x1e, 0x1d, 0xdf, 0x1c, 0x1e, 0x1d, +0x9f, 0x1c, 0x1e, 0x1d, 0x60, 0x1c, 0x1e, 0x1d, 0x10, 0x95, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x97, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, 0x24, +0x14, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe8, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xe3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, +0x0d, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe8, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, +0x2d, 0x78, 0x43, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x1e, 0x1d, 0x20, 0x1c, 0x1e, 0x1d, 0x50, +0x1c, 0x1e, 0x1d, 0x80, 0x1c, 0x1e, 0x1d, 0x9f, 0x86, 0x1c, 0x1e, 0x1d, 0xbf, 0x03, 0x1c, 0x1e, +0x1d, 0x9f, 0x1c, 0x1e, 0x1d, 0x80, 0x1c, 0x1e, 0x1d, 0x50, 0x1c, 0x1e, 0x1d, 0x20, 0x99, 0x00, +0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x95, 0x00, 0x00, +0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x36, 0x90, 0x50, 0xff, 0xec, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x36, 0x90, 0x50, 0xff, 0xe3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xec, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, +0x3f, 0xa8, 0x5e, 0xff, 0xef, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xe1, 0x00, +0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0xef, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, +0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, +0xbd, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x92, +0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xf1, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, +0xa8, 0x5e, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xbf, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xf4, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0xf4, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, 0x0d, 0xff, +0x8f, 0x00, 0x00, 0x00, 0xff, 0xbd, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xdf, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xf5, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x05, 0x0c, 0x07, 0xff, +0xdd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf5, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x8e, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xbf, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, +0x30, 0x1b, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x83, 0x24, 0x60, 0x36, 0xff, 0x01, 0x36, 0x90, 0x50, +0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xdd, +0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, +0xa8, 0x5e, 0xff, 0x36, 0x90, 0x50, 0xff, 0x83, 0x24, 0x60, 0x36, 0xff, 0x01, 0x32, 0x84, 0x4a, +0xff, 0x17, 0x3c, 0x21, 0xff, 0x8d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, +0x00, 0x00, 0x50, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x70, 0x00, 0x00, 0x00, 0xef, 0x98, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, 0x0d, 0xff, +0x24, 0x60, 0x36, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xee, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, +0x64, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xdb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xee, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3f, 0xa8, 0x5e, 0xff, 0x24, 0x60, +0x36, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xaf, +0x00, 0x00, 0x00, 0x10, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xbf, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x24, 0x60, 0x36, +0xff, 0x44, 0xb4, 0x64, 0xff, 0xed, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xdb, +0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xed, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x50, 0xb8, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xef, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, +0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xed, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x3b, 0x9c, 0x57, 0xff, 0xdb, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0xed, 0x48, +0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xb7, 0x00, 0x00, 0x00, 0x00, 0xb5, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, +0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf0, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x0e, 0x24, 0x14, 0xff, 0xd9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0xf0, +0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x20, 0xb5, +0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0xbf, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xd9, 0x00, +0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, +0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x9b, 0x00, 0x00, 0x00, 0xff, +0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf4, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xd9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, 0x57, +0xff, 0xf4, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x50, 0xb3, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xcf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, +0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf7, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, +0xd7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0xf7, 0x48, 0xc0, 0x6b, 0xff, 0x02, +0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x99, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x99, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, +0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf9, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x20, 0x54, 0x2f, 0xff, 0xd7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xf9, +0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xb1, 0x00, 0x00, 0x00, 0x00, +0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, +0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfa, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, +0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xd7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, +0x3b, 0x9c, 0x57, 0xff, 0xfa, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x20, 0x54, +0x2f, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, +0xb0, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x98, +0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xfb, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xd9, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfb, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, +0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xcf, 0x00, 0x00, 0x00, 0x10, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x40, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x36, 0x90, +0x50, 0xff, 0xfc, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, +0xdb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfc, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xdf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, +0x6c, 0x3c, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, +0xff, 0xdd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xae, 0x00, 0x00, 0x00, 0x00, 0xad, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, +0x14, 0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, +0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x93, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xae, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x93, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, +0xc0, 0x6b, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xe1, 0x00, 0x00, 0x00, 0xff, +0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, +0xc0, 0x6b, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x50, 0xad, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, 0xc0, 0x6b, 0xff, 0x44, 0xb4, 0x64, 0xff, +0x0e, 0x24, 0x14, 0xff, 0xe3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, 0xc0, 0x6b, 0xff, 0x44, 0xb4, 0x64, 0xff, +0x17, 0x3c, 0x21, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xad, 0x00, +0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x92, 0x00, 0x00, +0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, 0xc0, 0x6b, +0xff, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xe5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, 0xc0, 0x6b, +0xff, 0x48, 0xc0, 0x6b, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x20, 0xac, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, +0x03, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x0e, 0x24, 0x14, +0xff, 0xe7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xfd, +0x48, 0xc0, 0x6b, 0xff, 0x03, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x36, 0x90, 0x50, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xac, +0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x90, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xfd, 0x48, 0xc0, 0x6b, +0xff, 0x03, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, +0x07, 0xff, 0xe9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, +0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, +0x57, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, +0xac, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, +0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, +0x6b, 0xff, 0x03, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xc3, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, +0xff, 0x3b, 0x9c, 0x57, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x48, 0xc0, 0x6b, 0xff, 0x48, +0xc0, 0x6b, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x8d, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xbf, 0xac, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x85, 0x24, +0x60, 0x36, 0xff, 0x02, 0x32, 0x84, 0x4a, 0xff, 0x36, 0x90, 0x50, 0xff, 0x44, 0xb4, 0x64, 0xff, +0xf6, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x04, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x48, 0xc0, 0x6b, 0xff, +0x3f, 0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0xbf, 0x00, 0x00, 0x00, 0xff, 0x04, 0x1b, 0x48, +0x28, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, +0x07, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xf6, 0x48, 0xc0, 0x6b, +0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x36, 0x90, 0x50, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x85, 0x24, +0x60, 0x36, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x8d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0xdf, 0xac, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x80, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xf3, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, +0xff, 0x12, 0x30, 0x1b, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3b, +0x9c, 0x57, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, +0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x2d, 0x78, 0x43, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0xac, 0x00, +0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9a, 0x00, 0x00, +0x00, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x1b, 0x48, 0x28, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x87, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xb7, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x87, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x1b, 0x48, 0x28, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xf1, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x99, 0x00, 0x00, +0x00, 0xff, 0xac, 0x00, 0x00, 0x00, 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x8f, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xf1, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x92, 0x00, 0x00, +0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, +0xff, 0x1b, 0x48, 0x28, 0xff, 0xb5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, +0xb4, 0x64, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf1, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x96, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xac, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x98, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, +0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x8c, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xb1, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x8c, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, +0x57, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, +0x3f, 0xa8, 0x5e, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, +0x07, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x20, +0xaa, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0xcf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, +0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x91, +0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8e, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xaf, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x18, 0x0d, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x8e, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, +0xff, 0x3b, 0x9c, 0x57, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x0e, +0x24, 0x14, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x40, 0xa9, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, +0x00, 0x00, 0x00, 0xdf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xf3, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x91, 0x00, 0x00, 0x00, +0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x91, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, +0x0e, 0x24, 0x14, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, +0x64, 0xff, 0x91, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x92, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, +0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa8, 0x00, 0x00, 0x00, 0x00, 0xa6, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0x96, 0x00, 0x00, +0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x20, 0x54, 0x2f, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x3b, +0x9c, 0x57, 0xff, 0x93, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, +0xff, 0xab, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x93, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x91, 0x00, 0x00, +0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, +0xff, 0x09, 0x18, 0x0d, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa7, +0x00, 0x00, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, +0x00, 0xef, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, +0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x95, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x95, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, +0x64, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x17, 0x3c, +0x21, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xa6, 0x00, 0x00, 0x00, +0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, +0x9c, 0x57, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, +0xff, 0x98, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa7, +0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x98, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x18, 0x0d, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x29, +0x6c, 0x3c, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0xa5, 0x00, 0x00, +0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x95, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x36, 0x90, 0x50, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, +0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x9a, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, +0x05, 0x0c, 0x07, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, +0x57, 0xff, 0x9a, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x0e, 0x24, 0x14, 0xff, +0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xf3, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x93, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xa3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, +0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x54, 0x2f, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x9c, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, +0x84, 0x4a, 0xff, 0x9d, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x91, 0x00, 0x00, +0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x9f, 0xa4, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdf, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, +0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x90, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x9f, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, +0x9f, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x90, 0x00, +0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xf2, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x40, 0xa3, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x60, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xf3, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, +0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xa0, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, +0xff, 0x44, 0xb4, 0x64, 0xff, 0xa0, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x17, +0x3c, 0x21, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, +0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xaf, 0xa3, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xbf, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xf3, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, +0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xa3, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, +0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xa3, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x54, +0x2f, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, +0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xa1, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, +0x78, 0x43, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x0e, 0x24, 0x14, +0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xa5, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, +0x18, 0x0d, 0xff, 0xa5, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, +0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xf2, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x70, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xf2, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0xa7, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, +0x43, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xa7, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xf2, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, +0x43, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xa2, 0x00, 0x00, 0x00, +0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x91, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2d, 0x78, 0x43, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x17, +0x3c, 0x21, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, 0x5e, +0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, +0x00, 0x09, 0x18, 0x0d, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, +0x30, 0x1b, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, +0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, +0x00, 0x00, 0x00, 0xff, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xf1, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0xab, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, +0x60, 0x36, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xab, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, +0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x10, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, +0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x24, 0x60, 0x36, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x3f, 0xa8, +0x5e, 0xff, 0xac, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x9d, 0x00, 0x00, 0x00, +0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xac, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, +0x17, 0x3c, 0x21, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xf1, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x40, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, +0xff, 0x03, 0x09, 0x18, 0x0d, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x0e, 0x24, +0x14, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x03, 0x0e, 0x24, 0x14, 0xff, 0x17, 0x3c, 0x21, 0xff, +0x29, 0x6c, 0x3c, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe5, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, +0x57, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, +0x32, 0x84, 0x4a, 0xff, 0xaf, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x9b, 0x00, +0x00, 0x00, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0xaf, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, +0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, +0x3b, 0x9c, 0x57, 0xff, 0xe5, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x44, 0xb4, 0x64, 0xff, 0x29, 0x6c, +0x3c, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x03, +0x09, 0x18, 0x0d, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x09, 0x18, 0x0d, 0xff, +0x8d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa1, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x99, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, +0xb4, 0x64, 0xff, 0xb0, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x9b, 0x00, 0x00, +0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xb0, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, +0xff, 0x20, 0x54, 0x2f, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xe3, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x98, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x98, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, +0x3b, 0x9c, 0x57, 0xff, 0xe2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, +0x1b, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, +0xb2, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, +0x32, 0x84, 0x4a, 0xff, 0xb2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, +0x0d, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, 0x5e, 0xff, +0xe2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, +0xff, 0x3b, 0x9c, 0x57, 0xff, 0xe2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, +0xff, 0xb4, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, +0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xb4, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, +0xff, 0xe2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x96, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xa1, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, +0x0d, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, +0x12, 0x30, 0x1b, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, +0x5e, 0xff, 0xb6, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x99, 0x00, 0x00, 0x00, +0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0xb6, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, +0x12, 0x30, 0x1b, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, +0x5e, 0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x0e, 0x24, 0x14, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xa1, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x32, +0x84, 0x4a, 0xff, 0xb8, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x99, 0x00, 0x00, +0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xb8, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, +0xff, 0x09, 0x18, 0x0d, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, +0x6c, 0x3c, 0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, +0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xa2, 0x00, 0x00, 0x00, 0x00, +0xa0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0x94, 0x00, +0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe0, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, +0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xb9, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, +0x28, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0xb9, 0x48, 0xc0, 0x6b, +0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8e, 0x00, +0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xe0, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x70, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, +0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8e, +0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xbb, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, +0xff, 0xbb, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x8e, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0xe1, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x60, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xe0, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, +0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xbd, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, +0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xbd, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x36, 0x90, 0x50, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, +0x1b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xe0, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, +0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0x9f, 0x00, +0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x94, 0x00, 0x00, +0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xe0, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, +0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0xbf, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, +0x60, 0x36, 0xff, 0xbf, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xe0, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x2d, 0x78, 0x43, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, +0x00, 0x00, 0x10, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x50, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xdf, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, +0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc0, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xc0, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x24, 0x14, 0xff, 0x36, 0x90, 0x50, 0xff, 0xdf, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, +0x43, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9e, 0x00, 0x00, 0x00, +0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x93, +0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xde, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, +0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xc2, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x99, +0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xc2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, +0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x54, 0x2f, +0xff, 0x44, 0xb4, 0x64, 0xff, 0xde, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x92, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, +0x43, 0xff, 0xde, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x09, 0x18, 0x0d, 0xff, +0x8d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x36, 0x90, 0x50, 0xff, 0xc4, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0xc4, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x12, 0x30, 0x1b, 0xff, +0x8d, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xde, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xdd, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x8d, 0x00, 0x00, +0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xc6, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x24, 0x60, 0x36, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xc6, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8d, 0x00, 0x00, +0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xdd, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x2d, 0x78, 0x43, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x9c, +0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x92, 0x00, +0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xdd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x24, 0x60, +0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, +0x2d, 0x78, 0x43, 0xff, 0xc8, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x99, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xc8, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, +0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, +0x24, 0x60, 0x36, 0xff, 0xdd, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x91, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, +0xff, 0xdc, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8c, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0xca, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, +0xff, 0xca, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8c, +0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xdc, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x9f, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xdb, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, +0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xcb, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x12, 0x30, 0x1b, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0xcb, 0x48, +0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x8c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xdb, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x44, +0xb4, 0x64, 0xff, 0xda, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, +0xb4, 0x64, 0xff, 0xcd, 0x48, 0xc0, 0x6b, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0xcd, 0x48, 0xc0, +0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8b, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0xda, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x60, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xd9, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x8b, 0x00, 0x00, 0x00, +0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xce, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, +0x57, 0xff, 0xce, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, +0x50, 0xff, 0xd9, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0x8f, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xd8, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x8b, 0x00, 0x00, +0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd0, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, +0x84, 0x4a, 0xff, 0xd0, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x3f, +0xa8, 0x5e, 0xff, 0xd8, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x8e, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, +0x44, 0xb4, 0x64, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xd0, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x8a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xd2, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x9b, 0x00, 0x00, 0x00, +0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xd2, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, +0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, +0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0xd0, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, +0x44, 0xb4, 0x64, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, +0x0d, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x99, 0x00, 0x00, 0x00, +0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x05, 0x2d, 0x78, 0x43, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x36, 0x90, 0x50, 0xff, 0x24, 0x60, 0x36, +0xff, 0x12, 0x30, 0x1b, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x02, 0x0e, +0x24, 0x14, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xca, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x32, 0x84, 0x4a, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, +0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd4, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x12, 0x30, 0x1b, 0xff, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xd4, +0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xca, +0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3f, 0xa8, 0x5e, 0xff, 0x24, 0x60, 0x36, 0xff, 0x0e, 0x24, 0x14, +0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x0c, 0x07, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x24, +0x60, 0x36, 0xff, 0x36, 0x90, 0x50, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x8e, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x99, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, +0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x36, 0x90, 0x50, 0xff, 0xc7, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x8a, 0x00, 0x00, +0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd6, +0x48, 0xc0, 0x6b, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0xd6, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, +0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, +0x01, 0x12, 0x30, 0x1b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xc7, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, +0x90, 0x50, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, +0xff, 0x1b, 0x48, 0x28, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x99, +0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, +0x18, 0x0d, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc5, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, +0xff, 0x20, 0x54, 0x2f, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, 0x0d, 0xff, 0x2d, +0x78, 0x43, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xd7, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, +0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xd7, 0x48, 0xc0, 0x6b, 0xff, +0x02, 0x44, 0xb4, 0x64, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8a, 0x00, 0x00, +0x00, 0xff, 0x01, 0x20, 0x54, 0x2f, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc6, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x0e, 0x24, 0x14, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x40, 0x99, +0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x9a, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xc5, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x29, 0x6c, 0x3c, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, +0x09, 0x18, 0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xda, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xda, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0xc5, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, +0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, +0x99, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x99, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xc4, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, +0x01, 0x12, 0x30, 0x1b, 0xff, 0x36, 0x90, 0x50, 0xff, 0xdc, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x0e, +0x24, 0x14, 0xff, 0x9d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0xdc, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, +0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xc4, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, +0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x98, 0x00, 0x00, 0x00, 0xff, 0x9a, 0x00, 0x00, 0x00, +0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x98, 0x00, 0x00, 0x00, 0xff, +0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xc3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, +0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, +0xff, 0x3b, 0x9c, 0x57, 0xff, 0xdd, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x9f, +0x00, 0x00, 0x00, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xdd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, +0x9c, 0x57, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, +0xff, 0x3b, 0x9c, 0x57, 0xff, 0xc3, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x0e, +0x24, 0x14, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x9a, 0x00, 0x00, +0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x97, 0x00, 0x00, 0x00, +0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc2, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, +0x07, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xdf, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x29, 0x6c, 0x3c, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xdf, 0x48, +0xc0, 0x6b, 0xff, 0x02, 0x3f, 0xa8, 0x5e, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x88, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc2, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x95, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xaf, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xc2, +0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, 0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x44, +0xb4, 0x64, 0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x9f, 0x00, 0x00, +0x00, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0xe1, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, +0xff, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, +0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xc2, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x24, 0x60, 0x36, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, +0x00, 0x00, 0x10, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xaf, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, +0xc2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x87, 0x00, +0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xe3, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, +0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0xe3, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x32, 0x84, 0x4a, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, +0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xc2, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, +0x00, 0x10, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x60, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xc1, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x86, 0x00, 0x00, +0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xe5, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, +0xff, 0xe5, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3f, 0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, +0xff, 0xc1, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x91, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0x92, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xc0, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x3b, 0x9c, 0x57, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, +0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xe7, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x09, 0x18, 0x0d, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, +0x00, 0x30, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0xe7, 0x48, 0xc0, 0x6b, +0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x86, 0x00, +0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x36, 0x90, 0x50, 0xff, 0xc0, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, +0xff, 0xbf, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x86, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x36, 0x90, 0x50, 0xff, 0xe9, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, +0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, +0x78, 0x43, 0xff, 0xe9, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x1b, 0x48, 0x28, +0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xbf, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x91, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0x98, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xbe, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, +0x36, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, 0x0d, 0xff, 0x29, 0x6c, 0x3c, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xeb, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x8e, 0x00, +0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x8f, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xeb, 0x48, +0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x09, 0x18, 0x0d, 0xff, +0x85, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x54, 0x2f, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xbe, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x90, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x98, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, +0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xbd, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, +0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, +0x48, 0x28, 0xff, 0x36, 0x90, 0x50, 0xff, 0xed, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3b, 0x9c, 0x57, +0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, +0xff, 0xed, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x84, +0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, 0xb4, 0x64, +0xff, 0xbd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x90, +0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, +0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xbd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x02, 0x09, 0x18, 0x0d, 0xff, 0x29, 0x6c, +0x3c, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xef, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, +0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xcf, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xef, 0x48, +0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x09, 0x18, 0x0d, 0xff, +0x83, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xbd, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xef, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0xbc, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x82, 0x00, 0x00, +0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x36, 0x90, 0x50, 0xff, 0xf1, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xbf, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x91, 0x00, 0x00, +0x00, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xf1, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, +0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, +0x18, 0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xbc, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x32, 0x84, 0x4a, +0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, 0x00, 0x00, 0x00, 0x00, +0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x48, 0x28, 0xff, 0xbb, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x36, 0x90, 0x50, 0xff, 0x0e, 0x24, +0x14, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x02, 0x12, 0x30, 0x1b, 0xff, 0x2d, 0x78, 0x43, 0xff, +0x44, 0xb4, 0x64, 0xff, 0xf3, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x8f, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xf3, 0x48, 0xc0, 0x6b, +0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x82, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0xbb, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x96, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x90, +0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xb9, 0x48, 0xc0, +0x6b, 0xff, 0x06, 0x36, 0x90, 0x50, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x24, 0x60, 0x36, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xf5, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xf5, 0x48, 0xc0, 0x6b, 0xff, +0x06, 0x3f, 0xa8, 0x5e, 0xff, 0x24, 0x60, 0x36, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x36, 0x90, 0x50, 0xff, 0xb9, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x10, 0x95, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xef, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0xb8, 0x48, +0xc0, 0x6b, 0xff, 0x05, 0x36, 0x90, 0x50, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x00, 0x00, 0x00, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x36, 0x90, 0x50, 0xff, 0xf8, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, +0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, +0x1b, 0x48, 0x28, 0xff, 0xf8, 0x48, 0xc0, 0x6b, 0xff, 0x05, 0x36, 0x90, 0x50, 0xff, 0x1b, 0x48, +0x28, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x36, 0x90, +0x50, 0xff, 0xb8, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x8f, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0x95, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x30, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xb7, +0x48, 0xc0, 0x6b, 0xff, 0x04, 0x3f, 0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x00, 0x00, 0x00, +0xff, 0x17, 0x3c, 0x21, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xfa, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, +0xa8, 0x5e, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x86, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, 0x57, +0xff, 0xfa, 0x48, 0xc0, 0x6b, 0xff, 0x04, 0x2d, 0x78, 0x43, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x00, +0x00, 0x00, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xb7, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x12, 0x30, 0x1b, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, +0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x90, 0x00, +0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xb5, 0x48, 0xc0, 0x6b, 0xff, 0x04, 0x3f, 0xa8, +0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x44, 0xb4, +0x64, 0xff, 0xfa, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, +0x17, 0x3c, 0x21, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x87, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, +0x1b, 0xff, 0xfc, 0x48, 0xc0, 0x6b, 0xff, 0x04, 0x44, 0xb4, 0x64, 0xff, 0x2d, 0x78, 0x43, 0xff, +0x0e, 0x24, 0x14, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xb5, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x95, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, +0x00, 0x00, 0x00, 0xff, 0x06, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x24, 0x60, 0x36, +0xff, 0x20, 0x54, 0x2f, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x09, 0x18, 0x0d, +0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xa7, +0x48, 0xc0, 0x6b, 0xff, 0x03, 0x3f, 0xa8, 0x5e, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x29, 0x6c, 0x3c, +0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xfb, 0x48, 0xc0, 0x6b, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x36, 0x90, 0x50, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x87, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x91, 0x00, 0x00, 0x00, +0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x3f, 0xa8, 0x5e, 0xff, +0x29, 0x6c, 0x3c, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xa7, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x06, +0x09, 0x18, 0x0d, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x1b, 0x48, 0x28, 0xff, +0x24, 0x60, 0x36, 0xff, 0x24, 0x60, 0x36, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8d, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0x9c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, 0xa6, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xfd, 0x48, 0xc0, +0x6b, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x8f, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, +0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x82, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xa7, 0x48, 0xc0, +0x6b, 0xff, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x95, 0x00, 0x00, 0x00, +0x00, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9b, 0x00, 0x00, 0x00, 0xff, +0x00, 0x12, 0x30, 0x1b, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xab, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x29, 0x6c, 0x3c, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x89, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, +0x3c, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xab, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x17, 0x3c, 0x21, +0xff, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x95, 0x00, 0x00, 0x00, 0x00, +0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x9b, 0x00, 0x00, 0x00, 0xff, 0x00, +0x29, 0x6c, 0x3c, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x10, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x91, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, +0x6b, 0xff, 0xab, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x99, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0x95, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xdf, 0x9a, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xfe, +0x48, 0xc0, 0x6b, 0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x90, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x20, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0xfe, 0x48, 0xc0, 0x6b, +0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x99, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x30, 0x95, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x8f, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0xfe, 0x48, +0xc0, 0x6b, 0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x90, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x8c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xfe, +0x48, 0xc0, 0x6b, 0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x97, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x96, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x99, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, +0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, +0x09, 0x18, 0x0d, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, +0x0d, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x2d, 0x78, 0x43, 0xff, 0x97, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x96, +0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x97, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, +0xff, 0xaa, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xfe, 0x48, 0xc0, +0x6b, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x95, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x96, 0x00, +0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x97, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa9, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, +0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, +0x36, 0x90, 0x50, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, +0x54, 0x2f, 0xff, 0x95, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x80, 0x97, 0x00, 0x00, +0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x96, 0x00, 0x00, 0x00, +0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0xdf, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x92, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, +0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x94, 0x00, 0x00, 0x00, 0xff, +0x00, 0x1b, 0x48, 0x28, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x17, 0x3c, 0x21, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x91, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xef, 0x92, 0x00, 0x00, 0x00, +0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0x98, +0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x94, 0x00, +0x00, 0x00, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0xbf, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x93, 0x00, 0x00, 0x00, 0xff, +0x00, 0x29, 0x6c, 0x3c, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x3f, 0xa8, 0x5e, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x99, 0x00, +0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x92, 0x00, 0x00, +0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x40, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x92, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xfd, 0x48, 0xc0, 0x6b, +0xff, 0xa9, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x20, 0x99, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x20, 0x92, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3f, 0xa8, +0x5e, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, +0xff, 0x0e, 0x24, 0x14, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x95, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, +0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, +0x00, 0x00, 0x00, 0x80, 0x99, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0xfe, 0x48, 0xc0, +0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x91, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xaf, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0xfe, 0x48, +0xc0, 0x6b, 0xff, 0xa8, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x90, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x10, 0x98, 0x00, 0x00, 0x00, 0x00, +0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, +0x0e, 0x24, 0x14, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x9c, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, +0xa8, 0x5e, 0xff, 0x8a, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x92, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x50, 0x97, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0xef, 0x93, 0x00, 0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x8a, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x9c, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x60, 0x98, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x60, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, +0x9b, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x32, 0x84, 0x4a, 0xff, 0x00, 0x00, 0x00, 0xff, 0x32, 0x84, +0x4a, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x92, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, 0x02, +0x36, 0x90, 0x50, 0xff, 0x00, 0x00, 0x00, 0xff, 0x2d, 0x78, 0x43, 0xff, 0xfc, 0x48, 0xc0, 0x6b, +0xff, 0x9d, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0xcf, 0x98, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xaf, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xfe, 0x48, +0xc0, 0x6b, 0xff, 0x9b, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x87, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, +0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x20, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x93, +0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x87, 0x48, 0xc0, +0x6b, 0xff, 0x03, 0x0e, 0x24, 0x14, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x3b, +0x9c, 0x57, 0xff, 0xfb, 0x48, 0xc0, 0x6b, 0xff, 0x9e, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, +0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, +0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x9b, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x85, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x50, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0xef, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x44, 0xb4, 0x64, +0xff, 0x85, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x9c, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x60, 0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x40, 0x91, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, +0x9a, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x83, 0x00, +0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, +0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xaf, +0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x20, 0x54, +0x2f, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, +0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x9b, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x97, 0x00, 0x00, +0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x90, 0x00, 0x00, 0x00, +0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x9a, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, +0x0c, 0x07, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x92, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x10, 0x9e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x84, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfd, 0x48, 0xc0, 0x6b, 0xff, 0x9b, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, +0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, +0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x9b, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, 0x9c, +0x57, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, 0x00, 0x00, +0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, +0x00, 0x00, 0x00, 0xcf, 0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x82, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, +0x1b, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x9b, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x17, 0x3c, 0x21, +0xff, 0x8d, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0x00, +0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, +0x32, 0x84, 0x4a, 0xff, 0x93, 0x36, 0x90, 0x50, 0xff, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x85, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x03, 0x29, 0x6c, +0x3c, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x70, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x30, 0x00, 0x00, 0x00, 0xef, 0x94, 0x00, 0x00, 0x00, 0xff, 0x03, 0x1b, 0x48, 0x28, 0xff, +0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x87, 0x00, 0x00, 0x00, +0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xfe, 0x48, 0xc0, 0x6b, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x3b, 0x9c, 0x57, 0xff, 0x92, 0x36, 0x90, 0x50, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0x8e, +0x00, 0x00, 0x00, 0xff, 0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x80, 0xaa, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x24, 0x60, 0x36, +0xff, 0xfc, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, +0x02, 0x17, 0x3c, 0x21, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x50, 0x95, 0x00, 0x00, 0x00, 0xff, 0x02, 0x1b, 0x48, 0x28, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x1b, +0x48, 0x28, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xfc, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, 0x12, 0x30, 0x1b, 0xff, 0xa9, 0x00, 0x00, 0x00, 0xff, +0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, +0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xfb, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, +0xff, 0x1b, 0x48, 0x28, 0xff, 0x93, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, +0x00, 0x00, 0x10, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, 0x00, 0x00, +0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, +0x00, 0x2d, 0x78, 0x43, 0xff, 0xfb, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, +0x24, 0x14, 0xff, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x97, 0x00, 0x00, +0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xa9, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xec, 0x48, 0xc0, 0x6b, 0xff, 0x02, +0x3f, 0xa8, 0x5e, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8b, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, +0x00, 0x00, 0x00, 0x10, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa1, 0x00, +0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x8b, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, +0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0xec, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0xbf, 0x97, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x40, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0xed, +0x48, 0xc0, 0x6b, 0xff, 0x03, 0x0e, 0x24, 0x14, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0e, 0x24, 0x14, +0xff, 0x44, 0xb4, 0x64, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, +0x0c, 0x07, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x30, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xa0, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x04, 0x44, +0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x44, +0xb4, 0x64, 0xff, 0xec, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, +0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x97, 0x00, 0x00, 0x00, 0x00, +0x97, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, +0xb4, 0x64, 0xff, 0xed, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x82, 0x00, 0x00, +0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x30, 0xa9, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xa0, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, +0x00, 0x20, 0x54, 0x2f, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xed, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa5, 0x00, 0x00, +0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0x97, 0x00, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xa5, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, +0x44, 0xb4, 0x64, 0xff, 0x98, 0x48, 0xc0, 0x6b, 0xff, 0x04, 0x3f, 0xa8, 0x5e, 0xff, 0x29, 0x6c, +0x3c, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x32, 0x84, 0x4a, 0xff, 0xcf, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0xb4, +0x64, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xab, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, +0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, +0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0xcf, 0x48, 0xc0, 0x6b, 0xff, 0x04, +0x36, 0x90, 0x50, 0xff, 0x00, 0x00, 0x00, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x29, 0x6c, 0x3c, 0xff, +0x3f, 0xa8, 0x5e, 0xff, 0x98, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, +0x14, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x97, 0x00, 0x00, 0x00, +0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xa4, 0x00, 0x00, 0x00, 0xff, +0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x95, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x44, +0xb4, 0x64, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x83, +0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0xbd, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8e, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, +0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0x85, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x00, 0x00, 0x60, 0xad, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0xcf, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x85, +0x48, 0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, +0x78, 0x43, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, 0xbd, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x03, 0x09, 0x18, 0x0d, +0xff, 0x20, 0x54, 0x2f, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x95, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa2, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x9f, 0x98, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xcf, 0xa2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x44, 0xb4, +0x64, 0xff, 0x92, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x44, 0xb4, 0x64, 0xff, 0x32, 0x84, 0x4a, 0xff, +0x20, 0x54, 0x2f, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3f, 0xa8, +0x5e, 0xff, 0xbb, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, +0x1b, 0x48, 0x28, 0xff, 0x8d, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x86, 0x00, +0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, +0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, +0xaf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xa0, 0x00, +0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x84, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, +0x8d, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x1b, 0x48, 0x28, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x3f, 0xa8, +0x5e, 0xff, 0xbc, 0x48, 0xc0, 0x6b, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x03, 0x0e, 0x24, 0x14, +0xff, 0x20, 0x54, 0x2f, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x92, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x30, 0xa3, 0x00, 0x00, 0x00, 0xff, 0x04, 0x0e, 0x24, 0x14, 0xff, 0x20, 0x54, +0x2f, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x36, 0x90, 0x50, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x88, 0x48, +0xc0, 0x6b, 0xff, 0x05, 0x3f, 0xa8, 0x5e, 0xff, 0x36, 0x90, 0x50, 0xff, 0x2d, 0x78, 0x43, 0xff, +0x24, 0x60, 0x36, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x8b, 0x00, 0x00, 0x00, +0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0xbb, 0x48, 0xc0, 0x6b, 0xff, 0x04, 0x3b, 0x9c, 0x57, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x24, 0x60, 0x36, 0xff, +0x8b, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x00, +0x24, 0x60, 0x36, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, +0x07, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x60, 0xb1, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, +0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x8b, 0x48, 0xc0, 0x6b, +0xff, 0x04, 0x29, 0x6c, 0x3c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x05, 0x0c, +0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0xbb, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, +0x8b, 0x00, 0x00, 0x00, 0xff, 0x05, 0x09, 0x18, 0x0d, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x24, 0x60, +0x36, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x36, 0x90, 0x50, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x88, 0x48, +0xc0, 0x6b, 0xff, 0x04, 0x44, 0xb4, 0x64, 0xff, 0x36, 0x90, 0x50, 0xff, 0x2d, 0x78, 0x43, 0xff, +0x20, 0x54, 0x2f, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xa1, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x8f, 0x99, 0x00, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x70, 0xa9, 0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x82, 0x12, 0x30, 0x1b, 0xff, +0x94, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x91, 0x48, 0xc0, 0x6b, 0xff, 0x03, +0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x3f, 0xa8, 0x5e, 0xff, +0x93, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x83, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, +0x50, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x88, 0x00, 0x00, 0x00, +0xff, 0x00, 0x2d, 0x78, 0x43, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, +0x00, 0x30, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, +0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x82, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x32, 0x84, 0x4a, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x2d, 0x78, +0x43, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3b, 0x9c, 0x57, 0xff, 0x83, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x3f, 0xa8, 0x5e, 0xff, 0x93, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x3f, 0xa8, 0x5e, 0xff, 0x09, 0x18, +0x0d, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x91, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x29, 0x6c, 0x3c, 0xff, 0x94, 0x00, 0x00, 0x00, 0xff, 0x82, 0x12, 0x30, 0x1b, 0xff, 0x00, 0x09, +0x18, 0x0d, 0xff, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x9a, 0x00, 0x00, +0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xc0, 0x00, 0x00, 0x00, +0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, +0x20, 0x54, 0x2f, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, +0x28, 0xff, 0x91, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x36, 0x90, 0x50, 0xff, 0x0e, 0x24, 0x14, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x8d, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x88, 0x48, 0xc0, 0x6b, +0xff, 0x00, 0x20, 0x54, 0x2f, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x04, 0x36, 0x90, 0x50, 0xff, +0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x30, 0xb5, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x9f, 0xa0, 0x00, 0x00, 0x00, +0xff, 0x04, 0x05, 0x0c, 0x07, 0xff, 0x36, 0x90, 0x50, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, +0x6b, 0xff, 0x36, 0x90, 0x50, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, +0x88, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x00, +0x24, 0x60, 0x36, 0xff, 0x8d, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, +0x07, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x36, 0x90, 0x50, 0xff, 0x91, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x1b, 0x48, 0x28, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x20, 0x54, +0x2f, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, +0xbe, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x9a, 0x00, +0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbe, 0x00, 0x00, +0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8b, 0x48, 0xc0, 0x6b, 0xff, +0x03, 0x44, 0xb4, 0x64, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, 0x07, +0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, 0x00, 0x12, +0x30, 0x1b, 0xff, 0x8b, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, +0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, +0x1b, 0x48, 0x28, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, 0x48, 0xc0, +0x6b, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x9f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, +0x00, 0x00, 0x00, 0x10, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xa1, 0x00, +0x00, 0x00, 0xff, 0x02, 0x2d, 0x78, 0x43, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, +0x8a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x86, 0x48, +0xc0, 0x6b, 0xff, 0x87, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x44, 0xb4, 0x64, +0xff, 0x8b, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x12, 0x30, 0x1b, 0xff, 0x82, 0x00, 0x00, 0x00, 0xff, +0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8f, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x12, +0x30, 0x1b, 0xff, 0x85, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, 0x28, +0xff, 0x32, 0x84, 0x4a, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8b, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xbc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xbf, 0x00, 0x00, 0x00, 0x10, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xdf, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, +0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x36, 0x90, 0x50, 0xff, +0x24, 0x60, 0x36, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x00, 0x24, 0x60, +0x36, 0xff, 0x8e, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x84, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x3b, 0x9c, 0x57, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x36, 0x90, +0x50, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x0e, 0x24, 0x14, 0xff, +0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, 0xff, 0x9f, 0x00, +0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x00, 0x50, 0x00, 0x00, 0x00, 0xef, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x20, 0x54, 0x2f, 0xff, +0x48, 0xc0, 0x6b, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, +0x57, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, 0x88, 0x00, 0x00, 0x00, +0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x3f, 0xa8, 0x5e, 0xff, 0x84, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, +0x36, 0xff, 0x8e, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x24, 0x60, 0x36, 0xff, 0x89, 0x00, 0x00, 0x00, +0xff, 0x02, 0x0e, 0x24, 0x14, 0xff, 0x24, 0x60, 0x36, 0xff, 0x36, 0x90, 0x50, 0xff, 0x89, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xb9, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x9d, 0x00, 0x00, 0x00, 0x00, 0x9e, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xdf, 0xb8, 0x00, 0x00, +0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x85, 0x48, 0xc0, 0x6b, 0xff, +0x03, 0x3f, 0xa8, 0x5e, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x24, 0x60, 0x36, 0xff, 0x12, 0x30, 0x1b, +0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x8c, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x86, 0x00, 0x00, +0x00, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, 0x78, 0x43, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x89, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, 0x83, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8c, 0x00, 0x00, +0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x9e, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x60, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, +0x00, 0x00, 0xcf, 0xa0, 0x00, 0x00, 0x00, 0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x8c, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, +0x89, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x88, 0x48, +0xc0, 0x6b, 0xff, 0x00, 0x36, 0x90, 0x50, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, +0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x8c, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, +0x09, 0x18, 0x0d, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x03, 0x12, 0x30, 0x1b, 0xff, 0x24, 0x60, +0x36, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x85, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x20, 0x9e, 0x00, 0x00, 0x00, 0x00, 0xa0, +0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, +0xdf, 0xb4, 0x00, 0x00, 0x00, 0xff, 0x08, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x48, +0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x24, +0x60, 0x36, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x8b, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x2d, +0x78, 0x43, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x88, 0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0xb4, 0x64, +0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x8a, +0x00, 0x00, 0x00, 0xff, 0x00, 0x09, 0x18, 0x0d, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, +0xb4, 0x64, 0xff, 0x1b, 0x48, 0x28, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xcf, 0x00, 0x00, 0x00, 0x20, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xaf, +0x00, 0x00, 0x00, 0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x82, 0x48, 0xc0, +0x6b, 0xff, 0x00, 0x0e, 0x24, 0x14, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, +0xff, 0x44, 0xb4, 0x64, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x44, 0xb4, 0x64, 0xff, 0x88, +0x00, 0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x8b, 0x48, 0xc0, +0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, +0x04, 0x05, 0x0c, 0x07, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x24, 0x60, 0x36, 0xff, 0x32, 0x84, 0x4a, +0xff, 0x3b, 0x9c, 0x57, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0xb2, +0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, +0x60, 0x00, 0x00, 0x00, 0x10, 0xa0, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x02, +0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x86, 0x00, 0x00, 0x00, +0x80, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xa8, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x0c, 0x07, 0xff, +0x20, 0x54, 0x2f, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x09, 0x18, 0x0d, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x89, 0x48, 0xc0, 0x6b, 0xff, 0x02, +0x3f, 0xa8, 0x5e, 0xff, 0x24, 0x60, 0x36, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x89, 0x00, 0x00, 0x00, +0xff, 0x00, 0x17, 0x3c, 0x21, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x32, 0x84, 0x4a, 0xff, +0x05, 0x0c, 0x07, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x04, 0x24, 0x60, 0x36, 0xff, 0x48, 0xc0, +0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x36, 0x90, 0x50, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xac, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0xc3, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xdf, 0xae, 0x00, 0x00, 0x00, 0xff, 0x04, +0x09, 0x18, 0x0d, 0xff, 0x36, 0x90, 0x50, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, +0x29, 0x6c, 0x3c, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x2d, 0x78, +0x43, 0xff, 0x86, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x89, 0x00, 0x00, 0x00, +0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x89, 0x48, +0xc0, 0x6b, 0xff, 0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x94, 0x00, 0x00, 0x00, +0xff, 0x03, 0x09, 0x18, 0x0d, 0xff, 0x12, 0x30, 0x1b, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x05, 0x0c, +0x07, 0xff, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, +0x86, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0xa4, 0x00, +0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xbf, 0x00, 0x00, +0x00, 0xff, 0x01, 0x05, 0x0c, 0x07, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x32, 0x84, 0x4a, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x00, 0x3b, +0x9c, 0x57, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x3f, 0xa8, 0x5e, 0xff, 0x12, 0x30, 0x1b, +0xff, 0x8d, 0x00, 0x00, 0x00, 0xff, 0x02, 0x3f, 0xa8, 0x5e, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x20, +0x54, 0x2f, 0xff, 0xad, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0x20, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0xaf, +0x00, 0x00, 0x00, 0xff, 0x03, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x44, 0xb4, 0x64, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x8c, 0x00, 0x00, 0x00, 0xff, 0x01, 0x12, 0x30, 0x1b, 0xff, 0x3f, +0xa8, 0x5e, 0xff, 0x84, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x3f, 0xa8, 0x5e, 0xff, 0x8c, 0x00, 0x00, +0x00, 0xff, 0x01, 0x17, 0x3c, 0x21, 0xff, 0x2d, 0x78, 0x43, 0xff, 0x88, 0x48, 0xc0, 0x6b, 0xff, +0x01, 0x3b, 0x9c, 0x57, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x20, 0xae, 0x00, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, +0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xbd, 0x00, 0x00, 0x00, 0xff, 0x01, +0x0e, 0x24, 0x14, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x85, 0x48, 0xc0, 0x6b, 0xff, 0x03, 0x44, 0xb4, +0x64, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x1b, 0x48, 0x28, 0xff, 0x05, 0x0c, 0x07, 0xff, 0x8d, 0x00, +0x00, 0x00, 0xff, 0x00, 0x29, 0x6c, 0x3c, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, +0x64, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x8e, 0x00, 0x00, 0x00, 0xff, 0x02, 0x24, 0x60, 0x36, 0xff, +0x2d, 0x78, 0x43, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xa4, 0x00, 0x00, 0x00, 0xff, 0x04, 0x00, 0x00, +0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x83, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc9, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x83, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, +0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa6, 0x00, 0x00, 0x00, 0xff, 0x02, +0x05, 0x0c, 0x07, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x24, 0x60, 0x36, 0xff, 0x8e, 0x00, 0x00, 0x00, +0xff, 0x01, 0x1b, 0x48, 0x28, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x00, +0x29, 0x6c, 0x3c, 0xff, 0x8d, 0x00, 0x00, 0x00, 0xff, 0x03, 0x05, 0x0c, 0x07, 0xff, 0x1b, 0x48, +0x28, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x85, 0x48, 0xc0, 0x6b, 0xff, 0x01, +0x3f, 0xa8, 0x5e, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xaf, 0x00, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, +0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x83, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x3b, 0x9c, 0x57, +0xff, 0x29, 0x6c, 0x3c, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1b, +0x48, 0x28, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x02, 0x44, 0xb4, 0x64, 0xff, 0x24, 0x60, 0x36, +0xff, 0x05, 0x0c, 0x07, 0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x0c, 0x07, 0xff, 0xa5, +0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xdc, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xa7, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x0c, 0x07, +0xff, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x02, 0x05, 0x0c, 0x07, 0xff, 0x24, 0x60, 0x36, 0xff, 0x44, +0xb4, 0x64, 0xff, 0x82, 0x48, 0xc0, 0x6b, 0xff, 0x00, 0x1b, 0x48, 0x28, 0xff, 0x90, 0x00, 0x00, +0x00, 0xff, 0x02, 0x12, 0x30, 0x1b, 0xff, 0x29, 0x6c, 0x3c, 0xff, 0x3b, 0x9c, 0x57, 0xff, 0x83, +0x48, 0xc0, 0x6b, 0xff, 0x01, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xb9, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xb0, 0x00, 0x00, 0x00, 0x00, +0xb0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x9f, 0xb9, 0x00, +0x00, 0x00, 0xff, 0x06, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x44, 0xb4, 0x64, 0xff, +0x36, 0x90, 0x50, 0xff, 0x24, 0x60, 0x36, 0xff, 0x17, 0x3c, 0x21, 0xff, 0x05, 0x0c, 0x07, 0xff, +0x92, 0x00, 0x00, 0x00, 0xff, 0x05, 0x0e, 0x24, 0x14, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x48, 0xc0, +0x6b, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x20, 0x54, 0x2f, 0xff, 0x05, 0x0c, 0x07, 0xff, 0xb7, 0x00, +0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xde, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xb9, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x0c, 0x07, 0xff, +0x1b, 0x48, 0x28, 0xff, 0x3f, 0xa8, 0x5e, 0xff, 0x48, 0xc0, 0x6b, 0xff, 0x48, 0xc0, 0x6b, 0xff, +0x0e, 0x24, 0x14, 0xff, 0x92, 0x00, 0x00, 0x00, 0xff, 0x06, 0x05, 0x0c, 0x07, 0xff, 0x17, 0x3c, +0x21, 0xff, 0x24, 0x60, 0x36, 0xff, 0x36, 0x90, 0x50, 0xff, 0x44, 0xb4, 0x64, 0xff, 0x44, 0xb4, +0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xb7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, +0x00, 0x00, 0x00, 0x30, 0xb1, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xef, 0xb7, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, 0x14, +0xff, 0x09, 0x18, 0x0d, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x03, 0x0e, 0x24, 0x14, 0xff, 0x44, +0xb4, 0x64, 0xff, 0x32, 0x84, 0x4a, 0xff, 0x17, 0x3c, 0x21, 0xff, 0xb9, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x9f, 0xbb, 0x00, 0x00, 0x00, 0xff, 0x03, 0x17, 0x3c, 0x21, 0xff, 0x32, 0x84, 0x4a, +0xff, 0x44, 0xb4, 0x64, 0xff, 0x0e, 0x24, 0x14, 0xff, 0x96, 0x00, 0x00, 0x00, 0xff, 0x01, 0x09, +0x18, 0x0d, 0xff, 0x0e, 0x24, 0x14, 0xff, 0xb6, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xaf, 0x00, 0x00, 0x00, 0x10, 0xb2, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x0e, 0x24, +0x14, 0xff, 0x09, 0x18, 0x0d, 0xff, 0xba, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, +0x00, 0x00, 0x00, 0x10, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xbc, 0x00, +0x00, 0x00, 0xff, 0x01, 0x09, 0x18, 0x0d, 0xff, 0x12, 0x30, 0x1b, 0xff, 0xcd, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x40, 0xb4, 0x00, 0x00, 0x00, 0x00, 0xb5, +0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, +0xef, 0xfc, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, +0x00, 0x00, 0x00, 0x10, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xfe, 0x00, +0x00, 0x00, 0xff, 0x8a, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0x50, 0xb6, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x60, +0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xef, 0xfc, 0x00, 0x00, 0x00, 0xff, 0x87, 0x00, 0x00, +0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x00, 0x00, 0x00, 0xff, 0x86, 0x00, 0x00, 0x00, 0xff, 0x02, +0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x20, 0xb8, 0x00, 0x00, 0x00, +0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xdf, 0x86, +0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0xcf, 0xf3, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xe9, 0x00, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xef, 0xf2, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, +0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbf, 0x86, 0x00, 0x00, 0x00, 0xff, +0x05, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0x8f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0xbc, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, +0x00, 0xef, 0x00, 0x00, 0x00, 0x50, 0xeb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, +0x00, 0x00, 0x00, 0xbf, 0xf0, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, +0x00, 0x20, 0xcb, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x9f, 0xed, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x00, +0x00, 0x00, 0x10, 0xee, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0xdf, 0xed, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x30, 0xcc, +0x00, 0x00, 0x00, 0x00, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xea, 0x00, +0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x10, +0xf2, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, +0x00, 0xef, 0xe9, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x30, +0xcd, 0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, +0x00, 0x00, 0xdf, 0xd9, 0x00, 0x00, 0x00, 0xff, 0x05, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, +0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, +0x50, 0x86, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x85, 0x00, 0x00, +0x00, 0x80, 0x05, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9f, 0xda, 0x00, 0x00, 0x00, 0xff, +0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0xce, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xcf, 0xd5, 0x00, 0x00, 0x00, +0xff, 0x01, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x60, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x97, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xbf, 0xd5, 0x00, 0x00, +0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0xd0, +0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, +0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x9f, 0x85, 0x00, 0x00, 0x00, 0xbf, 0x03, +0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xef, +0xc5, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, +0x00, 0x10, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x50, 0x00, 0x00, 0x00, 0xdf, 0xc6, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x8f, 0x00, +0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x85, 0x00, 0x00, 0x00, 0xbf, 0x03, 0x00, 0x00, 0x00, +0xaf, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x20, 0xd3, 0x00, 0x00, +0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcf, +0xc3, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x20, 0xfd, 0x00, +0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, +0xdf, 0xc2, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x60, 0xe0, +0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaf, 0x00, +0x00, 0x00, 0xff, 0x06, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x20, +0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xdf, +0x88, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, +0x00, 0x20, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x60, 0x00, 0x00, 0x00, 0xaf, 0x89, 0x00, 0x00, 0x00, 0xff, 0x05, 0x00, 0x00, 0x00, 0xbf, 0x00, +0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, +0x00, 0x00, 0xcf, 0xaf, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, +0x20, 0xe1, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, +0x00, 0x00, 0x00, 0x9f, 0x92, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, +0x00, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x94, 0x00, 0x00, 0x00, 0xff, 0x01, +0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x60, 0x86, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, +0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x82, 0x00, 0x00, 0x00, 0x80, 0x02, +0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0xfc, 0x00, 0x00, 0x00, +0x00, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x83, +0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x30, 0x86, 0x00, 0x00, +0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xef, 0x93, +0x00, 0x00, 0x00, 0xff, 0x04, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0x30, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xef, 0x91, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, +0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x50, 0xe3, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xdf, 0x8b, 0x00, +0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x50, +0x00, 0x00, 0x00, 0x10, 0x83, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, +0x00, 0xbf, 0x90, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x30, +0xfd, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, +0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xdf, 0x8f, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x60, 0x84, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, +0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xbf, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x40, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x00, +0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x80, +0x00, 0x00, 0x00, 0xaf, 0x83, 0x00, 0x00, 0x00, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, +0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x89, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xbf, 0x8b, 0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, +0x00, 0xcf, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x10, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xd1, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0xaf, 0x8b, 0x00, 0x00, +0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x89, +0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, +0x80, 0x00, 0x00, 0x00, 0x9f, 0x83, 0x00, 0x00, 0x00, 0xbf, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, +0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x40, 0xe8, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, +0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xbf, 0x84, 0x00, +0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xdf, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x70, +0x00, 0x00, 0x00, 0x20, 0xfb, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xcf, 0x84, +0x00, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, +0x50, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/platform/bcm28xx/vec/rules.mk b/platform/bcm28xx/vec/rules.mk new file mode 100644 index 0000000000..0e4490eb53 --- /dev/null +++ b/platform/bcm28xx/vec/rules.mk @@ -0,0 +1,7 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) +MODULE := $(LOCAL_DIR) +MODULE_SRCS += $(LOCAL_DIR)/vec.c + +MODULES += platform/bcm28xx/pixelvalve platform/bcm28xx/hvs lib/tga + +include make/module.mk diff --git a/platform/bcm28xx/vec/vec.c b/platform/bcm28xx/vec/vec.c new file mode 100644 index 0000000000..1b296ac468 --- /dev/null +++ b/platform/bcm28xx/vec/vec.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pi-logo.h" + +enum vec_mode { + ntsc, + ntscj, + pal, + palm, +}; + +gfx_surface *framebuffer; +gfx_surface *logo; +int width; +int height; +int stride; + +static void vec_init(const struct app_descriptor *app) { + hvs_initialize(); + *REG32(CM_VECDIV) = CM_PASSWORD | 4 << 12; + *REG32(CM_VECCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0; + *REG32(CM_VECCTL) = CM_PASSWORD | CM_VECCTL_ENAB_SET | CM_SRC_PLLC_CORE0; + int rate = measure_clock(29); + printf("vec rate: %d\n", rate); + + *REG32(VEC_WSE_RESET) = 1; + *REG32(VEC_SOFT_RESET) = 1; + *REG32(VEC_WSE_CONTROL) = 0; + + *REG32(VEC_SCHPH) = 0x28; + *REG32(VEC_CLMP0_START) = 0xac; + *REG32(VEC_CLMP0_END) = 0xac; + *REG32(VEC_CONFIG2) = VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS; + *REG32(VEC_CONFIG3) = VEC_CONFIG3_HORIZ_LEN_STD; + *REG32(VEC_DAC_CONFIG) = VEC_DAC_CONFIG_DAC_CTRL(0xc) | VEC_DAC_CONFIG_DRIVER_CTRL(0xc) | VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46); + *REG32(VEC_MASK0) = 0; + enum vec_mode mode = ntsc; + switch (mode) { + case ntsc: + *REG32(VEC_CONFIG0) = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN; + *REG32(VEC_CONFIG1) = VEC_CONFIG1_C_CVBS_CVBS; + break; + case ntscj: + *REG32(VEC_CONFIG0) = VEC_CONFIG0_NTSC_STD; + *REG32(VEC_CONFIG1) = VEC_CONFIG1_C_CVBS_CVBS; + break; + case pal: + *REG32(VEC_CONFIG0) = VEC_CONFIG0_PAL_BDGHI_STD; + *REG32(VEC_CONFIG1) = VEC_CONFIG1_C_CVBS_CVBS; + break; + case palm: + *REG32(VEC_CONFIG0) = VEC_CONFIG0_PAL_BDGHI_STD; + *REG32(VEC_CONFIG1) = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ; + *REG32(VEC_FREQ3_2) = 0x223b; + *REG32(VEC_FREQ1_0) = 0x61d1; + break; + } + *REG32(VEC_DAC_MISC) = VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N; + *REG32(VEC_CFG) = VEC_CFG_VEC_EN; + struct pv_timings t; + bool ntsc = true; + if (ntsc) { + t.vfp = 3; + t.vsync = 4; + t.vbp = 16; + t.vactive = 240; + + t.vfp_even = 4; + t.vsync_even = 3; + t.vbp_even = 16; + t.vactive_even = 240; + + t.interlaced = true; + + t.hfp = 14; + t.hsync = 64; + t.hbp = 60; + t.hactive = 720; + } + setup_pixelvalve(&t, 2); + if (!framebuffer) { + width = t.hactive; + height = t.vactive * 2; + stride = t.hactive; + framebuffer = gfx_create_surface(NULL, width, height, width, GFX_FORMAT_ARGB_8888); + } + printf("framebuffer at 0x%x is %dx%d stride: %d\n", framebuffer->ptr, framebuffer->width, framebuffer->height, framebuffer->stride); + int grid = 20; + for (int x=0; x< width; x++) { + for (int y=0; y < height; y++) { + uint color = 0xff000000; + if (y % grid == 0) color |= 0xffffff; + if (y % grid == 1) color |= 0xffffff; + if (x % grid == 0) color |= 0xffffff; + if (x % grid == 1) color |= 0xffffff; + gfx_putpixel(framebuffer, x, y, color); + } + } + int list_start = display_slot; + hvs_add_plane(framebuffer, 0, 0, false); + hvs_terminate_list(); + *REG32(SCALER_DISPLIST1) = list_start; + + hvs_configure_channel(1, width, height); + + logo = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); + list_start = display_slot; + hvs_add_plane(framebuffer, 0, 0, false); + hvs_add_plane(logo, (width/2) - (logo->width/2), 0, false); + hvs_terminate_list(); + *REG32(SCALER_DISPLIST1) = list_start; +} + +static void vec_entry(const struct app_descriptor *app, void *args) { +} + +APP_START(vec) + .init = vec_init, + .entry = vec_entry, +APP_END diff --git a/project/rpi3-start.mk b/project/rpi3-start.mk index 65203528b7..f205b77575 100644 --- a/project/rpi3-start.mk +++ b/project/rpi3-start.mk @@ -9,3 +9,4 @@ MODULES += \ lib/cksum \ lib/debugcommands \ platform/bcm28xx/otp \ + platform/bcm28xx/vec \ From 163a6eac7ceb880dfa59d46eb786cf525d24d9c5 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 19 Mar 2021 22:52:08 -0300 Subject: [PATCH 089/100] missed this file --- platform/bcm28xx/pll/pll_control.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/bcm28xx/pll/pll_control.c b/platform/bcm28xx/pll/pll_control.c index f9ab8a546f..ecc31c3a5d 100644 --- a/platform/bcm28xx/pll/pll_control.c +++ b/platform/bcm28xx/pll/pll_control.c @@ -489,11 +489,14 @@ void switch_vpu_to_src(int src) { void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { int pdiv = 1; uint64_t xtal_in = xtal_freq; + printf("xtal_in = %d\n", xtal_in); uint64_t goal_freq = target_freq / 2; + printf("goal_freq = %d\n", goal_freq); uint64_t divisor = (goal_freq<<20) / xtal_in; int div = divisor >> 20; int frac = divisor & 0xfffff; printf("divisor 0x%llx -> %d+(%d/2^20)\n", divisor, div, frac); + printf("ctrl: 0x%x\nfrac: 0x%x\n", *REG32(A2W_PLLC_CTRL), *REG32(A2W_PLLC_FRAC)); *REG32(CM_PLLC) = CM_PASSWORD | CM_PLLC_ANARST_SET; @@ -501,7 +504,7 @@ void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | frac; *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | div | PDIV(pdiv); - printf("frac set to 0x%x\n", *REG32(A2W_PLLC_FRAC)); + printf("frac set to 0x%x, wanted 0x%x\n", *REG32(A2W_PLLC_FRAC), frac); *REG32(A2W_PLLC_ANA3) = A2W_PASSWORD | KA(2); *REG32(A2W_PLLC_ANA2) = A2W_PASSWORD | 0x0; @@ -521,6 +524,7 @@ void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { *REG32(A2W_PLLC_DIG0) = A2W_PASSWORD | div | 0x555000; *REG32(A2W_PLLC_CTRL) = A2W_PASSWORD | div | PDIV(pdiv) | A2W_PLLC_CTRL_PRSTN_SET; + *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | frac; *REG32(A2W_PLLC_DIG3) = A2W_PASSWORD | 0x42; *REG32(A2W_PLLC_DIG2) = A2W_PASSWORD | 0x500401; @@ -544,4 +548,7 @@ void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { CM_PLLC_HOLDCORE1_SET; while (!BIT_SET(*REG32(CM_LOCK), CM_LOCK_FLOCKC_BIT)) {} + printf("ctrl: 0x%x\nfrac: 0x%x\n", *REG32(A2W_PLLC_CTRL), *REG32(A2W_PLLC_FRAC)); + *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | frac; + printf("ctrl: 0x%x\nfrac: 0x%x\n", *REG32(A2W_PLLC_CTRL), *REG32(A2W_PLLC_FRAC)); } From 51fe20eefaf132903c95ec2f874e6aba4241e35e Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 19 Mar 2021 22:53:14 -0300 Subject: [PATCH 090/100] and this file! --- platform/bcm28xx/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 7aa6939a14..aafd285e69 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -134,7 +134,7 @@ static void switch_vpu_to_pllc() { int core0_div = 4; int per_div = 4; - setup_pllc( 2000LL * 1000 * 1000, core0_div, per_div); + setup_pllc( 1728LL * 1000 * 1000, core0_div, per_div); int vpu_divisor = 1; From d1ce174b77033f3151c1d33e7c447903bf482bad Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sat, 20 Mar 2021 23:58:45 -0300 Subject: [PATCH 091/100] fix power domain issues when booting from SD --- .../bcm28xx/include/platform/bcm28xx/pm.h | 30 ---------------- platform/bcm28xx/platform.c | 2 +- platform/bcm28xx/pll/pll_read.c | 10 +++--- .../power/include/platform/bcm28xx/power.h | 34 ++++++++++++++++++- platform/bcm28xx/power/power.c | 33 +++++++++++++++++- platform/bcm28xx/vec/rules.mk | 2 +- platform/bcm28xx/vec/vec.c | 8 +++-- 7 files changed, 77 insertions(+), 42 deletions(-) delete mode 100644 platform/bcm28xx/include/platform/bcm28xx/pm.h diff --git a/platform/bcm28xx/include/platform/bcm28xx/pm.h b/platform/bcm28xx/include/platform/bcm28xx/pm.h deleted file mode 100644 index c642143f65..0000000000 --- a/platform/bcm28xx/include/platform/bcm28xx/pm.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include - -#define PM_BASE (BCM_PERIPH_BASE_VIRT + 0x100000) -#define PM_PASSWORD 0x5a000000 - -#define PM_RSTC (PM_BASE + 0x1c) -#define PM_RSTC_WRCFG_CLR 0xffffffcf // mask to keep everything but the watchdog config -// https://github.com/raspberrypi/linux/issues/932 -// docs for RSTS -// definitions from broadcom/bcm2708_chip/cpr_powman.h -// comments from github issue -#define PM_RSTS (PM_BASE + 0x20) -#define PM_RSTS_HADPOR_SET 0x00001000 // bit 12 had power-on reset -#define PM_RSTS_HADSRH_SET 0x00000400 // bit 10 had software hard reset -#define PM_RSTS_HADSRF_SET 0x00000200 // bit 9 had software full reset -#define PM_RSTS_HADSRQ_SET 0x00000100 // bit 8 had software quick reset -#define PM_RSTS_HADWRH_SET 0x00000040 // bit 6 had watchdog hard reset -#define PM_RSTS_HADWRF_SET 0x00000020 // bit 5 had watchdog full reset -#define PM_RSTS_HADWRQ_SET 0x00000010 // bit 4 had watchdog quick reset -#define PM_RSTS_HADDRH_SET 0x00000004 // bit 2 had debugger hard reset -#define PM_RSTS_HADDRF_SET 0x00000002 // bit 1 had debugger full reset -#define PM_RSTS_HADDRQ_SET 0x00000001 // bit 0 had debugger quick reset -#define PM_WDOG (PM_BASE + 0x24) -#define PM_WDOG_MASK 0x00000fff -#define PM_USB (PM_BASE + 0x5c) -#define PM_SMPS (PM_BASE + 0x6c) -#define PM_SPAREW (PM_BASE + 0x74) -#define PM_IMAGE (PM_BASE + 0x108) diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index aafd285e69..ccc23fbb88 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #if BCM2836 || BCM2835 diff --git a/platform/bcm28xx/pll/pll_read.c b/platform/bcm28xx/pll/pll_read.c index acbc00bd4f..448f6812c3 100644 --- a/platform/bcm28xx/pll/pll_read.c +++ b/platform/bcm28xx/pll/pll_read.c @@ -1,12 +1,12 @@ -#include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include #include +#include static int cmd_pll_dump(int argc, const cmd_args *argv); static int cmd_measure_clock(int argc, const cmd_args *argv); diff --git a/platform/bcm28xx/power/include/platform/bcm28xx/power.h b/platform/bcm28xx/power/include/platform/bcm28xx/power.h index 23f0e3ed1f..a5e38f508d 100644 --- a/platform/bcm28xx/power/include/platform/bcm28xx/power.h +++ b/platform/bcm28xx/power/include/platform/bcm28xx/power.h @@ -1,10 +1,42 @@ #pragma once -#include #include +#include #define BIT(n) (1< #include #include +#include + +static int cmd_pm_dump(int argc, const cmd_args *argv); +static int cmd_pm_usb_on(int argc, const cmd_args *argv); + +STATIC_COMMAND_START +STATIC_COMMAND("pm_dump_all", "dump power domain states", &cmd_pm_dump) +STATIC_COMMAND("pm_usb_on", "enable usb power domain", &cmd_pm_usb_on) +STATIC_COMMAND_END(pm); void power_up_image(void) { puts("image domain on..."); //dumpreg(PM_IMAGE); - *REG32(PM_IMAGE) |= PM_PASSWORD | 0x10000; // CFG = 1 + *REG32(PM_IMAGE) |= PM_PASSWORD | 0x10000 | BIT(6); // CFG = 1 #if 0 printf("PM_IMAGE: 0x%x\n", *REG32(PM_IMAGE)); *REG32(PM_IMAGE) |= PM_PASSWORD | 1; // POWUP = 1 @@ -82,3 +91,25 @@ void power_domain_on(volatile uint32_t *reg) { /* Disable functional isolation */ *REG32(reg) |= PM_PASSWORD | PM_ISFUNC; } + +static void dump_power_domain(const char *name, uint32_t pmreg) { + volatile uint32_t *reg = REG32(pmreg); + uint32_t v = *reg; + printf("%8s: 0x%x == 0x%08x ", name, pmreg, v); + printf("%2s %2s %2s", v & PM_POWUP ? "UP":"", v & PM_POWOK ? "OK":"", v & PM_ENABLE ? "EN":""); + if ((pmreg == PM_IMAGE) && (v & BIT(7))) printf(" H264RSTN"); + puts(""); +} + +static int cmd_pm_dump(int argc, const cmd_args *argv) { + dump_power_domain("PM_USB", PM_USB); + dump_power_domain("PM_SMPS", PM_SMPS); + dump_power_domain("PM_IMAGE", PM_IMAGE); + dump_power_domain("PM_GRAFX", PM_GRAFX); + dump_power_domain("PM_PROC", PM_PROC); + return 0; +} +static int cmd_pm_usb_on(int argc, const cmd_args *argv) { + power_up_usb(); + return 0; +} diff --git a/platform/bcm28xx/vec/rules.mk b/platform/bcm28xx/vec/rules.mk index 0e4490eb53..6995e03d81 100644 --- a/platform/bcm28xx/vec/rules.mk +++ b/platform/bcm28xx/vec/rules.mk @@ -2,6 +2,6 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) MODULE_SRCS += $(LOCAL_DIR)/vec.c -MODULES += platform/bcm28xx/pixelvalve platform/bcm28xx/hvs lib/tga +MODULES += platform/bcm28xx/pixelvalve platform/bcm28xx/hvs lib/tga platform/bcm28xx/power include make/module.mk diff --git a/platform/bcm28xx/vec/vec.c b/platform/bcm28xx/vec/vec.c index 1b296ac468..baf32bf150 100644 --- a/platform/bcm28xx/vec/vec.c +++ b/platform/bcm28xx/vec/vec.c @@ -2,12 +2,13 @@ #include #include #include +#include #include #include -#include -#include +#include #include -#include +#include +#include #include "pi-logo.h" @@ -25,6 +26,7 @@ int height; int stride; static void vec_init(const struct app_descriptor *app) { + power_up_usb(); hvs_initialize(); *REG32(CM_VECDIV) = CM_PASSWORD | 4 << 12; *REG32(CM_VECCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0; From 86ecba0ff92d6e9f54ccb93383e16780c435d20c Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 21 Mar 2021 00:06:48 -0300 Subject: [PATCH 092/100] saving previously unsaved changes to dance, and fixing it --- platform/bcm28xx/hvs-dance/dance.c | 126 +++++++++++++++++++++++++---- platform/bcm28xx/rules.mk | 1 + 2 files changed, 112 insertions(+), 15 deletions(-) diff --git a/platform/bcm28xx/hvs-dance/dance.c b/platform/bcm28xx/hvs-dance/dance.c index 4546a6a3ca..39ff0930d5 100644 --- a/platform/bcm28xx/hvs-dance/dance.c +++ b/platform/bcm28xx/hvs-dance/dance.c @@ -1,39 +1,60 @@ #include +#include +#include +#include +#include #include #include +#include #include #include #include #include +#include #include #include static int cmd_hvs_dance(int argc, const cmd_args *argv); +static int cmd_hvs_limit(int argc, const cmd_args *argv); +static int cmd_hvs_delay(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dance", "make the HVS dance in another direction", &cmd_hvs_dance) +STATIC_COMMAND("l", "limit sprites", &cmd_hvs_limit) +STATIC_COMMAND("d", "delay updates", &cmd_hvs_delay) STATIC_COMMAND_END(hvs_dance); gfx_surface *fb; struct item { - int x, y; + unsigned int x, y; signed int xd, yd; }; -#define ITEMS 13 +#define ITEMS 580 struct item items[ITEMS]; +uint32_t sprite_limit = 1; +int delay = 0; -void do_frame_update(void) { +void do_frame_update(int frame) { + if (delay != 0) { + if ((frame % delay) != 0) return; + } + if ((display_slot + (sprite_limit * 7) + 1) > 4096) { + //printf("early dlist loop %d\n", display_slot); + display_slot = 0; + } int start = display_slot; - for (int i=0; ix > (0x500 - fb->width)) it->xd *= -1; if (it->y > (0x400 - fb->height)) it->yd *= -1; + it->x += it->xd; it->y += it->yd; +#if 0 if (it->x < 0) { it->x = it->x * -1; it->xd *= -1; @@ -42,28 +63,89 @@ void do_frame_update(void) { it->y = it->y * -1; it->yd *= -1; } - hvs_add_plane(fb, it->x, it->y); +#endif + hvs_add_plane(fb, it->x, it->y, false); } hvs_terminate_list(); + if (display_slot > 4096) { + printf("dlist overflow!!!: %d\n", display_slot); + display_slot = 0; + do_frame_update(frame); + return; + } + *REG32(SCALER_DISPLIST1) = start; if (display_slot > 4000) { display_slot = 0; - puts("dlist loop"); + //puts("dlist loop"); } } +uint32_t hsync, hbp, hact, hfp, vsync, vbp, vfps, last_vfps; + static enum handler_return pv_irq(void *pvnr) { - struct pixel_valve *rawpv = getPvAddr(pvnr); + uint32_t t = *REG32(ST_CLO); + struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); + struct pixel_valve *rawpv = getPvAddr((int)pvnr); uint32_t stat = rawpv->int_status; + uint32_t ack = 0; + uint32_t stat1 = hvs_channels[1].dispstat; + if (stat & PV_INTEN_HSYNC_START) { + ack |= PV_INTEN_HSYNC_START; + hsync = t; + if ((SCALER_STAT_LINE(stat1) % 5) == 0) { + hvs_channels[1].dispbkgnd = (1<<24) | 0x00ff00; + } else { + hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; + } + } + if (stat & PV_INTEN_HBP_START) { + ack |= PV_INTEN_HBP_START; + hbp = t; + } + if (stat & PV_INTEN_HACT_START) { + ack |= PV_INTEN_HACT_START; + hact = t; + }; + if (stat & PV_INTEN_HFP_START) { + ack |= PV_INTEN_HFP_START; + hfp = t; + } + if (stat & PV_INTEN_VSYNC_START) { + ack |= PV_INTEN_VSYNC_START; + vsync = t; + } + if (stat & PV_INTEN_VBP_START) { + ack |= PV_INTEN_VBP_START; + vbp = t; + } + if (stat & PV_INTEN_VACT_START) { + ack |= PV_INTEN_VACT_START; + } if (stat & PV_INTEN_VFP_START) { - rawpv->int_status = PV_INTEN_VFP_START; - struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); - uint32_t stat1 = hvs_channels[1].dispstat; - do_frame_update(); - printf("line: %d frame: %d start: %d\n", stat1 & 0xfff, (stat1 >> 12) & 0x3f, *REG32(SCALER_DISPLIST1)); + ack |= PV_INTEN_VFP_START; + last_vfps = vfps; + vfps = t; + hvs_channels[1].dispbkgnd = (1<<24) | 0xff0000; + do_frame_update((stat1 >> 12) & 0x3f); + //printf("line: %d frame: %2d start: %4d ", stat1 & 0xfff, (stat1 >> 12) & 0x3f, *REG32(SCALER_DISPLIST1)); + //uint32_t idle = *REG32(SD_IDL); + //uint32_t total = *REG32(SD_CYC); + //*REG32(SD_IDL) = 0; + //uint64_t idle_percent = ((uint64_t)idle * 100) / ((uint64_t)total); + //printf("sdram usage: %d %d, %lld\n", idle, total, idle_percent); + //printf("HSYNC:%5d HBP:%d HACT:%d HFP:%d VSYNC:%5d VBP:%5d VFPS:%d FRAME:%d\n", t - vsync, t-hbp, t-hact, t-hfp, t-vsync, t-vbp, t-vfps, t-last_vfps); + hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; + } + if (stat & PV_INTEN_VFP_END) { + ack |= PV_INTEN_VFP_END; + } + if (stat & PV_INTEN_IDLE) { + ack |= PV_INTEN_IDLE; } + rawpv->int_status = ack; return INT_NO_RESCHEDULE; } @@ -80,7 +162,18 @@ static int cmd_hvs_dance(int argc, const cmd_args *argv) { return 0; } -static void dance_init(struct app_descriptor *app) { +static int cmd_hvs_limit(int argc, const cmd_args *argv) { + if (argc == 2) sprite_limit = argv[1].u; + if (sprite_limit > ITEMS) sprite_limit = ITEMS; + return 0; +} + +static int cmd_hvs_delay(int argc, const cmd_args *argv) { + if (argc == 2) delay = argv[1].u; + return 0; +} + +static void dance_init(const struct app_descriptor *app) { fb = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); if (!fb) { fb = gfx_create_surface(NULL, 10, 10, 10, GFX_FORMAT_ARGB_8888); @@ -109,6 +202,8 @@ static void dance_entry(const struct app_descriptor *app, void *args) { if (it->x > (0x500 - fb->width)) it->x = 0x500 - fb->width; if (it->y > (0x400 - fb->height)) it->y = 0x400 - fb->height; } + struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); + hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; { puts("setting up pv interrupt"); @@ -116,8 +211,9 @@ static void dance_entry(const struct app_descriptor *app, void *args) { struct pixel_valve *rawpv = getPvAddr(pvnr); rawpv->int_enable = 0; rawpv->int_status = 0xff; - setup_pv_interrupt(pvnr, pv_irq, pvnr); - rawpv->int_enable = PV_INTEN_VFP_START; + setup_pv_interrupt(pvnr, pv_irq, (void*)pvnr); + rawpv->int_enable = PV_INTEN_VFP_START | 0x3f; + //hvs_setup_irq(); puts("done"); } } diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 6768ac0e45..c75208fd97 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -19,6 +19,7 @@ ifeq ($(ARCH),vpu) endif GLOBAL_DEFINES += SMP_MAX_CPUS=1 else # it must be arm32 or arm64 + MODULE_DEPS += platform/bcm28xx/power ifeq ($(HAVE_ARM_TIMER),1) MODULE_DEPS += dev/timer/arm_generic GLOBAL_DEFINES += HAVE_ARM_TIMER=1 From 1787a2ea4054375be1a7efbb2f7c5355f55a578a Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 21 Mar 2021 03:27:43 -0300 Subject: [PATCH 093/100] fix vc4-stage1 --- app/vc4-stage1/stage1.c | 2 +- platform/bcm28xx/rpi-ddr2/sdram.c | 2 +- platform/bcm28xx/rules.mk | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/vc4-stage1/stage1.c b/app/vc4-stage1/stage1.c index e18f882f81..fa0774652e 100644 --- a/app/vc4-stage1/stage1.c +++ b/app/vc4-stage1/stage1.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/platform/bcm28xx/rpi-ddr2/sdram.c b/platform/bcm28xx/rpi-ddr2/sdram.c index d758f908cd..4b994b8be7 100644 --- a/platform/bcm28xx/rpi-ddr2/sdram.c +++ b/platform/bcm28xx/rpi-ddr2/sdram.c @@ -24,7 +24,7 @@ VideoCoreIV SDRAM initialization code. #include #include #include -#include +#include #include #include #include diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index c75208fd97..3beb13ba0d 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -5,6 +5,7 @@ MODULE := $(LOCAL_DIR) WITH_SMP := 1 #SMP_MAX_CPUS ?= 1 #LK_HEAP_IMPLEMENTATION ?= dlmalloc +MODULE_DEPS += platform/bcm28xx/power ifeq ($(ARCH),vpu) MODULE_DEPS += platform/bcm28xx/pll @@ -19,7 +20,6 @@ ifeq ($(ARCH),vpu) endif GLOBAL_DEFINES += SMP_MAX_CPUS=1 else # it must be arm32 or arm64 - MODULE_DEPS += platform/bcm28xx/power ifeq ($(HAVE_ARM_TIMER),1) MODULE_DEPS += dev/timer/arm_generic GLOBAL_DEFINES += HAVE_ARM_TIMER=1 From 8043bb7877f98a1e1c944aa7e2c0749195ad4d87 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 21 Mar 2021 03:32:24 -0300 Subject: [PATCH 094/100] and vc4-stage2 --- platform/bcm28xx/dpi/dpi.c | 2 +- platform/bcm28xx/dwc2/dwc2.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/bcm28xx/dpi/dpi.c b/platform/bcm28xx/dpi/dpi.c index 2206255e1d..13d37aa52e 100644 --- a/platform/bcm28xx/dpi/dpi.c +++ b/platform/bcm28xx/dpi/dpi.c @@ -70,7 +70,7 @@ int cmd_dpi_start(int argc, const cmd_args *argv) { hvs_configure_channel(0, width, height); int list_start = display_slot; - hvs_add_plane(framebuffer, 0, 0); + hvs_add_plane(framebuffer, 0, 0, false); hvs_terminate_list(); *REG32(SCALER_DISPLIST0) = list_start; diff --git a/platform/bcm28xx/dwc2/dwc2.c b/platform/bcm28xx/dwc2/dwc2.c index 533033c107..840e2dc8ce 100644 --- a/platform/bcm28xx/dwc2/dwc2.c +++ b/platform/bcm28xx/dwc2/dwc2.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include From 715ef3eddd3477df5d3007c2b7d0bf5696052c99 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 22 Mar 2021 20:31:47 -0300 Subject: [PATCH 095/100] vec dance works --- arch/vpu/intc.c | 1 + arch/vpu/thread.c | 8 +- dev/timer/vc4/rules.mk | 1 + dev/timer/vc4/timer.c | 22 +- platform/bcm28xx/hvs-dance/dance.c | 125 +++++++---- platform/bcm28xx/hvs-dance/include/dance.h | 5 + platform/bcm28xx/hvs/hvs.c | 195 +++++++++++++++--- .../hvs/include/platform/bcm28xx/hvs.h | 13 +- platform/bcm28xx/include/platform/bcm28xx.h | 1 + platform/bcm28xx/pixelvalve/pv.c | 6 +- .../power/include/platform/bcm28xx/power.h | 18 +- platform/bcm28xx/power/power.c | 4 +- .../vec/include/platform/bcm28xx/vec.h | 16 +- platform/bcm28xx/vec/vec.c | 10 +- project/rpi3-start.mk | 1 + 15 files changed, 321 insertions(+), 105 deletions(-) create mode 100644 platform/bcm28xx/hvs-dance/include/dance.h diff --git a/arch/vpu/intc.c b/arch/vpu/intc.c index 99caed757a..f74827cb77 100644 --- a/arch/vpu/intc.c +++ b/arch/vpu/intc.c @@ -220,6 +220,7 @@ void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp) { switch (source) { case 64: // timer0 case 73: // dwc2 + case 106: // pv2 case 121: // uart assert(irq_handlers[source - 64].h); ret = irq_handlers[source - 64].h(irq_handlers[source - 64].arg); diff --git a/arch/vpu/thread.c b/arch/vpu/thread.c index b90ff8eff7..459937af22 100644 --- a/arch/vpu/thread.c +++ b/arch/vpu/thread.c @@ -25,10 +25,12 @@ static inline void push(thread_t *t, uint32_t val) { static void initial_thread_func(void) __NO_RETURN; static void initial_thread_func(void) { thread_t *ct = get_current_thread(); - uint32_t own_sp; + //uint32_t own_sp; - __asm__ volatile ("mov %0, sp": "=r"(own_sp)); + //__asm__ volatile ("mov %0, sp": "=r"(own_sp)); //dprintf(INFO, "thread %p(%s) starting with sp near 0x%x\n", ct, ct->name, own_sp); + spin_unlock(&thread_lock); + arch_enable_ints(); int ret = ct->entry(ct->arg); @@ -39,6 +41,8 @@ void arch_thread_initialize(thread_t *t) { //printf("thread %p(%s) has a stack of %p+0x%x\n", t, t->name, t->stack, t->stack_size); t->arch.sp = (uint32_t)((t->stack + t->stack_size) - 4); __asm__ volatile ("mov %0, sr": "=r"(t->arch.sr)); + t->arch.sr &= ~0x40000000; // disable irq in the new thread + //printf("initial sr: 0x%x\n", t->arch.sr); push(t, (uint32_t)(&initial_thread_func)); // lr for (int i=6; i<=23; i++) { push(t, 0); // r${i} diff --git a/dev/timer/vc4/rules.mk b/dev/timer/vc4/rules.mk index bedd03f803..eed55d5093 100644 --- a/dev/timer/vc4/rules.mk +++ b/dev/timer/vc4/rules.mk @@ -5,5 +5,6 @@ MODULE := $(LOCAL_DIR) MODULE_SRCS += $(LOCAL_DIR)/timer.c GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1 +MODULE_CFLAGS := -O2 include make/module.mk diff --git a/dev/timer/vc4/timer.c b/dev/timer/vc4/timer.c index 87215949e3..d2321075ed 100644 --- a/dev/timer/vc4/timer.c +++ b/dev/timer/vc4/timer.c @@ -1,15 +1,19 @@ #include #include +#include #include #include #include #include static enum handler_return timer0_irq(void *arg); +static void vc4_timer_init(uint level); static platform_timer_callback timer_cb = 0;; static void *timer_arg = 0;; +LK_INIT_HOOK(vc4_timer, &vc4_timer_init, LK_INIT_LEVEL_PLATFORM); + lk_bigtime_t current_time_hires(void) { //TODO, deal with rollover return ( ((lk_bigtime_t)*REG32(ST_CHI)) << 32) | *REG32(ST_CLO); @@ -19,22 +23,30 @@ lk_time_t current_time(void) { return current_time_hires(); } +static void vc4_timer_init(uint level) { +#if VC4_TIMER_CHANNEL == 0 + // TODO, only register the interrupt handler once + register_int_handler(0, timer0_irq, NULL); + unmask_interrupt(0); +#elif VC4_TIMER_CHANNEL == 1 + register_int_handler(1, timer0_irq, NULL); + unmask_interrupt(1); +#else +#error unsupported timer channel +#endif +} + status_t platform_set_oneshot_timer (platform_timer_callback callback, void *arg, lk_time_t interval) { timer_cb = callback; timer_arg = arg; //printf("platform_set_oneshot_timer(..., ..., %d)\n", interval); #if VC4_TIMER_CHANNEL == 0 *REG32(ST_C0) = *REG32(ST_CLO) + (interval * 1000); - register_int_handler(0, timer0_irq, NULL); - unmask_interrupt(0); #elif VC4_TIMER_CHANNEL == 1 *REG32(ST_C1) = *REG32(ST_CLO) + (interval * 1000); - register_int_handler(1, timer0_irq, NULL); - unmask_interrupt(1); #else #error unsupported timer channel #endif - return NO_ERROR; } diff --git a/platform/bcm28xx/hvs-dance/dance.c b/platform/bcm28xx/hvs-dance/dance.c index 39ff0930d5..dc4538dc39 100644 --- a/platform/bcm28xx/hvs-dance/dance.c +++ b/platform/bcm28xx/hvs-dance/dance.c @@ -7,7 +7,7 @@ #include #include #include -#include +//#include #include #include #include @@ -17,11 +17,13 @@ static int cmd_hvs_dance(int argc, const cmd_args *argv); static int cmd_hvs_limit(int argc, const cmd_args *argv); static int cmd_hvs_delay(int argc, const cmd_args *argv); +static int cmd_dance_update(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dance", "make the HVS dance in another direction", &cmd_hvs_dance) STATIC_COMMAND("l", "limit sprites", &cmd_hvs_limit) STATIC_COMMAND("d", "delay updates", &cmd_hvs_delay) +STATIC_COMMAND("u", "update", &cmd_dance_update) STATIC_COMMAND_END(hvs_dance); gfx_surface *fb; @@ -33,23 +35,36 @@ struct item { #define ITEMS 580 struct item items[ITEMS]; -uint32_t sprite_limit = 1; +uint32_t sprite_limit = 15; int delay = 0; +uint32_t screen_width, screen_height; + +#define SCALED + void do_frame_update(int frame) { if (delay != 0) { if ((frame % delay) != 0) return; } if ((display_slot + (sprite_limit * 7) + 1) > 4096) { - //printf("early dlist loop %d\n", display_slot); + printf("early dlist loop %d\n", display_slot); display_slot = 0; } + int w,h; +#ifdef SCALED + w = 100; + h = 100; +#else + w = fb->width; + h = fb->height; +#endif + int start = display_slot; for (unsigned int i=0; i < sprite_limit; i++) { struct item *it = &items[i]; - if (it->x > (0x500 - fb->width)) it->xd *= -1; - if (it->y > (0x400 - fb->height)) it->yd *= -1; + if (it->x > (screen_width - w)) it->xd *= -1; + if (it->y > (screen_height - h)) it->yd *= -1; it->x += it->xd; it->y += it->yd; @@ -64,12 +79,16 @@ void do_frame_update(int frame) { it->yd *= -1; } #endif +#ifdef SCALED + hvs_add_plane_scaled(fb, it->x, it->y, w, h, false); +#else hvs_add_plane(fb, it->x, it->y, false); +#endif } hvs_terminate_list(); if (display_slot > 4096) { - printf("dlist overflow!!!: %d\n", display_slot); + //printf("dlist overflow!!!: %d\n", display_slot); display_slot = 0; do_frame_update(frame); return; @@ -83,6 +102,12 @@ void do_frame_update(int frame) { } } +static int cmd_dance_update(int argc, const cmd_args *argv) { + printf("fb 0x%x is %dx%d\n", fb, fb->width, fb->height); + do_frame_update(0); + return 0; +} + uint32_t hsync, hbp, hact, hfp, vsync, vbp, vfps, last_vfps; static enum handler_return pv_irq(void *pvnr) { @@ -96,9 +121,9 @@ static enum handler_return pv_irq(void *pvnr) { ack |= PV_INTEN_HSYNC_START; hsync = t; if ((SCALER_STAT_LINE(stat1) % 5) == 0) { - hvs_channels[1].dispbkgnd = (1<<24) | 0x00ff00; + //hvs_channels[1].dispbkgnd = (1<<24) | 0x00ff00; } else { - hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; + //hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; } } if (stat & PV_INTEN_HBP_START) { @@ -128,7 +153,7 @@ static enum handler_return pv_irq(void *pvnr) { ack |= PV_INTEN_VFP_START; last_vfps = vfps; vfps = t; - hvs_channels[1].dispbkgnd = (1<<24) | 0xff0000; + //hvs_channels[1].dispbkgnd = (1<<24) | 0xff0000; do_frame_update((stat1 >> 12) & 0x3f); //printf("line: %d frame: %2d start: %4d ", stat1 & 0xfff, (stat1 >> 12) & 0x3f, *REG32(SCALER_DISPLIST1)); //uint32_t idle = *REG32(SD_IDL); @@ -137,7 +162,7 @@ static enum handler_return pv_irq(void *pvnr) { //uint64_t idle_percent = ((uint64_t)idle * 100) / ((uint64_t)total); //printf("sdram usage: %d %d, %lld\n", idle, total, idle_percent); //printf("HSYNC:%5d HBP:%d HACT:%d HFP:%d VSYNC:%5d VBP:%5d VFPS:%d FRAME:%d\n", t - vsync, t-hbp, t-hact, t-hfp, t-vsync, t-vbp, t-vfps, t-last_vfps); - hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; + //hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; } if (stat & PV_INTEN_VFP_END) { ack |= PV_INTEN_VFP_END; @@ -149,16 +174,28 @@ static enum handler_return pv_irq(void *pvnr) { return INT_NO_RESCHEDULE; } -static int cmd_hvs_dance(int argc, const cmd_args *argv) { +static void dance_scramble(void) { + int w,h; +#ifdef SCALED + w = 100; + h = 100; +#else + w = fb->width; + h = fb->height; +#endif for (int i=0; ix = (unsigned int)rand() % 0x500; - it->y = (unsigned int)rand() % 0x400; - it->xd = rand() % 25; - it->yd = rand() % 25; - if (it->x > (0x500 - fb->width)) it->x = 0x500 - fb->width; - if (it->y > (0x400 - fb->height)) it->y = 0x400 - fb->height; + it->x = (unsigned int)rand() % screen_width; + it->y = (unsigned int)rand() % screen_height; + it->xd = rand() % 10; + it->yd = rand() % 10; + if (it->x > (screen_width - w)) it->x = screen_width - fb->width; + if (it->y > (screen_height - h)) it->y = screen_height - fb->height; } +} + +static int cmd_hvs_dance(int argc, const cmd_args *argv) { + dance_scramble(); return 0; } @@ -173,8 +210,33 @@ static int cmd_hvs_delay(int argc, const cmd_args *argv) { return 0; } +void dance_start(gfx_surface* fbin, int hvs_channel) { + fb = fbin; + gfx_flush(fb); + + struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); + hvs_channels[hvs_channel].dispbkgnd = (1<<24) | 0xffffff; + screen_width = (hvs_channels[hvs_channel].dispctrl >> 12) & 0xfff; + screen_height = (hvs_channels[hvs_channel].dispctrl & 0xfff) / 2; + printf("detected a %dx%d screen\n", screen_width, screen_height); + + srand(*REG32(ST_CLO)); + dance_scramble(); + if (true) { + puts("setting up pv interrupt"); + int pvnr = 2; + struct pixel_valve *rawpv = getPvAddr(pvnr); + rawpv->int_enable = 0; + rawpv->int_status = 0xff; + setup_pv_interrupt(pvnr, pv_irq, (void*)pvnr); + rawpv->int_enable = PV_INTEN_VFP_START | 0x3f; + //hvs_setup_irq(); + puts("done"); + } +} + static void dance_init(const struct app_descriptor *app) { - fb = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); +#if 0 if (!fb) { fb = gfx_create_surface(NULL, 10, 10, 10, GFX_FORMAT_ARGB_8888); for (unsigned int i=0; iwidth; i++) { @@ -188,34 +250,13 @@ static void dance_init(const struct app_descriptor *app) { } } fb->flush = 0; +#endif + screen_width = 0x500; + screen_height = 0x400; } static void dance_entry(const struct app_descriptor *app, void *args) { - gfx_flush(fb); - srand(*REG32(ST_CLO)); - for (int i=0; ix = (unsigned int)rand() % 0x500; - it->y = (unsigned int)rand() % 0x400; - it->xd = rand() % 25; - it->yd = rand() % 25; - if (it->x > (0x500 - fb->width)) it->x = 0x500 - fb->width; - if (it->y > (0x400 - fb->height)) it->y = 0x400 - fb->height; - } - struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); - hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; - { - puts("setting up pv interrupt"); - int pvnr = 2; - struct pixel_valve *rawpv = getPvAddr(pvnr); - rawpv->int_enable = 0; - rawpv->int_status = 0xff; - setup_pv_interrupt(pvnr, pv_irq, (void*)pvnr); - rawpv->int_enable = PV_INTEN_VFP_START | 0x3f; - //hvs_setup_irq(); - puts("done"); - } } APP_START(hvs_dance) diff --git a/platform/bcm28xx/hvs-dance/include/dance.h b/platform/bcm28xx/hvs-dance/include/dance.h new file mode 100644 index 0000000000..ee74294439 --- /dev/null +++ b/platform/bcm28xx/hvs-dance/include/dance.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void dance_start(gfx_surface* fbin, int hvs_channel); diff --git a/platform/bcm28xx/hvs/hvs.c b/platform/bcm28xx/hvs/hvs.c index 6d93123fca..a5d0b51506 100644 --- a/platform/bcm28xx/hvs/hvs.c +++ b/platform/bcm28xx/hvs/hvs.c @@ -1,10 +1,11 @@ #include +#include #include #include #include +#include #include #include -#include // note, 4096 slots total volatile uint32_t* dlist_memory = REG32(SCALER_LIST_MEMORY); @@ -33,6 +34,8 @@ static uint32_t gfx_to_hvs_pixel_format(gfx_format fmt) { } void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip) { + assert(fb); + printf("rendering FB of size %dx%d at %dx%d\n", fb->width, fb->height, x, y); dlist_memory[display_slot++] = CONTROL_VALID | CONTROL_WORDS(7) | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) @@ -48,22 +51,66 @@ void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip) { dlist_memory[display_slot++] = fb->stride * fb->pixelsize; } -void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, int width, int height, bool hflip) { +enum scaling_mode { + none, + PPF, // upscaling? + TPZ // downscaling? +}; + +static void write_tpz(unsigned int source, unsigned int dest) { + uint32_t scale = (1<<16) * source / dest; + uint32_t recip = ~0 / scale; + dlist_memory[display_slot++] = scale << 8; + dlist_memory[display_slot++] = recip; +} + +void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, unsigned int width, unsigned int height, bool hflip) { + assert(fb); + //printf("rendering FB of size %dx%d at %dx%d, scaled down to %dx%d\n", fb->width, fb->height, x, y, width, height); + enum scaling_mode xmode, ymode; + if (fb->width > width) xmode = TPZ; + else if (fb->width < width) xmode = PPF; + else xmode = none; + + if (fb->height > height) ymode = TPZ; + else if (fb->height < height) ymode = PPF; + else ymode = none; + + int scl0; + switch ((xmode << 2) | ymode) { + case (PPF << 2) | PPF: + scl0 = SCALER_CTL0_SCL_H_PPF_V_PPF; + break; + case (TPZ << 2) | PPF: + scl0 = SCALER_CTL0_SCL_H_TPZ_V_PPF; + break; + case (PPF << 2) | TPZ: + scl0 = SCALER_CTL0_SCL_H_PPF_V_TPZ; + break; + case (TPZ << 2) | TPZ: + scl0 = SCALER_CTL0_SCL_H_TPZ_V_TPZ; + break; + default: + puts("unsupported scale combonation"); + } + int start = display_slot; - dlist_memory[display_slot++] = CONTROL_VALID - | CONTROL_WORDS(14) + dlist_memory[display_slot++] = 0 // CONTROL_VALID +// | CONTROL_WORDS(14) | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) // | CONTROL0_VFLIP // makes the HVS addr count down instead, pointer word must be last line of image | (hflip ? CONTROL0_HFLIP : 0) - | CONTROL_FORMAT(gfx_to_hvs_pixel_format(fb->format)); - dlist_memory[display_slot++] = POS0_X(x) | POS0_Y(y) | POS0_ALPHA(0xff); - dlist_memory[display_slot++] = width | (height << 16); - dlist_memory[display_slot++] = POS2_H(fb->height) | POS2_W(fb->width); - dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state - dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0xc0000000; - dlist_memory[display_slot++] = 0xDEADBEEF; // dummy for HVS state - dlist_memory[display_slot++] = fb->stride * fb->pixelsize; - dlist_memory[display_slot++] = 0x100; + | CONTROL_FORMAT(gfx_to_hvs_pixel_format(fb->format)) + | (scl0 << 5) + | (scl0 << 8); // SCL1 + dlist_memory[display_slot++] = POS0_X(x) | POS0_Y(y) | POS0_ALPHA(0xff); // position word 0 + dlist_memory[display_slot++] = width | (height << 16); // position word 1 + dlist_memory[display_slot++] = POS2_H(fb->height) | POS2_W(fb->width); // position word 2 + dlist_memory[display_slot++] = 0xDEADBEEF; // position word 3, dummy for HVS state + dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0xc0000000; // pointer word 0 + dlist_memory[display_slot++] = 0xDEADBEEF; // pointer context word 0 dummy for HVS state + dlist_memory[display_slot++] = fb->stride * fb->pixelsize; // pitch word 0 + dlist_memory[display_slot++] = 0x100; // LBM base addr #if 0 bool ppf = false; @@ -76,19 +123,26 @@ void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, int width, int height, dlist_memory[display_slot++] = 0xDEADBEEF; //scaling context } #endif - bool tpz = true; - if (tpz) { - uint32_t xscale = (1<<16) * fb->width / width; - uint32_t yscale = (1<<16) * fb->height / height; - uint32_t xrecip = ~0 / xscale; - uint32_t yrecip = ~0 / yscale; - dlist_memory[display_slot++] = (xscale << 8); - dlist_memory[display_slot++] = xrecip; - dlist_memory[display_slot++] = (yscale << 8); - dlist_memory[display_slot++] = yrecip; - dlist_memory[display_slot++] = 0xDEADBEEF; //scaling context + + if (xmode == PPF) { + puts("unfinished"); + } + + if (ymode == PPF) { + puts("unfinished"); + } + + if (xmode == TPZ) { + write_tpz(fb->width, width); } - printf("entry size: %d\n", display_slot - start); + + if (ymode == TPZ) { + write_tpz(fb->height, height); + dlist_memory[display_slot++] = 0xDEADBEEF; // context for scaling + } + + //printf("entry size: %d, spans 0x%x-0x%x\n", display_slot - start, start, display_slot); + dlist_memory[start] |= CONTROL_VALID | CONTROL_WORDS(display_slot - start); } void hvs_terminate_list(void) { @@ -138,6 +192,43 @@ void hvs_wipe_displaylist(void) { display_slot = 0; } +static bool bcm_host_is_model_pi4(void) { + return false; +} + +void hvs_print_position0(uint32_t w) { + printf("position0: 0x%x\n", w); + if (bcm_host_is_model_pi4()) { + printf(" x: %d y: %d\n", w & 0x3fff, (w >> 16) & 0x3fff); + } else { + printf(" x: %d y: %d\n", w & 0xfff, (w >> 12) & 0xfff); + } +} +void hvs_print_control2(uint32_t w) { + printf("control2: 0x%x\n", w); + printf(" alpha: 0x%x\n", (w >> 4) & 0xffff); + printf(" alpha mode: %d\n", (w >> 30) & 0x3); +} +void hvs_print_word1(uint32_t w) { + printf(" word1: 0x%x\n", w); +} +void hvs_print_position2(uint32_t w) { + printf("position2: 0x%x\n", w); + printf(" width: %d height: %d\n", w & 0xffff, (w >> 16) & 0xfff); +} +void hvs_print_position3(uint32_t w) { + printf("position3: 0x%x\n", w); +} +void hvs_print_pointer0(uint32_t w) { + printf("pointer word: 0x%x\n", w); +} +void hvs_print_pointerctx0(uint32_t w) { + printf("pointer context word: 0x%x\n", w); +} +void hvs_print_pitch0(uint32_t w) { + printf("pitch word: 0x%x\n", w); +} + static int cmd_hvs_dump(int argc, const cmd_args *argv) { printf("SCALER_DISPCTRL: 0x%x\n", *REG32(SCALER_DISPCTRL)); printf("SCALER_DISPSTAT: 0x%x\n", *REG32(SCALER_DISPSTAT)); @@ -162,8 +253,60 @@ static int cmd_hvs_dump(int argc, const cmd_args *argv) { uint32_t base = hvs_channels[i].dispbase; printf("SCALER_DISPBASE%d: base 0x%x top 0x%x\n\n", i, base & 0xffff, base >> 16); } - for (uint32_t i=list1; i<(list1+16); i++) { + for (uint32_t i=list1; i<(list1+64); i++) { printf("dlist[%x]: 0x%x\n", i, dlist_memory[i]); + if (dlist_memory[i] & BV(31)) { + puts("(31)END"); + break; + } + if (dlist_memory[i] & BV(30)) { + int x = i; + int words = (dlist_memory[i] >> 24) & 0x3f; + for (unsigned int index=i; index < (i+words); index++) { + printf("raw dlist[%d] == 0x%x\n", index-i, dlist_memory[index]); + } + bool unity; + printf(" (3:0)format: %d\n", dlist_memory[i] & 0xf); + if (dlist_memory[i] & (1<<4)) puts(" (4)unity"); + printf(" (7:5)SCL0: %d\n", (dlist_memory[i] >> 5) & 0x7); + printf(" (10:8)SCL1: %d\n", (dlist_memory[i] >> 8) & 0x7); + if (false) { // is bcm2711 + if (dlist_memory[i] & (1<<11)) puts(" (11)rgb expand"); + if (dlist_memory[i] & (1<<12)) puts(" (12)alpha expand"); + } else { + printf(" (12:11)rgb expand: %d\n", (dlist_memory[i] >> 11) & 0x3); + } + printf(" (14:13)pixel order: %d\n", (dlist_memory[i] >> 13) & 0x3); + if (false) { // is bcm2711 + unity = dlist_memory[i] & (1<<15); + } else { + unity = dlist_memory[i] & (1<<4); + if (dlist_memory[i] & (1<<15)) puts(" (15)vflip"); + if (dlist_memory[i] & (1<<16)) puts(" (16)hflip"); + } + printf(" (18:17)key mode: %d\n", (dlist_memory[i] >> 17) & 0x3); + if (dlist_memory[i] & (1<<19)) puts(" (19)alpha mask"); + printf(" (21:20)tiling mode: %d\n", (dlist_memory[i] >> 20) & 0x3); + printf(" (29:24)words: %d\n", words); + x++; + hvs_print_position0(dlist_memory[x++]); + if (bcm_host_is_model_pi4()) { + hvs_print_control2(dlist_memory[x++]); + } + if (unity) { + puts("unity scaling"); + } else { + hvs_print_word1(dlist_memory[x++]); + } + hvs_print_position2(dlist_memory[x++]); + hvs_print_position3(dlist_memory[x++]); + hvs_print_pointer0(dlist_memory[x++]); + hvs_print_pointerctx0(dlist_memory[x++]); + hvs_print_pitch0(dlist_memory[x++]); + if (words > 1) { + i += words - 1; + } + } } return 0; } diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index a33bb0847a..5c9754e4b5 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -49,7 +49,7 @@ extern volatile struct hvs_channel *hvs_channels; #define CONTROL_FORMAT(n) (n & 0xf) #define CONTROL_END (1<<31) #define CONTROL_VALID (1<<30) -#define CONTROL_WORDS(n) ((n & 0x3f) << 24) +#define CONTROL_WORDS(n) (((n) & 0x3f) << 24) #define CONTROL0_FIXED_ALPHA (1<<19) #define CONTROL0_HFLIP (1<<16) #define CONTROL0_VFLIP (1<<15) @@ -92,6 +92,15 @@ enum hvs_pixel_format { #define HVS_PIXEL_ORDER_XRGB 2 #define HVS_PIXEL_ORDER_XBGR 3 +#define SCALER_CTL0_SCL_H_PPF_V_PPF 0 +#define SCALER_CTL0_SCL_H_TPZ_V_PPF 1 +#define SCALER_CTL0_SCL_H_PPF_V_TPZ 2 +#define SCALER_CTL0_SCL_H_TPZ_V_TPZ 3 +#define SCALER_CTL0_SCL_H_PPF_V_NONE 4 +#define SCALER_CTL0_SCL_H_NONE_V_PPF 5 +#define SCALER_CTL0_SCL_H_NONE_V_TPZ 6 +#define SCALER_CTL0_SCL_H_TPZ_V_NONE 7 + #define POS0_X(n) (n & 0xfff) #define POS0_Y(n) ((n & 0xfff) << 12) #define POS0_ALPHA(n) ((n & 0xff) << 24) @@ -103,7 +112,7 @@ extern int display_slot; extern volatile uint32_t* dlist_memory; void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip); -void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, int width, int height, bool hflip); +void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, unsigned int width, unsigned int height, bool hflip); void hvs_terminate_list(void); void hvs_wipe_displaylist(void); void hvs_initialize(void); diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index be73696e1c..466c387bf3 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -15,6 +15,7 @@ void print_timestamp(void); } #endif +#define BV(n) (1 << n) #define SDRAM_BASE 0 #ifdef ARCH_VPU #define BCM_PERIPH_BASE_PHYS (0x7e000000U) diff --git a/platform/bcm28xx/pixelvalve/pv.c b/platform/bcm28xx/pixelvalve/pv.c index b70b899f00..ffb5186cdb 100644 --- a/platform/bcm28xx/pixelvalve/pv.c +++ b/platform/bcm28xx/pixelvalve/pv.c @@ -4,8 +4,6 @@ #include #include -#define BV(b) (1 << b) - struct pixel_valve *getPvAddr(int pvnr) { uint32_t addr; assert(pvnr <= 2); @@ -22,7 +20,7 @@ struct pixel_valve *getPvAddr(int pvnr) { default: return NULL; } - struct pixel_valve *rawpv = addr; + struct pixel_valve *rawpv = (struct pixel_valve*) addr; return rawpv; } @@ -87,7 +85,7 @@ void setup_pixelvalve(struct pv_timings *t, int pvnr) { } void setup_pv_interrupt(int pvnr, int_handler handler, void *arg) { - struct pixel_valve *rawpv = getPvAddr(pvnr); + //struct pixel_valve *rawpv = getPvAddr(pvnr); unsigned int irq = getPvIrq(pvnr); register_int_handler(irq, handler, arg); diff --git a/platform/bcm28xx/power/include/platform/bcm28xx/power.h b/platform/bcm28xx/power/include/platform/bcm28xx/power.h index a5e38f508d..9c3eaa4ccb 100644 --- a/platform/bcm28xx/power/include/platform/bcm28xx/power.h +++ b/platform/bcm28xx/power/include/platform/bcm28xx/power.h @@ -3,8 +3,6 @@ #include #include -#define BIT(n) (1< #include -#define BIT(n) (1 << n) - #define VEC_BASE (BCM_PERIPH_BASE_VIRT + 0x806000) #define VEC_WSE_RESET (VEC_BASE + 0x0c0) @@ -12,7 +10,7 @@ #define VEC_CONFIG0 (VEC_BASE + 0x104) #define VEC_CONFIG0_NTSC_STD 0 #define VEC_CONFIG0_PAL_BDGHI_STD 1 -#define VEC_CONFIG0_PDEN BIT(6) +#define VEC_CONFIG0_PDEN BV(6) #define VEC_SCHPH (VEC_BASE + 0x108) #define VEC_SOFT_RESET (VEC_BASE + 0x10c) #define VEC_CLMP0_START (VEC_BASE + 0x144) @@ -20,20 +18,20 @@ #define VEC_FREQ3_2 (VEC_BASE + 0x180) #define VEC_FREQ1_0 (VEC_BASE + 0x184) #define VEC_CONFIG1 (VEC_BASE + 0x188) -#define VEC_CONFIG1_CUSTOM_FREQ BIT(0) +#define VEC_CONFIG1_CUSTOM_FREQ BV(0) #define VEC_CONFIG1_C_CVBS_CVBS (7 << 10) #define VEC_CONFIG2 (VEC_BASE + 0x18c) -#define VEC_CONFIG2_UV_DIG_DIS BIT(6) -#define VEC_CONFIG2_RGB_DIG_DIS BIT(5) +#define VEC_CONFIG2_UV_DIG_DIS BV(6) +#define VEC_CONFIG2_RGB_DIG_DIS BV(5) #define VEC_CONFIG3 (VEC_BASE + 0x1a0) #define VEC_CONFIG3_HORIZ_LEN_STD (0 << 0) #define VEC_MASK0 (VEC_BASE + 0x204) #define VEC_CFG (VEC_BASE + 0x208) -#define VEC_CFG_VEC_EN BIT(3) +#define VEC_CFG_VEC_EN BV(3) #define VEC_DAC_CONFIG (VEC_BASE + 0x210) #define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x) ((x) << 24) #define VEC_DAC_CONFIG_DRIVER_CTRL(x) ((x) << 16) #define VEC_DAC_CONFIG_DAC_CTRL(x) (x) #define VEC_DAC_MISC (VEC_BASE + 0x214) -#define VEC_DAC_MISC_DAC_RST_N BIT(0) -#define VEC_DAC_MISC_VID_ACT BIT(8) +#define VEC_DAC_MISC_DAC_RST_N BV(0) +#define VEC_DAC_MISC_VID_ACT BV(8) diff --git a/platform/bcm28xx/vec/vec.c b/platform/bcm28xx/vec/vec.c index baf32bf150..1782cafdcf 100644 --- a/platform/bcm28xx/vec/vec.c +++ b/platform/bcm28xx/vec/vec.c @@ -1,7 +1,8 @@ #include +#include +#include #include #include -#include #include #include #include @@ -12,6 +13,8 @@ #include "pi-logo.h" +//extern uint8_t* pilogo; + enum vec_mode { ntsc, ntscj, @@ -95,7 +98,6 @@ static void vec_init(const struct app_descriptor *app) { stride = t.hactive; framebuffer = gfx_create_surface(NULL, width, height, width, GFX_FORMAT_ARGB_8888); } - printf("framebuffer at 0x%x is %dx%d stride: %d\n", framebuffer->ptr, framebuffer->width, framebuffer->height, framebuffer->stride); int grid = 20; for (int x=0; x< width; x++) { for (int y=0; y < height; y++) { @@ -117,9 +119,11 @@ static void vec_init(const struct app_descriptor *app) { logo = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); list_start = display_slot; hvs_add_plane(framebuffer, 0, 0, false); - hvs_add_plane(logo, (width/2) - (logo->width/2), 0, false); + hvs_add_plane_scaled(logo, (width/2) - (logo->width/2), 0, 100, 100, false); hvs_terminate_list(); *REG32(SCALER_DISPLIST1) = list_start; + + dance_start(logo, 1); } static void vec_entry(const struct app_descriptor *app, void *args) { diff --git a/project/rpi3-start.mk b/project/rpi3-start.mk index f205b77575..8cd7630134 100644 --- a/project/rpi3-start.mk +++ b/project/rpi3-start.mk @@ -10,3 +10,4 @@ MODULES += \ lib/debugcommands \ platform/bcm28xx/otp \ platform/bcm28xx/vec \ + platform/bcm28xx/hvs-dance \ From af84c4dd0392c5486dc46a9f8c30cc0d5360b561 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Fri, 26 Mar 2021 05:35:22 -0300 Subject: [PATCH 096/100] arm looks to be starting? --- platform/bcm28xx/arm/arm.c | 182 ++++++++++++++++++ platform/bcm28xx/arm/payload.S | 6 + platform/bcm28xx/arm/rules.mk | 7 + platform/bcm28xx/hvs-dance/dance.c | 77 ++++++-- platform/bcm28xx/hvs-dance/include/dance.h | 2 +- platform/bcm28xx/hvs-dance/rules.mk | 1 + platform/bcm28xx/hvs/hvs.c | 64 ++++-- .../hvs/include/platform/bcm28xx/hvs.h | 19 +- .../bcm28xx/include/platform/bcm28xx/pll.h | 12 ++ platform/bcm28xx/platform.c | 4 +- platform/bcm28xx/pll/pll_control.c | 7 +- platform/bcm28xx/pll/pll_read.c | 2 + .../power/include/platform/bcm28xx/power.h | 3 +- platform/bcm28xx/power/power.c | 16 +- platform/bcm28xx/vec/vec.c | 12 +- project/rpi3-start.mk | 1 + 16 files changed, 368 insertions(+), 47 deletions(-) create mode 100644 platform/bcm28xx/arm/arm.c create mode 100644 platform/bcm28xx/arm/payload.S create mode 100644 platform/bcm28xx/arm/rules.mk diff --git a/platform/bcm28xx/arm/arm.c b/platform/bcm28xx/arm/arm.c new file mode 100644 index 0000000000..97a99d3b50 --- /dev/null +++ b/platform/bcm28xx/arm/arm.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include + +extern uint8_t arm_payload_start, arm_payload_end; + +void mapBusToArm(uint32_t busAddr, uint32_t armAddr); +void setupClock(void); +void bridgeStart(bool cycleBrespBits); + +#define ARM_CONTROL0 (ARM_BASE+0x000) +#define ARM_C0_SIZ1G 0x00000003 +#define ARM_C0_BRESP1 0x00000004 +#define ARM_C0_BRESP2 0x00000008 +#define ARM_C0_FULLPERI 0x00000040 +#define ARM_C0_APROTPASS 0x0000A000 // Translate 1:1 +#define ARM_C0_APROTMSK 0x0000F000 +#define ARM_TRANSLATE (ARM_BASE+0x100) +#define ARM_CONTROL1 (ARM_BASE+0x440) +#define ARM_C1_PERSON 0x00000100 // peripherals on +#define ARM_C1_REQSTOP 0x00000200 // ASYNC bridge request stop +#define ARM_ERRHALT (ARM_BASE + 0x448) +#define ARM_ID (ARM_BASE + 0x44C) + +#define PM_PROC_ARMRSTN_CLR 0xffffffbf + +static const uint8_t g_BrespTab[] = { + 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x1C, 0x18, 0x1C, 0x18, 0x0, + 0x10, 0x14, 0x10, 0x1C, 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x0, + 0x10, 0x14, 0x10, 0x1C, 0x18, 0x1C, 0x10, 0x14, 0x18, 0x1C, 0x10, 0x14, 0x10, 0x0, + 0x10, 0x14, 0x18, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x0, + 0x10, 0x14, 0x18, 0x14, 0x18, 0x14, 0x10, 0x14, 0x10, 0x14, 0x10, 0x14, 0x18, 0x0 +}; + +static void printregs(void) { + printf("C0: 0x%x, C1: 0x%x, ERRHALT: 0x%x\n", *REG32(ARM_CONTROL0), *REG32(ARM_CONTROL1), *REG32(ARM_ERRHALT)); + printf("CM_LOCK: 0x%x\n", *REG32(CM_LOCK)); +} + +static void arm_init(const struct app_descriptor *app) { + power_arm_start(); + printregs(); + printf("arm starting...\n"); + memcpy((void*)0xc0000000, &arm_payload_start, &arm_payload_end - &arm_payload_start); + mapBusToArm(0xc0000000, 0); + printf("armid 0x%x, C0 0x%x\n", *REG32(ARM_ID), *REG32(ARM_CONTROL0)); + /* + * enable peripheral access, map arm secure bits to axi secure bits 1:1 and + * set the mem size for who knows what reason. + */ + *REG32(ARM_CONTROL0) |= + ARM_C0_BRESP2 + | ARM_C0_SIZ1G + | ARM_C0_APROTPASS | ARM_C0_APROTMSK // allow both kernel and userland to access mmio + | ARM_C0_FULLPERI // allow access to all peripherals + | (0x8 << 20) // ARM_C0_PRIO_PER + | (0x5 << 24) // ARM_C0_PRIO_L2 + | (0xa << 28); // ARM_C0_PRIO_UC + // | ARM_C0_AARCH64; + *REG32(ARM_CONTROL1) |= ARM_C1_PERSON; + + printregs(); + + setupClock(); + printregs(); + power_arm_start(); + printregs(); + bridgeStart(true); + printregs(); +} + +// maps a 16mb chunk of ram +// the bus address has a resolution of 2mb +// the arm addr has a resolution of 16mb +// the entire mapping is 16mb long +// comments say there are 32 slots in the list (512mb mapped) an another 32 spare (1gig mapped) +void mapBusToArm(uint32_t busAddr, uint32_t armAddr) { + volatile uint32_t* tte = (volatile uint32_t*)ARM_TRANSLATE; + + uint32_t index = armAddr >> 24; // div by 16mb + uint32_t pte = busAddr >> 21; // div by 2mb + printf("mapBusToArm index:%x, pte:%x\n", index, pte); + + tte[index] = pte; +} + +void setupClock(void) { + puts("initializing PLLB ..."); + + /* oscillator->pllb */ + *REG32(A2W_XOSC_CTRL) |= A2W_PASSWORD | A2W_XOSC_CTRL_PLLBEN_SET; + + *REG32(A2W_PLLB_FRAC) = A2W_PASSWORD | 0xeaaa8; // out of 0x100000 + *REG32(A2W_PLLB_CTRL) = A2W_PASSWORD | 48 | 0x1000; + + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; + + *REG32(A2W_PLLB_ANA3) = A2W_PASSWORD | 0x100; + *REG32(A2W_PLLB_ANA2) = A2W_PASSWORD | 0x0; + *REG32(A2W_PLLB_ANA1) = A2W_PASSWORD | 0x140000; + *REG32(A2W_PLLB_ANA0) = A2W_PASSWORD | 0x0; + + *REG32(CM_PLLB) = CM_PASSWORD | 0xAA; // hold all divider taps + + uint32_t dig0 = *REG32(A2W_PLLB_DIG0), + dig1 = *REG32(A2W_PLLB_DIG1), + dig2 = *REG32(A2W_PLLB_DIG2), + dig3 = *REG32(A2W_PLLB_DIG3); + + *REG32(A2W_PLLB_DIG3) = A2W_PASSWORD | dig3; + *REG32(A2W_PLLB_DIG2) = A2W_PASSWORD | (dig2 & 0xFFEFFBFE); + *REG32(A2W_PLLB_DIG1) = A2W_PASSWORD | (dig1 & ~(1 << 14)); + *REG32(A2W_PLLB_DIG0) = A2W_PASSWORD | dig0; + + *REG32(A2W_PLLB_CTRL) |= A2W_PASSWORD | 0x20000; + + dig3 |= 0x42; + + *REG32(A2W_PLLB_DIG3) = A2W_PASSWORD | dig3; + *REG32(A2W_PLLB_DIG2) = A2W_PASSWORD | dig2; + *REG32(A2W_PLLB_DIG1) = A2W_PASSWORD | dig1; + *REG32(A2W_PLLB_DIG0) = A2W_PASSWORD | dig0; + + + *REG32(A2W_PLLB_ARM) = A2W_PASSWORD | 2; + + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET | CM_PLLB_LOADARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD | CM_PLLB_DIGRST_SET | CM_PLLB_ANARST_SET | CM_PLLB_HOLDARM_SET; + *REG32(CM_PLLB) = CM_PASSWORD; + + *REG32(CM_ARMCTL) = CM_PASSWORD | 4 | CM_ARMCTL_ENAB_SET; + + printf("KAIP = 0x%X\n", *REG32(A2W_PLLB_ANA_KAIP)); /* 0x228 */ + printf("MULTI = 0x%X\n", *REG32(A2W_PLLB_ANA_MULTI)); /* 0x613277 */ + + puts("ARM clock succesfully initialized!"); +} + +void bridgeWriteBresp(uint8_t bits) { + //printf("bits: 0x%x\n", bits); + *REG32(ARM_CONTROL0) = (*REG32(ARM_CONTROL0) & ~(ARM_C0_BRESP1|ARM_C0_BRESP2)) | bits; + udelay(30); +} + +void bridgeCycleBresp(void) { + puts("cycling through bresp bits ..."); + for (unsigned int i = 0; i < sizeof(g_BrespTab)/sizeof(g_BrespTab[0]); i++) { + bridgeWriteBresp(g_BrespTab[i]); + } +} + +void bridgeStart(bool cycleBrespBits) { + puts("setting up async bridge ..."); + + if (cycleBrespBits) { + *REG32(PM_PROC) |= PM_PASSWORD | ~PM_PROC_ARMRSTN_CLR; + bridgeCycleBresp(); + *REG32(PM_PROC) |= PM_PASSWORD | ~PM_PROC_ARMRSTN_CLR; + + udelay(300); + } + + puts("starting async bridge now!"); + *REG32(ARM_CONTROL1) &= ~ARM_C1_REQSTOP; + udelay(300); + + if (!cycleBrespBits) { + *REG32(PM_PROC) |= PM_PASSWORD | ~PM_PROC_ARMRSTN_CLR; + } + + printf("bridge init done, PM_PROC is now: 0x%X!\n", *REG32(PM_PROC)); +} + +APP_START(arm) + .init = arm_init, +// .entry = arm_entry, +APP_END diff --git a/platform/bcm28xx/arm/payload.S b/platform/bcm28xx/arm/payload.S new file mode 100644 index 0000000000..7f32120f21 --- /dev/null +++ b/platform/bcm28xx/arm/payload.S @@ -0,0 +1,6 @@ +.data +.global arm_payload_start +arm_payload_start: +.incbin "../../../armstart.bin" +.global arm_payload_end +arm_payload_end: diff --git a/platform/bcm28xx/arm/rules.mk b/platform/bcm28xx/arm/rules.mk new file mode 100644 index 0000000000..2660ef6691 --- /dev/null +++ b/platform/bcm28xx/arm/rules.mk @@ -0,0 +1,7 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) +MODULE := $(LOCAL_DIR) +MODULE_SRCS += $(LOCAL_DIR)/arm.c $(LOCAL_DIR)/payload.S + +MODULES += platform/bcm28xx/power + +include make/module.mk diff --git a/platform/bcm28xx/hvs-dance/dance.c b/platform/bcm28xx/hvs-dance/dance.c index dc4538dc39..7b0008e6ad 100644 --- a/platform/bcm28xx/hvs-dance/dance.c +++ b/platform/bcm28xx/hvs-dance/dance.c @@ -1,44 +1,48 @@ #include #include #include +#include #include #include #include #include #include #include -//#include #include #include #include #include #include +//#include static int cmd_hvs_dance(int argc, const cmd_args *argv); static int cmd_hvs_limit(int argc, const cmd_args *argv); static int cmd_hvs_delay(int argc, const cmd_args *argv); static int cmd_dance_update(int argc, const cmd_args *argv); +static int cmd_dance_list(int argc, const cmd_args *argv); STATIC_COMMAND_START STATIC_COMMAND("dance", "make the HVS dance in another direction", &cmd_hvs_dance) STATIC_COMMAND("l", "limit sprites", &cmd_hvs_limit) STATIC_COMMAND("d", "delay updates", &cmd_hvs_delay) STATIC_COMMAND("u", "update", &cmd_dance_update) +STATIC_COMMAND("dance_list", "list", &cmd_dance_list) STATIC_COMMAND_END(hvs_dance); gfx_surface *fb; +void (*background)(void); struct item { - unsigned int x, y; + signed int x, y; signed int xd, yd; }; #define ITEMS 580 struct item items[ITEMS]; -uint32_t sprite_limit = 15; +uint32_t sprite_limit = 2; int delay = 0; -uint32_t screen_width, screen_height; +int32_t screen_width, screen_height; #define SCALED @@ -46,8 +50,8 @@ void do_frame_update(int frame) { if (delay != 0) { if ((frame % delay) != 0) return; } - if ((display_slot + (sprite_limit * 7) + 1) > 4096) { - printf("early dlist loop %d\n", display_slot); + if ((display_slot + (sprite_limit * 14) + 1) > 4096) { + //printf("early dlist loop %d\n", display_slot); display_slot = 0; } @@ -61,6 +65,7 @@ void do_frame_update(int frame) { #endif int start = display_slot; + background(); for (unsigned int i=0; i < sprite_limit; i++) { struct item *it = &items[i]; if (it->x > (screen_width - w)) it->xd *= -1; @@ -69,6 +74,23 @@ void do_frame_update(int frame) { it->x += it->xd; it->y += it->yd; + if (it->x < 0) { + it->x *= -1; + it->xd *= -1; + } + if (it->y < 0) { + it->y *= -1; + it->yd *= -1; + } + if (it->x > screen_width) { + it->x -= screen_width; + it->xd *= -1; + } + if (it->y > screen_height) { + it->y -= screen_height; + it->yd *= -1; + } + #if 0 if (it->x < 0) { it->x = it->x * -1; @@ -88,7 +110,7 @@ void do_frame_update(int frame) { hvs_terminate_list(); if (display_slot > 4096) { - //printf("dlist overflow!!!: %d\n", display_slot); + printf("dlist overflow!!!: %d\n", display_slot); display_slot = 0; do_frame_update(frame); return; @@ -102,8 +124,15 @@ void do_frame_update(int frame) { } } +static int cmd_dance_list(int argc, const cmd_args *argv) { + for (unsigned int i=0; i < sprite_limit; i++) { + struct item *it = &items[i]; + printf("%d: %dx%d, rate %dx%d\n", i, it->x, it->y, it->xd, it->yd); + } + return 0; +} + static int cmd_dance_update(int argc, const cmd_args *argv) { - printf("fb 0x%x is %dx%d\n", fb, fb->width, fb->height); do_frame_update(0); return 0; } @@ -121,9 +150,9 @@ static enum handler_return pv_irq(void *pvnr) { ack |= PV_INTEN_HSYNC_START; hsync = t; if ((SCALER_STAT_LINE(stat1) % 5) == 0) { - //hvs_channels[1].dispbkgnd = (1<<24) | 0x00ff00; + //hvs_set_background_color(1, 0x0000ff); } else { - //hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; + //hvs_set_background_color(1, 0xffffff); } } if (stat & PV_INTEN_HBP_START) { @@ -153,7 +182,7 @@ static enum handler_return pv_irq(void *pvnr) { ack |= PV_INTEN_VFP_START; last_vfps = vfps; vfps = t; - //hvs_channels[1].dispbkgnd = (1<<24) | 0xff0000; + hvs_set_background_color(1, 0xff0000); do_frame_update((stat1 >> 12) & 0x3f); //printf("line: %d frame: %2d start: %4d ", stat1 & 0xfff, (stat1 >> 12) & 0x3f, *REG32(SCALER_DISPLIST1)); //uint32_t idle = *REG32(SD_IDL); @@ -162,7 +191,7 @@ static enum handler_return pv_irq(void *pvnr) { //uint64_t idle_percent = ((uint64_t)idle * 100) / ((uint64_t)total); //printf("sdram usage: %d %d, %lld\n", idle, total, idle_percent); //printf("HSYNC:%5d HBP:%d HACT:%d HFP:%d VSYNC:%5d VBP:%5d VFPS:%d FRAME:%d\n", t - vsync, t-hbp, t-hact, t-hfp, t-vsync, t-vbp, t-vfps, t-last_vfps); - //hvs_channels[1].dispbkgnd = (1<<24) | 0xffffff; + hvs_set_background_color(1, 0xffffff); } if (stat & PV_INTEN_VFP_END) { ack |= PV_INTEN_VFP_END; @@ -187,11 +216,23 @@ static void dance_scramble(void) { struct item *it = &items[i]; it->x = (unsigned int)rand() % screen_width; it->y = (unsigned int)rand() % screen_height; - it->xd = rand() % 10; - it->yd = rand() % 10; + it->xd = (rand() % 5)+1; + it->yd = (rand() % 5)+1; if (it->x > (screen_width - w)) it->x = screen_width - fb->width; if (it->y > (screen_height - h)) it->y = screen_height - fb->height; } + + items[0].x = 40; + items[0].y = 100; + items[0].xd = 0; + items[0].yd = 0; + +#if 0 + items[1].x = 140; + items[1].y = 0; + items[1].xd = 0; + items[1].yd = 1; +#endif } static int cmd_hvs_dance(int argc, const cmd_args *argv) { @@ -210,14 +251,14 @@ static int cmd_hvs_delay(int argc, const cmd_args *argv) { return 0; } -void dance_start(gfx_surface* fbin, int hvs_channel) { +void dance_start(gfx_surface* fbin, int hvs_channel, void (*backgroundcb)(void)) { fb = fbin; + background = backgroundcb; gfx_flush(fb); - struct hvs_channel *hvs_channels = (struct hvs_channel*)REG32(SCALER_DISPCTRL0); - hvs_channels[hvs_channel].dispbkgnd = (1<<24) | 0xffffff; + hvs_set_background_color(hvs_channel, 0xffffff); screen_width = (hvs_channels[hvs_channel].dispctrl >> 12) & 0xfff; - screen_height = (hvs_channels[hvs_channel].dispctrl & 0xfff) / 2; + screen_height = (hvs_channels[hvs_channel].dispctrl & 0xfff); printf("detected a %dx%d screen\n", screen_width, screen_height); srand(*REG32(ST_CLO)); diff --git a/platform/bcm28xx/hvs-dance/include/dance.h b/platform/bcm28xx/hvs-dance/include/dance.h index ee74294439..02a1506d07 100644 --- a/platform/bcm28xx/hvs-dance/include/dance.h +++ b/platform/bcm28xx/hvs-dance/include/dance.h @@ -2,4 +2,4 @@ #include -void dance_start(gfx_surface* fbin, int hvs_channel); +void dance_start(gfx_surface* fbin, int hvs_channel, void (*background)(void)); diff --git a/platform/bcm28xx/hvs-dance/rules.mk b/platform/bcm28xx/hvs-dance/rules.mk index 211eeb77b9..6d5f823a52 100644 --- a/platform/bcm28xx/hvs-dance/rules.mk +++ b/platform/bcm28xx/hvs-dance/rules.mk @@ -18,5 +18,6 @@ $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.tga: $(LOCAL_DIR)/RPi-Logo-Reg-SCREEN.png $(BUILDDIR)/$(LOCAL_DIR)/dance.o: $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.h GLOBAL_INCLUDES += $(BUILDDIR)/$(LOCAL_DIR) +MODULE_CFLAGS := -O2 include make/module.mk diff --git a/platform/bcm28xx/hvs/hvs.c b/platform/bcm28xx/hvs/hvs.c index a5d0b51506..3472f0bce5 100644 --- a/platform/bcm28xx/hvs/hvs.c +++ b/platform/bcm28xx/hvs/hvs.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -11,6 +12,16 @@ volatile uint32_t* dlist_memory = REG32(SCALER_LIST_MEMORY); volatile struct hvs_channel *hvs_channels = (volatile struct hvs_channel*)REG32(SCALER_DISPCTRL0); int display_slot = 0; +int scaled_layer_count = 0; +timer_t ddr2_monitor; + +enum scaling_mode { + none, + PPF, // upscaling? + TPZ // downscaling? +}; + +struct hvs_channel_config channels[3]; static int cmd_hvs_dump(int argc, const cmd_args *argv); @@ -35,7 +46,7 @@ static uint32_t gfx_to_hvs_pixel_format(gfx_format fmt) { void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip) { assert(fb); - printf("rendering FB of size %dx%d at %dx%d\n", fb->width, fb->height, x, y); + //printf("rendering FB of size %dx%d at %dx%d\n", fb->width, fb->height, x, y); dlist_memory[display_slot++] = CONTROL_VALID | CONTROL_WORDS(7) | CONTROL_PIXEL_ORDER(HVS_PIXEL_ORDER_ABGR) @@ -51,12 +62,6 @@ void hvs_add_plane(gfx_surface *fb, int x, int y, bool hflip) { dlist_memory[display_slot++] = fb->stride * fb->pixelsize; } -enum scaling_mode { - none, - PPF, // upscaling? - TPZ // downscaling? -}; - static void write_tpz(unsigned int source, unsigned int dest) { uint32_t scale = (1<<16) * source / dest; uint32_t recip = ~0 / scale; @@ -66,7 +71,7 @@ static void write_tpz(unsigned int source, unsigned int dest) { void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, unsigned int width, unsigned int height, bool hflip) { assert(fb); - //printf("rendering FB of size %dx%d at %dx%d, scaled down to %dx%d\n", fb->width, fb->height, x, y, width, height); + if ((x < 0) || (y < 0)) printf("rendering FB of size %dx%d at %dx%d, scaled down to %dx%d\n", fb->width, fb->height, x, y, width, height); enum scaling_mode xmode, ymode; if (fb->width > width) xmode = TPZ; else if (fb->width < width) xmode = PPF; @@ -107,10 +112,11 @@ void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, unsigned int width, uns dlist_memory[display_slot++] = width | (height << 16); // position word 1 dlist_memory[display_slot++] = POS2_H(fb->height) | POS2_W(fb->width); // position word 2 dlist_memory[display_slot++] = 0xDEADBEEF; // position word 3, dummy for HVS state - dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0xc0000000; // pointer word 0 + dlist_memory[display_slot++] = (uint32_t)fb->ptr | 0x80000000; // pointer word 0 dlist_memory[display_slot++] = 0xDEADBEEF; // pointer context word 0 dummy for HVS state dlist_memory[display_slot++] = fb->stride * fb->pixelsize; // pitch word 0 - dlist_memory[display_slot++] = 0x100; // LBM base addr + dlist_memory[display_slot++] = (scaled_layer_count * 720); // LBM base addr + scaled_layer_count++; #if 0 bool ppf = false; @@ -147,6 +153,7 @@ void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, unsigned int width, uns void hvs_terminate_list(void) { dlist_memory[display_slot++] = CONTROL_END; + scaled_layer_count = 0; } static enum handler_return hvs_irq(void *unused) { @@ -154,7 +161,29 @@ static enum handler_return hvs_irq(void *unused) { return INT_NO_RESCHEDULE; } +//#define SD_IDL 0x7ee00018 +//#define SD_CYC 0x7ee00030 + +static void check_sdram_usage(void) { + static float last_time = 1; + uint64_t idle = *REG32(SD_IDL); + uint64_t total = *REG32(SD_CYC); + *REG32(SD_IDL) = 0; + uint32_t idle_percent = (idle * 100) / (total); + float time = ((float)*REG32(ST_CLO)) / 1000000; + uint32_t clock = total / (time - last_time) / 1000 / 1000; + last_time = time; + printf("[%f] DDR2 was idle 0x%x / 0x%x cycles (%d%%) %dMHz\n", time, (uint32_t)idle, (uint32_t)total, idle_percent, clock); +} + +static enum handler_return ddr2_checker(struct timer *unused1, unsigned int unused2, void *unused3) { + check_sdram_usage(); + return INT_NO_RESCHEDULE; +} + void hvs_initialize() { + timer_initialize(&ddr2_monitor); + //timer_set_periodic(&ddr2_monitor, 500, ddr2_checker, NULL); *REG32(SCALER_DISPCTRL) &= ~SCALER_DISPCTRL_ENABLE; // disable HVS *REG32(SCALER_DISPCTRL) = SCALER_DISPCTRL_ENABLE | 0x9a0dddff; // re-enable HVS for (int i=0; i<3; i++) { @@ -163,9 +192,9 @@ void hvs_initialize() { hvs_channels[i].dispbkgnd = 0x1020202; // bit 24 } - hvs_channels[2].dispbase = BASE_BASE(0) | BASE_TOP(0xf00); - hvs_channels[1].dispbase = BASE_BASE(0xf10) | BASE_TOP(0x4b00); - hvs_channels[0].dispbase = BASE_BASE(0x4b10) | BASE_TOP(0x7700); + hvs_channels[2].dispbase = BASE_BASE(0) | BASE_TOP(0x7f0); + hvs_channels[1].dispbase = BASE_BASE(0xf10) | BASE_TOP(0x50f0); + hvs_channels[0].dispbase = BASE_BASE(0x800) | BASE_TOP(0xf00); hvs_wipe_displaylist(); @@ -177,11 +206,16 @@ void hvs_setup_irq() { unmask_interrupt(33); } -void hvs_configure_channel(int channel, int width, int height) { +void hvs_configure_channel(int channel, int width, int height, bool interlaced) { + channels[channel].width = width; + channels[channel].height = height; + channels[channel].interlaced = interlaced; + hvs_channels[channel].dispctrl = SCALER_DISPCTRLX_RESET; hvs_channels[channel].dispctrl = SCALER_DISPCTRLX_ENABLE | SCALER_DISPCTRL_W(width) | SCALER_DISPCTRL_H(height); - hvs_channels[channel].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202 | SCALER_DISPBKGND_INTERLACE; + hvs_channels[channel].dispbkgnd = SCALER_DISPBKGND_AUTOHS | 0x020202 + | (channels[channel].interlaced ? SCALER_DISPBKGND_INTERLACE : 0); // the SCALER_DISPBKGND_INTERLACE flag makes the HVS alternate between sending even and odd scanlines } diff --git a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h index 5c9754e4b5..4d646a41ca 100644 --- a/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h +++ b/platform/bcm28xx/hvs/include/platform/bcm28xx/hvs.h @@ -27,6 +27,14 @@ struct hvs_channel { extern volatile struct hvs_channel *hvs_channels; +struct hvs_channel_config { + uint32_t width; + uint32_t height; + bool interlaced; +}; + +extern struct hvs_channel_config channels[3]; + #define SCALER_STAT_LINE(n) ((n) & 0xfff) #define SCALER_DISPCTRL0 (SCALER_BASE + 0x40) @@ -34,9 +42,9 @@ extern volatile struct hvs_channel *hvs_channels; #define SCALER_DISPCTRLX_RESET (1<<30) #define SCALER_DISPCTRL_W(n) ((n & 0xfff) << 12) #define SCALER_DISPCTRL_H(n) (n & 0xfff) -#define SCALER_DISPBKGND_AUTOHS (1<<31) +#define SCALER_DISPBKGND_AUTOHS (1<<31) #define SCALER_DISPBKGND_INTERLACE (1<<30) -#define SCALER_DISPBKGND_GAMMA (1<<29) +#define SCALER_DISPBKGND_GAMMA (1<<29) #define SCALER_DISPBKGND_FILL (1<<24) #define BASE_BASE(n) (n & 0xffff) @@ -116,5 +124,10 @@ void hvs_add_plane_scaled(gfx_surface *fb, int x, int y, unsigned int width, uns void hvs_terminate_list(void); void hvs_wipe_displaylist(void); void hvs_initialize(void); -void hvs_configure_channel(int channel, int width, int height); +void hvs_configure_channel(int channel, int width, int height, bool interlaced); void hvs_setup_irq(void); + +inline __attribute__((always_inline)) void hvs_set_background_color(int channel, uint32_t color) { + hvs_channels[channel].dispbkgnd = SCALER_DISPBKGND_FILL | SCALER_DISPBKGND_AUTOHS | color + | (channels[channel].interlaced ? SCALER_DISPBKGND_INTERLACE : 0); +} diff --git a/platform/bcm28xx/include/platform/bcm28xx/pll.h b/platform/bcm28xx/include/platform/bcm28xx/pll.h index 8f8c1beb4c..7a52d06cfd 100644 --- a/platform/bcm28xx/include/platform/bcm28xx/pll.h +++ b/platform/bcm28xx/include/platform/bcm28xx/pll.h @@ -166,6 +166,18 @@ void switch_vpu_to_src(int src); #define A2W_PLLC_ANA2 (A2W_BASE + 0x038) #define A2W_PLLC_ANA3 (A2W_BASE + 0x03c) +#define A2W_PLLB_DIG0 (A2W_BASE + 0x0e0) +#define A2W_PLLB_DIG1 (A2W_BASE + 0x0e4) +#define A2W_PLLB_DIG2 (A2W_BASE + 0x0e8) +#define A2W_PLLB_DIG3 (A2W_BASE + 0x0ec) + +#define A2W_PLLB_ANA1 (A2W_BASE + 0x0f4) +#define A2W_PLLB_ANA2 (A2W_BASE + 0x0f8) +#define A2W_PLLB_ANA3 (A2W_BASE + 0x0fc) +#define CM_PLLB_ANARST_SET 0x00000100 +#define CM_PLLB_DIGRST_SET 0x00000200 +#define A2W_PLLB_ANA_MULTI (A2W_BASE + 0xff0) + #define A2W_PLL_ANA3_KA_LSB 7 #define A2W_PLL_ANA3_KA_MASK (BIT_MASK(3) << A2W_PLL_ANA3_KA_LSB) #define A2W_PLL_ANA1_KI_LSB 19 diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index ccc23fbb88..262c8ac498 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -134,7 +134,9 @@ static void switch_vpu_to_pllc() { int core0_div = 4; int per_div = 4; - setup_pllc( 1728LL * 1000 * 1000, core0_div, per_div); + const uint64_t pllc_mhz = 108 * per_div * 4; + + setup_pllc( pllc_mhz * 1000 * 1000, core0_div, per_div); int vpu_divisor = 1; diff --git a/platform/bcm28xx/pll/pll_control.c b/platform/bcm28xx/pll/pll_control.c index ecc31c3a5d..ef6e913d25 100644 --- a/platform/bcm28xx/pll/pll_control.c +++ b/platform/bcm28xx/pll/pll_control.c @@ -30,6 +30,7 @@ const struct pll_def pll_def[] = { .ana_kaip = REG32(A2W_PLLA_ANA_KAIP), .ana_vco = REG32(A2W_PLLA_ANA_VCO), }, +#endif [PLL_B] = { .name = "PLLB", .ana = REG32(A2W_PLLB_ANA0), @@ -44,6 +45,7 @@ const struct pll_def pll_def[] = { .ana_kaip = REG32(A2W_PLLB_ANA_KAIP), .ana_vco = REG32(A2W_PLLB_ANA_VCO), }, +#if 0 [PLL_C] = { .name = "PLLC", .ana = REG32(A2W_PLLC_ANA0), @@ -489,9 +491,9 @@ void switch_vpu_to_src(int src) { void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { int pdiv = 1; uint64_t xtal_in = xtal_freq; - printf("xtal_in = %d\n", xtal_in); + printf("xtal_in = %llu\n", xtal_in); uint64_t goal_freq = target_freq / 2; - printf("goal_freq = %d\n", goal_freq); + printf("goal_freq = %llu\n", goal_freq); uint64_t divisor = (goal_freq<<20) / xtal_in; int div = divisor >> 20; int frac = divisor & 0xfffff; @@ -547,6 +549,7 @@ void setup_pllc(uint64_t target_freq, int core0_div, int per_div) { CM_PLLC_HOLDCORE2_SET | CM_PLLC_HOLDCORE1_SET; + puts("waiting for lock"); while (!BIT_SET(*REG32(CM_LOCK), CM_LOCK_FLOCKC_BIT)) {} printf("ctrl: 0x%x\nfrac: 0x%x\n", *REG32(A2W_PLLC_CTRL), *REG32(A2W_PLLC_FRAC)); *REG32(A2W_PLLC_FRAC) = A2W_PASSWORD | frac; diff --git a/platform/bcm28xx/pll/pll_read.c b/platform/bcm28xx/pll/pll_read.c index 448f6812c3..1205b4ab77 100644 --- a/platform/bcm28xx/pll/pll_read.c +++ b/platform/bcm28xx/pll/pll_read.c @@ -93,6 +93,7 @@ static uint32_t dump_pll_state(enum pll pll) { uint32_t frac_value = *def->frac; dprintf(INFO, "A2W_%s_CTRL: 0x%x\n", def->name, ctrl_val); dprintf(INFO, "A2W_%s_FRAC: 0x%x\n", def->name, frac_value); + dprintf(INFO, "CM_%s: 0x%x\n", def->name, *(def->cm_pll)); uint32_t freq = get_pll_freq(pll); dprintf(INFO, "%s freq: %u\n", def->name, freq); return freq; @@ -126,6 +127,7 @@ static int cmd_pll_dump(int argc, const cmd_args *argv) { } dump_plldiv2_state("VPU", CM_VPUCTL, CM_VPUDIV); + printf("CM_LOCK: 0x%x\n", *REG32(CM_LOCK)); return 0; } diff --git a/platform/bcm28xx/power/include/platform/bcm28xx/power.h b/platform/bcm28xx/power/include/platform/bcm28xx/power.h index 9c3eaa4ccb..85b3c2b0ed 100644 --- a/platform/bcm28xx/power/include/platform/bcm28xx/power.h +++ b/platform/bcm28xx/power/include/platform/bcm28xx/power.h @@ -45,4 +45,5 @@ void power_up_image(void); void power_up_usb(void); -void power_domain_on(volatile uint32_t *reg); +void power_domain_on(volatile uint32_t *reg, uint32_t rstn); +void power_arm_start(void); diff --git a/platform/bcm28xx/power/power.c b/platform/bcm28xx/power/power.c index 627ca3f14c..6665540f00 100644 --- a/platform/bcm28xx/power/power.c +++ b/platform/bcm28xx/power/power.c @@ -5,6 +5,11 @@ #include #include +#define PM_PROC_ARMRSTN_CLR 0xffffffbf +#define PM_IMAGE_PERIRSTN_SET 0x00000040 +#define PM_IMAGE_H264RSTN_SET 0x00000080 +#define PM_IMAGE_ISPRSTN_SET 0x00000100 + static int cmd_pm_dump(int argc, const cmd_args *argv); static int cmd_pm_usb_on(int argc, const cmd_args *argv); @@ -43,7 +48,7 @@ void power_up_image(void) { *REG32(PM_IMAGE) |= PM_PASSWORD | 0x40; #endif //dumpreg(PM_IMAGE); - power_domain_on(REG32(PM_IMAGE)); + power_domain_on(REG32(PM_IMAGE), ~(PM_IMAGE_ISPRSTN_SET | PM_IMAGE_H264RSTN_SET | PM_IMAGE_PERIRSTN_SET)); //dumpreg(PM_IMAGE); } @@ -67,7 +72,8 @@ void power_up_usb(void) { *REG32(CM_PERIICTL) |= CM_PASSWORD | 0x40; } -void power_domain_on(volatile uint32_t *reg) { +void power_domain_on(volatile uint32_t *reg, uint32_t rstn) { + puts("bringing domain up"); /* If it was already powered on by the fw, leave it that way. */ if (*REG32(reg) & PM_POWUP) { puts("already on"); @@ -76,6 +82,7 @@ void power_domain_on(volatile uint32_t *reg) { /* Enable power */ *REG32(reg) |= PM_PASSWORD | PM_POWUP; + puts("waiting"); while (!(*REG32(reg) & PM_POWOK)) { udelay(1); // TODO, add timeout } @@ -83,6 +90,7 @@ void power_domain_on(volatile uint32_t *reg) { /* Disable electrical isolation */ *REG32(reg) |= PM_PASSWORD | PM_ISPOW; + puts("mem rep"); /* Repair memory */ *REG32(reg) |= PM_PASSWORD | PM_MEMREP; while (!(*REG32(reg) & PM_MRDONE)) { @@ -92,6 +100,10 @@ void power_domain_on(volatile uint32_t *reg) { *REG32(reg) |= PM_PASSWORD | PM_ISFUNC; } +void power_arm_start(void) { + power_domain_on(REG32(PM_PROC), PM_PROC_ARMRSTN_CLR); +} + static void dump_power_domain(const char *name, uint32_t pmreg) { volatile uint32_t *reg = REG32(pmreg); uint32_t v = *reg; diff --git a/platform/bcm28xx/vec/vec.c b/platform/bcm28xx/vec/vec.c index 1782cafdcf..206fd20704 100644 --- a/platform/bcm28xx/vec/vec.c +++ b/platform/bcm28xx/vec/vec.c @@ -28,14 +28,18 @@ int width; int height; int stride; +static void draw_background_grid(void) { + //hvs_add_plane(framebuffer, 0, 0, false); +} + static void vec_init(const struct app_descriptor *app) { power_up_usb(); hvs_initialize(); *REG32(CM_VECDIV) = CM_PASSWORD | 4 << 12; - *REG32(CM_VECCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0; + *REG32(CM_VECCTL) = CM_PASSWORD | CM_SRC_PLLC_CORE0; // technically its on the PER tap *REG32(CM_VECCTL) = CM_PASSWORD | CM_VECCTL_ENAB_SET | CM_SRC_PLLC_CORE0; int rate = measure_clock(29); - printf("vec rate: %d\n", rate); + printf("vec rate: %f\n", ((float)rate)/1000/1000); *REG32(VEC_WSE_RESET) = 1; *REG32(VEC_SOFT_RESET) = 1; @@ -114,7 +118,7 @@ static void vec_init(const struct app_descriptor *app) { hvs_terminate_list(); *REG32(SCALER_DISPLIST1) = list_start; - hvs_configure_channel(1, width, height); + hvs_configure_channel(1, width, height, true); logo = tga_decode(pilogo, sizeof(pilogo), GFX_FORMAT_ARGB_8888); list_start = display_slot; @@ -123,7 +127,7 @@ static void vec_init(const struct app_descriptor *app) { hvs_terminate_list(); *REG32(SCALER_DISPLIST1) = list_start; - dance_start(logo, 1); + dance_start(logo, 1, &draw_background_grid); } static void vec_entry(const struct app_descriptor *app, void *args) { diff --git a/project/rpi3-start.mk b/project/rpi3-start.mk index 8cd7630134..2ebc5d55e3 100644 --- a/project/rpi3-start.mk +++ b/project/rpi3-start.mk @@ -11,3 +11,4 @@ MODULES += \ platform/bcm28xx/otp \ platform/bcm28xx/vec \ platform/bcm28xx/hvs-dance \ + platform/bcm28xx/arm \ From 8687ab0aa215cb3b8d6ae663f2c91b45a2ab55fb Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 28 Mar 2021 18:28:35 -0300 Subject: [PATCH 097/100] dtop generating pi-logo.h --- platform/bcm28xx/hvs-dance/rules.mk | 8 -------- 1 file changed, 8 deletions(-) diff --git a/platform/bcm28xx/hvs-dance/rules.mk b/platform/bcm28xx/hvs-dance/rules.mk index 6d5f823a52..472facf336 100644 --- a/platform/bcm28xx/hvs-dance/rules.mk +++ b/platform/bcm28xx/hvs-dance/rules.mk @@ -9,14 +9,6 @@ MODULE_DEPS += \ MODULE_SRCS += \ $(LOCAL_DIR)/dance.c -$(BUILDDIR)/$(LOCAL_DIR)/pi-logo.h: $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.tga - cat $< | tools/bin2h.py --before 'uint8_t pilogo[] = {' --after '};' > $@ - -$(BUILDDIR)/$(LOCAL_DIR)/pi-logo.tga: $(LOCAL_DIR)/RPi-Logo-Reg-SCREEN.png - convert $< -compress RLE $@ - -$(BUILDDIR)/$(LOCAL_DIR)/dance.o: $(BUILDDIR)/$(LOCAL_DIR)/pi-logo.h - GLOBAL_INCLUDES += $(BUILDDIR)/$(LOCAL_DIR) MODULE_CFLAGS := -O2 From 15741ea8db9d028303e49fb2be3555ba72b9c592 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Sun, 28 Mar 2021 18:44:50 -0300 Subject: [PATCH 098/100] dont include arm in the rpi3-start project --- project/rpi3-start.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/project/rpi3-start.mk b/project/rpi3-start.mk index 2ebc5d55e3..8cd7630134 100644 --- a/project/rpi3-start.mk +++ b/project/rpi3-start.mk @@ -11,4 +11,3 @@ MODULES += \ platform/bcm28xx/otp \ platform/bcm28xx/vec \ platform/bcm28xx/hvs-dance \ - platform/bcm28xx/arm \ From 38dbc0f757adbe9eac3eb3883c97fdf3d8cfb1b2 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Mon, 29 Mar 2021 08:15:08 -0300 Subject: [PATCH 099/100] fix dpi.c --- platform/bcm28xx/dpi/dpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/bcm28xx/dpi/dpi.c b/platform/bcm28xx/dpi/dpi.c index 13d37aa52e..b633faea95 100644 --- a/platform/bcm28xx/dpi/dpi.c +++ b/platform/bcm28xx/dpi/dpi.c @@ -67,7 +67,7 @@ int cmd_dpi_start(int argc, const cmd_args *argv) { gfx_putpixel(framebuffer, x, y, (0xff<<24) | (y << 16) | (y << 8) | y); } } - hvs_configure_channel(0, width, height); + hvs_configure_channel(0, width, height, true); int list_start = display_slot; hvs_add_plane(framebuffer, 0, 0, false); From d8738f00a13c69b7e611d7e7d04c906b063f0072 Mon Sep 17 00:00:00 2001 From: Michael Bishop Date: Wed, 31 Mar 2021 20:01:26 -0300 Subject: [PATCH 100/100] remove unused code --- platform/bcm28xx/arm_control/arm.c | 60 --------------------------- platform/bcm28xx/arm_control/rules.mk | 8 ---- 2 files changed, 68 deletions(-) delete mode 100644 platform/bcm28xx/arm_control/arm.c delete mode 100644 platform/bcm28xx/arm_control/rules.mk diff --git a/platform/bcm28xx/arm_control/arm.c b/platform/bcm28xx/arm_control/arm.c deleted file mode 100644 index 792a9e3a6f..0000000000 --- a/platform/bcm28xx/arm_control/arm.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include - -#define ARM_MEMORY_BASE 0xC0000000 -#define VC4_PERIPH_BASE 0x7E000000 -#define ARM_PERIPH_BASE 0x3F000000 - -#define ARM_BASE 0x7E00B000 -#define ARM_CONTROL0 ARM_BASE+0x000 -#define ARM_C0_SIZ1G 0x00000003 -#define ARM_C0_FULLPERI 0x00000040 -#define ARM_C0_APROTPASS 0x0000A000 // Translate 1:1 -#define ARM_IRQ_ENBL3 ARM_BASE+0x218 // ARM irqs enable bits -#define ARM_IE_MAIL 0x00000002 // Mail IRQ -#define ARM_CONTROL1 ARM_BASE+0x440 -#define ARM_C1_PERSON 0x00000100 // peripherals on -#define ARM_TRANSLATE ARM_BASE+0x100 -#define ARM_ID ARM_BASE+0x44C - -static int cmd_test_arm(int argc, const cmd_args *argv); - -STATIC_COMMAND_START -STATIC_COMMAND("arm", "arm the arm!", &cmd_test_arm) -STATIC_COMMAND_END(arm); - -// maps a 16mb chunk of ram -// the bus address has a resolution of 2mb -// the arm addr has a resolution of 16mb -// the entire mapping is 16mb long -// comments say there are 32 slots in the list (512mb mapped) an another 32 spare (1gig mapped) -void mapBusToArm(uint32_t busAddr, uint32_t armAddr) { - volatile uint32_t* tte = REG32(ARM_TRANSLATE); - - uint32_t index = armAddr >> 24; // div by 16mb - uint32_t pte = busAddr >> 21; // div by 2mb - //printf("mapBusToArm index:%x, pte:%x\n", index, pte); - - tte[index] = pte; -} - -static int cmd_test_arm(int argc, const cmd_args *argv) { - for (uint32_t i = 0; i < 62; i++) { - uint32_t offset = i * 0x1000000; - mapBusToArm(ARM_MEMORY_BASE + offset, 0x0 + offset); - } - mapBusToArm(VC4_PERIPH_BASE, ARM_PERIPH_BASE); - - printf("ARM ID: 0x%X C0: 0x%X\n", *REG32(ARM_ID), *REG32(ARM_CONTROL0)); - - /* - * enable peripheral access, map arm secure bits to axi secure bits 1:1 and - * set the mem size for who knows what reason. - */ - *REG32(ARM_CONTROL0) |= 0x008 | ARM_C0_APROTPASS | ARM_C0_SIZ1G | ARM_C0_FULLPERI; // | ARM_C0_AARCH64; - *REG32(ARM_CONTROL1) |= ARM_C1_PERSON; - - *REG32(ARM_IRQ_ENBL3) |= ARM_IE_MAIL; - return 0; -} diff --git a/platform/bcm28xx/arm_control/rules.mk b/platform/bcm28xx/arm_control/rules.mk deleted file mode 100644 index 29a24a6c23..0000000000 --- a/platform/bcm28xx/arm_control/rules.mk +++ /dev/null @@ -1,8 +0,0 @@ -LOCAL_DIR := $(GET_LOCAL_DIR) -MODULE := $(LOCAL_DIR) - -MODULE_SRCS += \ - $(LOCAL_DIR)/arm.c \ - - -include make/module.mk